diff -u --recursive --new-file v2.3.13/linux/CREDITS linux/CREDITS
--- v2.3.13/linux/CREDITS	Mon Aug  9 14:59:18 1999
+++ linux/CREDITS	Thu Aug 12 11:49:02 1999
@@ -176,9 +176,9 @@
 
 N: Carlos Henrique Bauer
 E: chbauer@acm.org
-E: bauer@atlas.unisinos.tche.br
-D: A test for detection of EPP-1.7 and ECP/EPP parports.
+E: bauer@atlas.unisinos.br
 D: Some new sysctl entries for the parport driver.
+D: New sysctl function for handling unsigned longs
 S: Universidade do Vale do Rio dos Sinos - UNISINOS
 S: DSI/IDASI
 S: Av. Unisinos, 950
@@ -987,10 +987,6 @@
 S: 160 00 Praha 6
 S: Czech Republic
 
-N: Andreas S. Krebs
-E: akrebs@altavista.net
-D: CYPRESS CY82C693 chipset IDE, Digital's PC-Alpha 164SX boards
-
 N: Niels Kristian Bech Jensen
 E: nkbj@image.dk
 W: http://www.image.dk/~nkbj
@@ -1001,15 +997,6 @@
 S: DK-8230 Åbyhøj
 S: Denmark
 
-N: Andrzej M. Krzysztofowicz
-E: ankry@mif.pg.gda.pl
-D: XT disk driver
-D: Aladdin 1533/1543(C) chipset IDE
-D: PIIX chipset IDE
-S: ul. Matemblewska 1B/10
-S: 80-283 Gdansk
-S: Poland
-
 N: Michael K. Johnson
 E: johnsonm@redhat.com
 W: http://www.redhat.com/~johnsonm
@@ -1024,6 +1011,29 @@
 S: Chapel Hill, North Carolina 27514-4818
 S: USA
 
+N: Dave Jones
+E: dave@powertweak.com
+W: http://linux.powertweak.com
+D: Centaur/IDT Winchip/Winchip 2 tweaks
+D: Misc clean ups and other random hacking.
+S: 40, Heol Edward Lewis,
+S: Gelligaer, Hengoed,
+S: Mid Glamorgan, CF82 8EJ,
+S: Wales, United Kingdom
+
+N: Andreas S. Krebs
+E: akrebs@altavista.net
+D: CYPRESS CY82C693 chipset IDE, Digital's PC-Alpha 164SX boards
+
+N: Andrzej M. Krzysztofowicz
+E: ankry@mif.pg.gda.pl
+D: XT disk driver
+D: Aladdin 1533/1543(C) chipset IDE
+D: PIIX chipset IDE
+S: ul. Matemblewska 1B/10
+S: 80-283 Gdansk
+S: Poland
+
 N: Bernhard Kaindl
 E: bkaindl@netway.at
 E: edv@bartelt.via.at
@@ -1293,7 +1303,7 @@
 D: SCSI Tape Driver
 
 N: Hamish Macdonald
-E: hamish_macdonald@westendsys.com
+E: hamishm@lucent.com
 D: Linux/68k port
 S: 32 Clydesdale Avenue
 S: Kanata, Ontario
diff -u --recursive --new-file v2.3.13/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.3.13/linux/Documentation/Configure.help	Mon Aug  9 14:59:18 1999
+++ linux/Documentation/Configure.help	Wed Aug 18 10:10:06 1999
@@ -1,7 +1,7 @@
 # Maintained by Axel Boldt (boldt@math.ucsb.edu)
 #
 # This version of the Linux kernel configuration help texts
-# corresponds to the kernel versions 2.2.x.
+# corresponds to the kernel versions 2.3.x.
 #
 # Translations of this file available on the WWW:
 #
@@ -2009,10 +2009,12 @@
   you have a Retina Z3 or plan to get one before you next recompile
   the kernel.
 
-Amiga CLgen driver (EXPERIMENTAL)
+Cirrus Logic generic driver (EXPERIMENTAL)
 CONFIG_FB_CLGEN
   This enables support for Cirrus Logic GD542x/543x based boards on
   Amiga: SD64, Piccolo, Picasso II/II+, Picasso IV, or EGS Spectrum.
+  If you have a PCI-based system, this enables support for these chips:
+  GD-543x, GD-544x, GD-5480.
   Say N unless you have such a graphics board or plan to get one
   before you next recompile the kernel.
 
@@ -2311,7 +2313,7 @@
 VGA characters/attributes support
 CONFIG_FBCON_VGA
   This is the low level frame buffer console driver for VGA text mode;
-  it is used if you said Y to "VGA chipset support (text only)" above.
+  it is used by frame buffer device drivers that support VGA text mode.
 
 Parallel-port support
 CONFIG_PARPORT
@@ -10262,6 +10264,20 @@
   connections. See Documentation/isdn/README.x25 for more information
   if you are thinking about using this.
 
+ISDN diversion services support
+CONFIG_ISDN_DIVERSION
+  This option allows you to use some supplementary diversion
+  services in conjunction with the HiSax driver on an EURO/DSS1
+  line. Supported options are CD (call deflection), CFU (Call 
+  forward unconditional), CFB (Call forward when busy) and CFNR 
+  (call forward not reachable).
+  Additionally the actual CFU, CFB and CFNR state may be 
+  interrogated. The use of CFU, CFB, CFNR and interrogation may
+  be limited to some countries. The keypad protocol is still not
+  implemented.
+  CD should work in all countries if this service has been sub-
+  scribed.
+
 ICN 2B and 4B support
 CONFIG_ISDN_DRV_ICN
   This enables support for two kinds of ISDN-cards made by a German
@@ -10488,6 +10504,30 @@
   you need to have access to a machine on the Internet that has a
   program like lynx or netscape).
 
+Eicon.Diehl active card support
+CONFIG_ISDN_DRV_EICON
+  Say Y here if you have an Eicon active ISDN card. In order to use
+  this card, additional firmware is necessary, which has to be loaded
+  into the card using the eiconctrl utility which is part of the latest
+  isdn4k-utils package. Please read the file
+  Documentation/isdn/README.eicon for more information.
+  
+Eicon old-type card support
+CONFIG_ISDN_DRV_EICON_ISA
+  Say Y here if you have an old-type Eicon active ISDN card. In order to
+  use this card, additional firmware is necessary, which has to be loaded
+  into the card using the eiconctrl utility which is part of the latest
+  isdn4k-utils package. Please read the file
+  Documentation/isdn/README.eicon for more information.
+
+Support AT-Fax Class 2 commands
+CONFIG_ISDN_TTY_FAX
+  If you say Y here, the modem-emulator will support a subset of the
+  Fax Class 2 commands. Using a getty with fax-support
+  (mgetty+sendfax, hylafax), you will be able to use your Linux box 
+  as an ISDN-fax-machine. This must be supported by the lowlevel driver
+  also. See Documentation/isdn/README.fax for more information.
+
 AVM-B1 with CAPI2.0 support
 CONFIG_ISDN_DRV_AVMB1
   This enables support for the AVM B1 ISDN networking cards. In
@@ -10625,6 +10665,33 @@
   If you anticipate running this kernel on a computer with a MC68060
   processor, say Y. Otherwise, say N.
 
+Math emulation support
+CONFIG_M68KFPU_EMU
+  At some point in the future, this will cause floating-point math
+  instructions to be emulated by the kernel on machines that lack a
+  floating-point math coprocessor.  Thrill-seekers and chronically
+  sleep-deprived psychotic hacker types can say Y now, everyone else
+  should probably wait a while.
+
+Math emulation only kernel
+CONFIG_M68KFPU_EMU_ONLY
+  This option prevents any floating-point instructions from being
+  compiled into the kernel, thereby the kernel doesn't save any
+  floating point context anymore during task switches, so this
+  kernel will only be usable on machines without a floating-point
+  math coprocessor. This makes the kernel a bit faster as no tests
+  needs to be executed whether a floating-point instruction in the
+  kernel should be executed or not.
+
+Math emulation extra precision
+CONFIG_M68KFPU_EMU_EXTRAPREC
+  The fpu uses normally a few bit more during calculations for
+  correct rounding, the emulator can (often) do the same but this
+  extra calculation can cost quite some time, so you can disable
+  it here. The emulator will then "only" calculate with a 64 bit
+  mantissa and round slightly incorrect, what is more then enough
+  for normal usage.
+
 Advanced processor options
 CONFIG_ADVANCED_CPU
   This gives you access to some advanced options for the CPU. The
@@ -11968,10 +12035,29 @@
   mknod /dev/ttyACM2 c 166 2
   mknod /dev/ttyACM3 c 166 3
 
+USB Printer Device Class support (Preliminary)
+CONFIG_USB_PRINTER
+  This is a generic driver for USB printers.
+
 USS720 parport driver
 CONFIG_USB_USS720
-  This driver is for USB parallel port adapters that use the USS-720
-  chip.
+  This driver is for USB parallel port adapters that use the 
+  Lucent Technologies USS-720 chip.
+  
+  The chip has two modes: automatic mode and manual mode.
+  In automatic mode, it looks like a standard USB printer. Only
+  Printers may be connected to the USS-720 in this mode.
+  The generic USB printer driver (CONFIG_USB_PRINTER, above)
+  may be used in that mode.
+
+  Manual mode is not limited to printers, any parallel port
+  device should work. This driver utilizes manual mode.
+  Note however that some operations are three orders of a magnitude
+  slower than on a PCI/ISA Parallel Port, so timing critical
+  applications might not work.
+
+  Say Y or M if you own an USS-720 USB->Parport cable and
+  intend to connect anything other than a printer to it. 
 
 USB /proc filesystem entry support (Preliminary)
 CONFIG_USB_PROC
@@ -11991,6 +12077,21 @@
   This is the parallel port equivalent of SCSI generic support (sg).
   It is safe to say N to this -- it is not needed for normal printing
   or parallel port CD-ROM/disk support.
+
+Kernel httpd acceleration (expirimental)
+CONFIG_KHTTPD
+  The kernel httpd acceleration daemon (kHTTPd) is a (limited) 
+  webserver build into the kernel. It is limited since it can only
+  serve files from the filesystem. Saying "M" here builds the
+  kHTTPd module; this is NOT enough to have a working kHTTPd. 
+  For safety reasons, the module has to be activated by doing a
+  "echo 1 > /proc/sys/net/khttpd/start" after inserting the module.
+
+  Before using this, read the README in /usr/src/linux/net/khttpd !
+
+  The kHTTPd is expirimental. Be careful when using it on a production
+  machine. Also note that kHTTPd doesn't support virtual servers yet.
+
 
 #
 # A couple of things I keep forgetting:
diff -u --recursive --new-file v2.3.13/linux/Documentation/fb/clgenfb.txt linux/Documentation/fb/clgenfb.txt
--- v2.3.13/linux/Documentation/fb/clgenfb.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/fb/clgenfb.txt	Wed Aug 18 10:10:06 1999
@@ -0,0 +1,59 @@
+
+		Framebuffer driver for Cirrus Logic chipsets
+		Copyright 1999 Jeff Garzik <jgarzik@pobox.com>
+
+
+
+{ just a little something to get people going; contributors welcome! }
+
+
+
+Chip families supported:
+	SD64
+	Piccolo
+	Picasso
+	Spectrum
+	Picasso4 (GD-5446)
+	Alpine (GD-543x/4x)
+	GD-5480
+
+Bus's supported:
+	PCI
+	Zorro
+
+Architectures supported:
+	i386
+	Alpha
+	PPC (Motorola Powerstack)
+	m68k (Amiga)
+
+
+
+Default video modes
+-------------------
+At the moment, there are two kernel command line arguments supported:
+
+mode:640x480
+	or
+mode:1024x768
+
+Full support for startup video modes (modedb) will be integrated soon.
+
+
+
+Version 1.9.4.1
+---------------
+Add compatibility support.  Now requires a 2.1.x, 2.2.x or 2.3.x kernel.
+
+
+Version 1.9.4
+-------------
+Several enhancements, smaller memory footprint, a few bugfixes.
+Requires kernel 2.3.14-pre1 or later.
+
+
+Version 1.9.3
+-------------
+Bundled with kernel 2.3.14-pre1 or later.
+
+
diff -u --recursive --new-file v2.3.13/linux/Documentation/fb/modedb.txt linux/Documentation/fb/modedb.txt
--- v2.3.13/linux/Documentation/fb/modedb.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/fb/modedb.txt	Wed Aug 18 10:10:06 1999
@@ -0,0 +1,48 @@
+
+
+			modedb default video mode support
+
+
+Currently all frame buffer device drivers have their own video mode databases,
+which is a mess and a waste of resources. The main idea of modedb is to have
+
+  - one routine to probe for video modes, which can be used by all frame buffer
+    devices
+  - one generic video mode database with a fair amount of standard videomodes
+    (taken from XFree86)
+  - the possibility to supply your own mode database for graphics hardware that
+    needs non-standard modes, like amifb and Mac frame buffer drivers (which
+    use macmodes.c)
+
+When a frame buffer device receives a video= option it doesn't know, it should
+consider that to be a video mode option. If no frame buffer device is specified
+in a video= option, fbmem considers that to be a global video mode option.
+
+Valid mode specifiers (mode_option argument):
+
+    <xres>x<yres>[-<bpp>][@<refresh>]
+    <name>[-<bpp>][@<refresh>]
+
+with <xres>, <yres>, <bpp> and <refresh> decimal numbers and <name> a string.
+Things between square brackets are optional.
+
+To find a suitable video mode, you just call
+
+int __init fb_find_mode(struct fb_var_screeninfo *var,
+                        struct fb_info *info, const char *mode_option,
+                        const struct fb_videomode *db, unsigned int dbsize,
+                        const struct fb_videomode *default_mode,
+                        unsigned int default_bpp)
+
+with db/dbsize your non-standard video mode database, or NULL to use the
+standard video mode database.
+
+fb_find_mode() first tries the specified video mode (or any mode that matches,
+e.g. there can be multiple 640x480 modes, each of them is tried). If that
+fails, the default mode is tried. If that fails, it walks over all modes.
+
+BTW, only a few drivers use this at the moment. Others are to follow
+(feel free to send patches).
+
+
+
diff -u --recursive --new-file v2.3.13/linux/Documentation/isapnp.txt linux/Documentation/isapnp.txt
--- v2.3.13/linux/Documentation/isapnp.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/isapnp.txt	Sun Aug 15 11:50:35 1999
@@ -0,0 +1,147 @@
+ISA Plug & Play support by Jaroslav Kysela <perex@suse.cz>
+=========================================================
+
+Interface /proc/isapnp
+======================
+
+Read commands:
+--------------
+
+No comment..
+
+Write commands:
+---------------
+
+With the write interface you can simply activate or modify the configuration
+for ISA Plug & Play devices. It is mainly useable for drivers which don't
+use the ISA Plug & Play kernel support yet.
+
+card <idx> <vendor>	- select PnP device by vendor identification
+csn <CSN>		- select PnP device by CSN
+dev <idx> <logdev>	- select logical device
+auto			- run autoconfigure
+activate		- activate logical device
+deactivate		- deactivate logical device
+port <idx> <value>	- set port 0-7 to value
+irq <idx> <value>	- set IRQ 0-1 to value
+dma <idx> <value>	- set DMA 0-1 to value
+memory <idx> <value>	- set memory 0-3 to value
+poke <reg> <value>	- poke configuration byte to selected register
+pokew <reg> <value>	- poke configuration word to selected register
+poked <reg> <value>	- poke configuration dword to selected register
+
+Explanation:
+	- variable <idx> begins with zero
+	- variable <CSN> begins with one
+	- <vendor> is in form 'PNP0000'
+	- <logdev> is in form 'PNP0000'
+
+Example:
+
+cat > /proc/isapnp <<EOF
+card 0 CSC7537
+dev 0 CSC0000
+port 0 0x534
+port 1 0x388
+port 2 0x220
+irq 0 5
+dma 0 1
+dma 1 3
+poke 0x70 9
+activate
+logdev 0 CSC0001
+port 0 0x240
+activate
+EOF
+
+Information for developers
+==========================
+
+Finding appropriate device
+--------------------------
+
+extern struct pci_bus *isapnp_find_card(unsigned short vendor,
+                                        unsigned short device,
+                                        struct pci_bus *from);
+
+The above function finds a ISA PnP card. For the vendor device should
+be used ISAPNP_VENDOR(a,b,c) where a,b,c are characters or integers.
+For the device number should be used ISAPNP_DEVICE(x) macro where x is
+integer value. Both vendor and device numbers can be get from contents
+of the /proc/isapnp file.
+
+extern struct pci_dev *isapnp_find_dev(struct pci_bus *card,
+                                       unsigned short vendor,
+                                       unsigned short function,
+                                       struct pci_dev *from);
+
+The above function finds the ISA PnP device. If card is NULL, then
+the global search mode is used (all devices are used for the searching).
+Otherwise only devices which belongs to the specified card are verified.
+For the function number can be used ISAPNP_FUNCTION(x) macro which works
+similarly as the ISAPNP_DEVICE(x) macro.
+
+ISA PnP configuration
+=====================
+
+There are two ways how can be ISA PnP interface used.
+
+First way is lowlevel
+---------------------
+
+All ISA PNP configuration registers are accessible via lowlevel
+isapnp_cfg_(set|get)_(byte|word|dword) functions.
+
+Before any lowlevel function 
+The function isapnp_cfg_begin() must be called before any lowlevel function.
+The function isapnp_cfg_end() must be always called after configuration
+otherwise the access to the ISA PnP configuration functions will be blocked.
+
+Second way is auto-configuration
+--------------------------------
+
+These two functions gives to the driver the real power of the ISA PnP
+feature. First function dev->prepare() only initialize the resource
+members in the device structure. This structure contains all resources
+set to auto configuration values after the initialization. The driver for
+ISA PnP device may modify (or not) some resources to skip auto configuration
+for the given resource.
+
+The function isapnp_configure does:
+	- resources which have the auto configuration value are configured
+	- the auto configuration is created using ISA PnP resource map
+	- the function writes configuration to ISA PnP configuration registers
+	- the function returns to the caller actual used resources
+
+Example (game port initialization)
+==================================
+
+/*** initialization ***/
+
+	struct pci_dev *dev;
+
+	/* find the first game port, use standard PnP IDs */
+	dev = isapnp_find_dev(NULL,
+			      ISAPNP_VENDOR('P','N','P'),
+			      ISAPNP_FUNCTION(0xb02f),
+			      NULL);
+	if (!dev)
+		return -ENODEV;
+	if (dev->prepare(dev)<0)
+		return -EAGAIN;
+	if (!dev->ro) {
+		/* override resource */
+		if (user_port != USER_PORT_AUTO_VALUE)
+			dev->resource[0].start = user_port;
+	}
+	if (dev->activate(dev)<0) {
+		printk("isapnp configure failed (out of resources?)\n");
+		return -ENOMEM;
+	}
+	user_port = dev->resource[0].start;		/* get real port */
+
+/*** deactivation ***/
+
+	/* to deactivate use: */
+ 	if (dev)
+ 		dev->deactivate(dev);
diff -u --recursive --new-file v2.3.13/linux/Documentation/isdn/CREDITS linux/Documentation/isdn/CREDITS
--- v2.3.13/linux/Documentation/isdn/CREDITS	Wed Jun  2 11:29:13 1999
+++ linux/Documentation/isdn/CREDITS	Thu Aug 12 09:42:32 1999
@@ -24,7 +24,7 @@
 Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
   For his Sync-PPP-code.
 
-Karsten Keil (isdn4@temic-ech.spacenet.de)
+Karsten Keil (keil@isdn4linux.de)
   For adding 1TR6-support to the Teles-driver.
   For the HiSax-driver.
 
diff -u --recursive --new-file v2.3.13/linux/Documentation/isdn/HiSax.cert linux/Documentation/isdn/HiSax.cert
--- v2.3.13/linux/Documentation/isdn/HiSax.cert	Sun May 23 10:03:41 1999
+++ linux/Documentation/isdn/HiSax.cert	Thu Aug 12 09:42:33 1999
@@ -14,7 +14,8 @@
 
 However, if you wish to modify the HiSax sources, please note the following:
 
-HiSax has passed the ITU approval test suite with ELSA Quickstep ISDN cards.
+HiSax has passed the ITU approval test suite with ELSA Quickstep ISDN cards
+and Eicon Technology Diva 2.01 PCI card.
 The certification is only valid for the combination of the tested software
 version and the tested hardware. Any changes to the HiSax source code may
 therefore affect the certification.
@@ -48,13 +49,14 @@
 drivers/isdn/hisax/l3_1tr6.c
 drivers/isdn/hisax/cert.c
 drivers/isdn/hisax/elsa.c
+drivers/isdn/hisax/diva.c
 
 Please send any changes, bugfixes and patches to me rather than implementing
 them directly into the HiSax sources.
 
 This does not reduce your rights granted by the GNU General Public License.
 If you wish to change the sources, go ahead; but note that then the
-certification is invalid even if you use ELSA Quickstep cards.
+certification is invalid even if you use one of the approved cards.
 
 Here are the certification registration numbers for ELSA Quickstep cards:
 German   D133361J CETECOM ICT Services GmbH 0682
@@ -68,9 +70,9 @@
 Version: 2.6.3i
 Charset: noconv
 
-iQCVAwUBNj5OKDpxHvX/mS9tAQFHuQP/WeImlqCcDZ2d132yAvRBWFULlJoSf1P/
-c1lVTeaWvsSaY5Cu9hrKhXXhPzeEaitUbcUBPXdpzFWCA5CE902lnz7AhgRC+HF1
-0qiKgkZZyc/5HKasFymR1+IWSLw30GesP3Di/ZMR3NJi8SlY9PIjx7hnEMunGSRO
-1ufPvfWWuu8=
-=nGJk
+iQCVAwUBN6xoKTpxHvX/mS9tAQF4DAP/efRWym6jvNOND1O9eaEFdP5fd2xKB3XD
+Ifh6Iv0DvARcIuxXtEjT+z3FjjQk35eo/wX4C4tpRhYQYdgCxl+iv+5DzhVDpB95
+3QS9E5m0E1eIK3t8XiQTRgb+1JPCMYUThCrakYsX25o3ndGKyDipsCTfkyR38XwC
+bUyTfcOYKAk=
+=VKyL
 -----END PGP SIGNATURE-----
diff -u --recursive --new-file v2.3.13/linux/Documentation/isdn/INTERFACE linux/Documentation/isdn/INTERFACE
--- v2.3.13/linux/Documentation/isdn/INTERFACE	Sun May 23 10:03:41 1999
+++ linux/Documentation/isdn/INTERFACE	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-$Id: INTERFACE,v 1.11 1999/03/02 12:14:51 armin Exp $
+$Id: INTERFACE,v 1.13 1999/08/11 20:30:26 armin Exp $
 
 Description of the Interface between Linklevel and Hardwarelevel
   of isdn4linux:
@@ -216,7 +216,7 @@
 
    Until now, the following commands are defined:
 
-***CHANGEI1.34: The parameter "num" has been replaced by a union "para" containing
+***CHANGEI1.34: The parameter "num" has been replaced by a union "parm" containing
                 the old "num" and a new setup_type struct used for ISDN_CMD_DIAL
                 and ISDN_STAT_ICALL callback.
 
@@ -235,7 +235,7 @@
        driver   = driver-Id.
        command  = ISDN_CMD_IOCTL
        arg      = Original ioctl-cmd - IIOCDRVCTL
-       para.num = first bytes filled with (unsigned long)arg
+       parm.num = first bytes filled with (unsigned long)arg
    
      Returnvalue:
        Depending on driver.
@@ -251,10 +251,10 @@
       command     = ISDN_CMD_DIAL
       arg         = channel-number locally to the driver. (starting with 0)
       
-      para.setup.phone  = An ASCII-String containing the number to dial.
-      para.setup.eazmsn = An ASCII-Sting containing the own EAZ or MSN.
-      para.setup.si1    = The Service-Indicator.
-      para.setup.si2    = Additional Service-Indicator.
+      parm.setup.phone  = An ASCII-String containing the number to dial.
+      parm.setup.eazmsn = An ASCII-Sting containing the own EAZ or MSN.
+      parm.setup.si1    = The Service-Indicator.
+      parm.setup.si2    = Additional Service-Indicator.
 
                     If the Line has been designed as SPV (a special german
                     feature, meaning semi-leased-line) the phone has to
@@ -272,7 +272,7 @@
       driver      = driver-Id.
       command     = ISDN_CMD_ACCEPTD
       arg         = channel-number locally to the driver. (starting with 0)
-      para        = unused.
+      parm        = unused.
 
   ISDN_CMD_ACCEPTB:
 
@@ -283,7 +283,7 @@
       driver      = driver-Id.
       command     = ISDN_CMD_ACCEPTB
       arg         = channel-number locally to the driver. (starting with 0)
-      para        = unused.
+      parm        = unused.
 
   ISDN_CMD_HANGUP:
 
@@ -295,7 +295,7 @@
       driver      = driver-Id.
       command     = ISDN_CMD_HANGUP
       arg         = channel-number locally to the driver. (starting with 0)
-      para        = unused.
+      parm        = unused.
 
   ISDN_CMD_CLREAZ:
 
@@ -306,7 +306,7 @@
       driver      = driver-Id.
       command     = ISDN_CMD_CLREAZ
       arg         = channel-number locally to the driver. (starting with 0)
-      para        = unused.
+      parm        = unused.
 
   ISDN_CMD_SETEAZ:
 
@@ -317,7 +317,7 @@
       driver      = driver-Id.
       command     = ISDN_CMD_SETEAZ
       arg         = channel-number locally to the driver. (starting with 0)
-      para.num    = ASCII-String, containing the desired EAZ's/MSN's
+      parm.num    = ASCII-String, containing the desired EAZ's/MSN's
                     (comma-separated). If an empty String is given, the
                     HL-driver should respond to ALL incoming calls,
                     regardless of the destination-address.
@@ -332,7 +332,7 @@
       driver      = driver-Id.
       command     = ISDN_CMD_GETEAZ
       arg         = channel-number locally to the driver. (starting with 0)
-      para.num    = ASCII-String, containing the current EAZ's/MSN's
+      parm.num    = ASCII-String, containing the current EAZ's/MSN's
 
   ISDN_CMD_SETSIL: (currently unused)
 
@@ -343,7 +343,7 @@
       driver      = driver-Id.
       command     = ISDN_CMD_SETSIL
       arg         = channel-number locally to the driver. (starting with 0)
-      para.num    = ASCII-String, containing the desired Service-Indicators.
+      parm.num    = ASCII-String, containing the desired Service-Indicators.
 
   ISDN_CMD_GETSIL: (currently unused)
 
@@ -354,7 +354,7 @@
       driver      = driver-Id.
       command     = ISDN_CMD_SETSIL
       arg         = channel-number locally to the driver. (starting with 0)
-      para.num    = ASCII-String, containing the current Service-Indicators.
+      parm.num    = ASCII-String, containing the current Service-Indicators.
 
   ISDN_CMD_SETL2:
 
@@ -369,7 +369,7 @@
       arg         = channel-number locally to the driver. (starting with 0)
                     logical or'ed with (protocol-Id << 8)
                     protocol-Id is one of the constants ISDN_PROTO_L2...
-      para        = unused.
+      parm        = unused.
 
   ISDN_CMD_GETL2: (currently unused)
 
@@ -380,7 +380,7 @@
       driver      = driver-Id.
       command     = ISDN_CMD_GETL2
       arg         = channel-number locally to the driver. (starting with 0)
-      para        = unused.
+      parm        = unused.
     Returnvalue:
       current protocol-Id (one of the constants ISDN_L2_PROTO)
 
@@ -397,7 +397,7 @@
       arg         = channel-number locally to the driver. (starting with 0)
                     logical or'ed with (protocol-Id << 8)
                     protocol-Id is one of the constants ISDN_PROTO_L3...
-      para        = unused.
+      parm.fax    = Pointer to T30_s fax struct. (fax usage only)
 
   ISDN_CMD_GETL2: (currently unused)
 
@@ -408,7 +408,7 @@
       driver      = driver-Id.
       command     = ISDN_CMD_GETL3
       arg         = channel-number locally to the driver. (starting with 0)
-      para        = unused.
+      parm        = unused.
     Returnvalue:
       current protocol-Id (one of the constants ISDN_L3_PROTO)
 
@@ -422,7 +422,7 @@
       driver      = driver-Id.
       command     = ISDN_CMD_LOCK
       arg         = unused.
-      para        = unused.
+      parm        = unused.
 
   ISDN_CMD_UNLOCK:
 
@@ -434,7 +434,19 @@
       driver      = driver-Id.
       command     = ISDN_CMD_UNLOCK
       arg         = unused.
-      para        = unused.
+      parm        = unused.
+
+  ISDN_CMD_FAXCMD:
+
+    With this command the HL-driver receives a fax sub-command.
+    For details refer to INTERFACE.fax
+
+    Parameter:
+      driver      = driver-Id.
+      command     = ISDN_CMD_FAXCMD
+      arg         = channel-number locally to the driver. (starting with 0)
+      parm        = unused.
+
 
 3. Description of the events to be signaled by the HL-driver to the LL.
 
@@ -456,7 +468,7 @@
       driver      = driver-Id
       command     = ISDN_STAT_STAVAIL
       arg         = length of available data.
-      para        = unused.
+      parm        = unused.
 
   ISDN_STAT_ICALL:
 
@@ -466,12 +478,12 @@
       driver            = driver-Id
       command           = ISDN_STAT_ICALL
       arg               = channel-number, locally to the driver. (starting with 0)
-      para.setup.phone  = Callernumber.
-      para.setup.eazmsn = CalledNumber.
-      para.setup.si1    = Service Indicator.
-      para.setup.si2    = Additional Service Indicator.
-      para.setup.plan   = octet 3 from Calling party number Information Element.
-      para.setup.screen = octet 3a from Calling party number Information Element.
+      parm.setup.phone  = Callernumber.
+      parm.setup.eazmsn = CalledNumber.
+      parm.setup.si1    = Service Indicator.
+      parm.setup.si2    = Additional Service Indicator.
+      parm.setup.plan   = octet 3 from Calling party number Information Element.
+      parm.setup.screen = octet 3a from Calling party number Information Element.
 
     Return:
       0           = No device matching this call.
@@ -497,7 +509,7 @@
       driver      = driver-Id
       command     = ISDN_STAT_RUN
       arg         = unused.
-      para        = unused.
+      parm        = unused.
 
   ISDN_STAT_STOP:
 
@@ -508,7 +520,7 @@
       driver      = driver-Id
       command     = ISDN_STAT_STOP
       arg         = unused.
-      para        = unused.
+      parm        = unused.
 
   ISDN_STAT_DCONN:
 
@@ -519,7 +531,7 @@
       driver      = driver-Id
       command     = ISDN_STAT_DCONN
       arg         = channel-number, locally to the driver. (starting with 0)
-      para        = unused.
+      parm        = unused.
 
   ISDN_STAT_BCONN:
 
@@ -534,7 +546,7 @@
       driver      = driver-Id
       command     = ISDN_STAT_BCONN
       arg         = channel-number, locally to the driver. (starting with 0)
-      para.num    = ASCII-String, containing type of connection (for analog
+      parm.num    = ASCII-String, containing type of connection (for analog
 		    modem only). This will be appended to the CONNECT message
 		    e.g. 14400/V.32bis
 
@@ -549,7 +561,7 @@
       driver      = driver-Id
       command     = ISDN_STAT_DHUP
       arg         = channel-number, locally to the driver. (starting with 0)
-      para        = unused.
+      parm        = unused.
 
   ISDN_STAT_BHUP:
 
@@ -564,7 +576,7 @@
       driver      = driver-Id
       command     = ISDN_STAT_BHUP
       arg         = channel-number, locally to the driver. (starting with 0)
-      para        = unused.
+      parm        = unused.
 
   ISDN_STAT_CINF:
 
@@ -575,7 +587,7 @@
       driver      = driver-Id
       command     = ISDN_STAT_CINF
       arg         = channel-number, locally to the driver. (starting with 0)
-      para.num    = ASCII string containing charge-units (digits only).
+      parm.num    = ASCII string containing charge-units (digits only).
 
   ISDN_STAT_LOAD: (currently unused)
 
@@ -588,7 +600,7 @@
       driver      = driver-Id
       command     = ISDN_STAT_UNLOAD
       arg         = unused.
-      para        = unused.
+      parm        = unused.
 
   ISDN_STAT_BSENT:
 
@@ -600,7 +612,7 @@
       driver      = driver-Id
       command     = ISDN_STAT_BSENT
       arg         = channel-number, locally to the driver. (starting with 0)
-      para.length = ***CHANGEI.1.21: New field.
+      parm.length = ***CHANGEI.1.21: New field.
 		    the driver has to set this to the original length
 		    of the skb at the time of receiving it from the linklevel.
 
@@ -613,21 +625,21 @@
       driver      = driver-Id
       command     = ISDN_STAT_NODCH
       arg         = channel-number, locally to the driver. (starting with 0)
-      para        = unused.
+      parm        = unused.
 
-  ISDN_STAT_ADDCH: (currently unused)
+  ISDN_STAT_ADDCH: 
 
-    This call is planned for HL-drivers, which are unable to check card-type
+    This call is for HL-drivers, which are unable to check card-type
     or numbers of supported channels before they have loaded any firmware
-    using ioctl. Those HL-driver simply set the channel-parameter to zero
-    or a minimum channel-number when registering, and later if they know
+    using ioctl. Those HL-driver simply set the channel-parameter to a
+    minimum channel-number when registering, and later if they know
     the real amount, perform this call, allocating additional channels.
 
     Parameter:
       driver      = driver-Id
       command     = ISDN_STAT_ADDCH
-      arg         = to be defined.
-      para        = to be defined.
+      arg         = number of channels to be added.
+      parm        = unused.
 
   ISDN_STAT_CAUSE:
 
@@ -640,7 +652,7 @@
       driver      = driver-Id
       command     = ISDN_STAT_NODCH
       arg         = channel-number, locally to the driver. (starting with 0)
-      para.num    = ASCII string containing CAUSE-message.
+      parm.num    = ASCII string containing CAUSE-message.
 
   ISDN_STAT_L1ERR:
 
@@ -653,5 +665,33 @@
       driver      = driver-Id
       command     = ISDN_STAT_L1ERR
       arg         = channel-number, locally to the driver. (starting with 0)
-      para.errcode= ISDN_STAT_L1ERR_SEND:     Packet lost while sending.
+      parm.errcode= ISDN_STAT_L1ERR_SEND:     Packet lost while sending.
 		    ISDN_STAT_L1ERR_RECV:     Packet lost while receiving.
+  ISDN_STAT_DISCH:
+
+    With this call, the HL-driver signals the LL to disable or enable the
+    use of supplied channel and driver.
+    The call may be used to reduce the available number of B-channels after
+    loading the driver. The LL has to ignore a disabled channel when searching
+    for free channels. The HL driver itself never delivers STAT callbacks for
+    disabled channels. 	    
+    The LL returns a nonzero code if the operation was not successfull or the
+    selected channel is actually regarded as busy.
+
+    Parameter:
+      driver      = driver-Id
+      command     = ISDN_STAT_DISCH
+      arg         = channel-number, locally to the driver. (starting with 0)
+      parm.num[0] = 0 if channel shall be disabled, else enabled.
+    
+  ISDN_STAT_FAXIND:
+
+    With this call the HL-driver signals a fax sub-command to the LL.
+    For details refer to INTERFACE.fax
+
+    Parameter:
+      driver      = driver-Id.
+      command     = ISDN_STAT_FAXIND
+      arg         = channel-number, locally to the driver. (starting with 0)
+      parm        = unused.
+
diff -u --recursive --new-file v2.3.13/linux/Documentation/isdn/INTERFACE.fax linux/Documentation/isdn/INTERFACE.fax
--- v2.3.13/linux/Documentation/isdn/INTERFACE.fax	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/isdn/INTERFACE.fax	Thu Aug 12 09:42:33 1999
@@ -0,0 +1,163 @@
+$Id: INTERFACE.fax,v 1.1 1999/08/11 20:30:28 armin Exp $
+
+
+Description of the fax-subinterface between linklevel and hardwarelevel of 
+  isdn4linux. 
+
+  The communication between linklevel (LL) and harwarelevel (HL) for fax
+  is based on the struct T30_s (defined in isdnif.h).
+  This struct is allocated in the LL.  
+  In order to use fax, the LL provides the pointer to this struct with the 
+  command ISDN_CMD_SETL3 (parm.fax). This pointer expires in case of hangup 
+  and when a new channel to a new connection is assigned. 
+
+
+Data handling:
+  In send-mode the HL-driver has to handle the <DLE> codes and the bit-order 
+  conversion by itself. 
+  In receive-mode the LL-driver takes care of the bit-order conversion
+  (specified by +FBOR)
+
+Structure T30_s description:
+
+  This structure stores the values (set by AT-commands), the remote-
+  capability-values and the command-codes between LL and HL.
+
+  If the HL-driver receives ISDN_CMD_FAXCMD, all needed information
+  is in this struct set by the LL.
+  To signal information to the LL, the HL-driver has to set the 
+  the parameters and use ISDN_STAT_FAXIND.
+  (Please refer to INTERFACE)
+
+Structure T30_s:
+
+  All members are 8-bit unsigned (__u8)
+
+  -  resolution     
+  -  rate
+  -  width
+  -  length
+  -  compression
+  -  ecm
+  -  binary
+  -  scantime
+  -  id[]
+  Local faxmachine's parameters, set by +FDIS, +FDCS, +FLID, ...
+
+  -  r_resolution
+  -  r_rate
+  -  r_width
+  -  r_length
+  -  r_compression
+  -  r_ecm
+  -  r_binary
+  -  r_scantime
+  -  r_id[]
+  Remote faxmachine's parameters. To be set by HL-driver.
+
+  -  phase      
+  Defines the actual state of fax connection. Set by HL or LL
+  depending on progress and type of connection.
+  If the phase changes because of an AT command, the LL driver
+  changes this value. Otherwise the HL-driver takes care of it, but
+  only neccessary on call establishment (from IDLE to PHASE_A).
+  (one of the constants ISDN_FAX_PHASE_[IDLE,A,B,C,D,E])
+
+  -  direction
+  Defines outgoing/send or incoming/receive connection.
+  (ISDN_TTY_FAX_CONN_[IN,OUT])
+
+  -  code
+  Commands from LL to HL; possible constants : 
+      ISDN_TTY_FAX_DR        signals +FDR command to HL
+
+      ISDN_TTY_FAX_DT        signals +FDT command to HL 
+
+      ISDN_TTY_FAX_ET        signals +FET command to HL
+
+
+  Other than that the "code" is set with the hangup-code value at
+  the end of connection for the +FHNG message.
+        
+  -  r_code 
+  Commands from HL to LL; possible constants :
+      ISDN_TTY_FAX_CFR       output of +FCFR message. 
+
+      ISDN_TTY_FAX_RID       output of remote ID set in r_id[]
+                             (+FCSI/+FTSI on send/receive)
+
+      ISDN_TTY_FAX_DCS       output of +FDCS and CONNECT message,
+                             switching to phase C.
+
+      ISDN_TTY_FAX_ET        signals end of data,
+                             switching to phase D.
+
+      ISDN_TTY_FAX_FCON      signals the established, outgoing connection,
+                             switching to phase B.
+
+      ISDN_TTY_FAX_FCON_I    signals the established, incoming connection,
+                             switching to phase B.
+
+      ISDN_TTY_FAX_DIS       output of +FDIS message and values.
+
+      ISDN_TTY_FAX_SENT      signals that all data has been sent 
+                             and <DLE><ETX> is acknowledged,
+                             OK message will be sent.
+
+      ISDN_TTY_FAX_PTS       signals a msg-confirmation (page sent successful),
+                             depending on fet value:
+                             0: output OK message (more pages follow)
+                             1: switching to phase B (next document)
+
+      ISDN_TTY_FAX_TRAIN_OK  output of +FDCS and OK message (for receive mode).
+
+      ISDN_TTY_FAX_EOP       signals end of data in receive mode,
+                             switching to phase D.
+
+      ISDN_TTY_FAX_HNG       output of the +FHNG and value set by code and
+                             OK message, switching to phase E.
+
+
+  -  badlin
+  Value of +FBADLIN  
+
+  -  badmul
+  Value of +FBADMUL
+
+  -  bor
+  Value of +FBOR
+
+  -  fet
+  Value of +FET command in send-mode.
+  Set by HL in receive-mode for +FET message.
+
+  -  pollid[]  
+  ID-string, set by +FCIG
+
+  -  cq
+  Value of +FCQ
+
+  -  cr
+  Value of +FCR
+
+  -  ctcrty
+  Value of +FCTCRTY
+
+  -  minsp
+  Value of +FMINSP
+
+  -  phcto
+  Value of +FPHCTO
+
+  -  rel
+  Value of +FREL
+
+  -  nbc
+  Value of +FNBC (0,1)
+  (+FNBC is not a known class 2 fax command, I added this to change the
+   automatic "best capabilities" connection in the eicon HL-driver)
+
+  
+Armin
+mac@melware.de
+
diff -u --recursive --new-file v2.3.13/linux/Documentation/isdn/README linux/Documentation/isdn/README
--- v2.3.13/linux/Documentation/isdn/README	Sun May 23 10:03:41 1999
+++ linux/Documentation/isdn/README	Thu Aug 12 09:42:33 1999
@@ -149,6 +149,8 @@
                AT&X0    BTX-mode and T.70-mode off (default)
                AT&X1    BTX-mode on. (S13.1=1, S13.5=0 S14=0, S16=7, S18=7, S19=0)
                AT&X2    T.70-mode on. (S13.1=1, S13.5=1, S14=0, S16=7, S18=7, S19=0)
+               AT+Rx    Resume a suspended call with CallID x (x = 1,2,3...)
+               AT+Sx    Suspend a call with CallID x (x = 1,2,3...)
 
            For voice-mode commands refer to README.audio
 
@@ -215,6 +217,9 @@
                                           an incoming call happened (RING) and
                                           the remote party hung up before any
                                           local ATA was given.
+			    Bit 7:    0 = Don't show display messages from net
+                                      1 = Show display messages from net
+				          (S12 Bit 1 must be 0 too)      
              14   0         Layer-2 protocol:
                                       0 = X75/LAPB with I-frames
                                       1 = X75/LAPB with UI-frames
@@ -225,8 +230,11 @@
                                       8 = V.110, 19200 baud
                                       9 = V.110, 38400 baud
                                      10 = Analog Modem (only if hardware supports this)
-             15   0         Layer-3 protocol: (at the moment always 0)
+                                     11 = Fax G3 (only if hardware supports this)
+             15   0         Layer-3 protocol:
                                       0 = transparent
+                                      1 = transparent with audio features (e.g. DSP)
+                                      2 = Fax G3 (S14 has to be set to 11)
              16   250       Send-Packet-size/16
              17   8         Window-size (not yet implemented)
              18   4         Bit coded register, Service-Octet-1 to accept,
@@ -255,6 +263,9 @@
                             Set on incoming call (during RING) to
                             octet 3a of calling party number IE (Screening info)
                             See section 4.5.10 of ITU Q.931
+             23   0         Bit coded register:
+                            Bit 0:    0 = Add CPN to RING message off
+                                      1 = Add CPN to RING message on
 
   Last but not least a (at the moment fairly primitive) device to request
   the line-status (/dev/isdninfo) is made available.
diff -u --recursive --new-file v2.3.13/linux/Documentation/isdn/README.HiSax linux/Documentation/isdn/README.HiSax
--- v2.3.13/linux/Documentation/isdn/README.HiSax	Sun May 23 10:03:41 1999
+++ linux/Documentation/isdn/README.HiSax	Thu Aug 12 09:42:33 1999
@@ -42,6 +42,7 @@
 ELSA PCMCIA
 ITK ix1-micro Rev.2
 Eicon.Diehl Diva 2.0 ISA and PCI (S0 and U interface, no PRO version)
+Eicon.Diehl Diva 2.01 ISA and PCI
 Eicon.Diehl Diva Piccola
 ASUSCOM NETWORK INC. ISDNLink 128K PC adapter (order code I-IN100-ST-D)
 Dynalink IS64PH (OEM version of ASUSCOM NETWORK INC. ISDNLink 128K adapter)
@@ -54,6 +55,13 @@
 ith Kommunikationstechnik GmbH MIC 16 ISA card
 Traverse Technologie NETjet PCI S0 card
 Dr. Neuhaus Niccy PnP/PCI
+Siemens I-Surf
+ACER P10
+HST Saphir
+Berkom Telekom A4T
+Scitel Quadro
+Gazel ISDN cards
+HFC-PCI based cards
 
 Note: PCF, PCF-Pro: up to now, only the ISDN part is supported
       PCC-8: not tested yet
@@ -165,6 +173,14 @@
    27   AVM PnP (Fritz!PnP)      irq, io  (from isapnp setup)
    27   AVM PCI (Fritz!PCI)      no parameter
    28   Sedlbauer Speed Fax+     irq, io (from isapnp setup)
+   29	Siemens I-Surf           irq, io, memory (from isapnp setup)   
+   30	ACER P10                 irq, io (from isapnp setup)   
+   31	HST Saphir               irq, io
+   32	Telekom A4T              none
+   33	Scitel Quadro		 subcontroller (4*S0, subctrl 1...4)
+   34	Gazel ISDN cards (ISA)   irq,io
+   34	Gazel ISDN cards (PCI)   none
+   35	HFC 2BDS0 PCI            none
 
 
 At the moment IRQ sharing is only possible with PCI cards. Please make sure
@@ -255,12 +271,19 @@
    22   Sedlbauer Speed Star (PCMCIA)  pa=irq, pb=io  (set with card manager)
    24   Dr. Neuhaus Niccy PnP   ONLY WORKS AS A MODULE !
    24   Dr. Neuhaus Niccy PCI   no parameter
-   25   Teles S0Box             irq, io (of the used lpt port)
-   26   AVM A1 PCMCIA (Fritz!)  irq, io (set with card manager)
+   25   Teles S0Box             pa=irq, pb=io (of the used lpt port)
+   26   AVM A1 PCMCIA (Fritz!)  pa=irq, pb=io (set with card manager)
    27   AVM PnP (Fritz!PnP)     ONLY WORKS AS A MODULE !
    27   AVM PCI (Fritz!PCI)     no parameter
    28   Sedlbauer Speed Fax+    ONLY WORKS AS A MODULE !
-
+   29	Siemens I-Surf          ONLY WORKS AS A MODULE !
+   30	ACER P10                ONLY WORKS AS A MODULE !
+   31	HST Saphir              pa=irq, pb=io
+   32	Telekom A4T             no parameter
+   33	Scitel Quadro		subcontroller (4*S0, subctrl 1...4)
+   34	Gazel ISDN cards (ISA)  pa=irq, pb=io
+   34	Gazel ISDN cards (PCI)  no parameter
+   35	HFC 2BDS0 PCI           no parameter
 
 Running the driver
 ------------------
@@ -515,8 +538,7 @@
       /sbin/hisaxctrl HiSax 5 1
 
 Remarks:
-a) If you have a CISCO don't forget to switch off the KEEP ALIVE option!
-b) Use state of the art isdn4k-utils
+a) Use state of the art isdn4k-utils
 
 Here an example script:
 #!/bin/sh
@@ -568,7 +590,7 @@
 			/sbin/isdnctrl encap isdn0s cisco-h
 		fi
 	fi
-	/sbin/isdnctrl dialmode isdn0 auto
+	/sbin/isdnctrl dialmode isdn0 manual
 	# configure tcp/ip
 	/sbin/ifconfig isdn0 ${LOCAL_IP} pointopoint ${REMOTE_IP}
 	/sbin/route add -host ${REMOTE_IP} isdn0
@@ -578,6 +600,7 @@
 	/sbin/hisaxctrl HiSax 5 1
         if [ ${I4L_LEASED_128K} = "yes" ]; then
 		# B-CHANNEL 2
+		sleep 10; /* Wait for master */
 		/sbin/hisaxctrl HiSax 5 2
 	fi
 	;;
@@ -599,4 +622,3 @@
 	exit 1
 esac
 exit 0
-
diff -u --recursive --new-file v2.3.13/linux/Documentation/isdn/README.audio linux/Documentation/isdn/README.audio
--- v2.3.13/linux/Documentation/isdn/README.audio	Sun May 23 10:03:41 1999
+++ linux/Documentation/isdn/README.audio	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-$Id: README.audio,v 1.7 1998/07/26 18:45:34 armin Exp $
+$Id: README.audio,v 1.8 1999/07/11 17:17:29 armin Exp $
 
 ISDN subsystem for Linux.
   Description of audio mode.
@@ -57,6 +57,17 @@
                                          of 0.1 second. (default 70)
         AT+VSD=?         Report possible parameters.
         AT+VSD?          Show current parameters.
+
+        AT+VDD=x,y       Set DTMF-detection parameters.
+                         Only possible if online and during this connection.
+                         Possible parameters:
+                           x = 0 ... 15  sensitivity threshold level.
+                                         (default 0 , I4L soft-decode)
+                                         (1-15 soft-decode off, hardware on)
+                           y = 0 ... 255 tone duration in units of 5ms.
+                                         Not for I4L soft decode (default 8, 40ms)
+        AT+VDD=?         Report possible parameters.
+        AT+VDD?          Show current parameters.
 
         AT+VSM=x         Select audio data format.
                          Possible parameters:
diff -u --recursive --new-file v2.3.13/linux/Documentation/isdn/README.avmb1 linux/Documentation/isdn/README.avmb1
--- v2.3.13/linux/Documentation/isdn/README.avmb1	Tue Apr 28 14:22:04 1998
+++ linux/Documentation/isdn/README.avmb1	Thu Aug 12 09:42:33 1999
@@ -1,10 +1,22 @@
+Driver for active AVM Controller.
+
 The driver provides a kernel capi2.0 Interface (kernelcapi) and
 on top of this a User-Level-CAPI2.0-interface (capi)
 and a driver to connect isdn4linux with CAPI2.0 (capidrv).
+The lowlevel interface can be used to implement a CAPI2.0
+also for passive cards since July 1999.
 
-The Author can be reached at calle@calle.in-berlin.de
-The command avmcapictrl is part of the isdn4linux-utils.
-t4-files can be found at ftp.avm.de.
+The author can be reached at calle@calle.in-berlin.de.
+The command avmcapictrl is part of the isdn4k-utils.
+t4-files can be found at ftp://ftp.avm.de/cardware/b1/linux/firmware
+
+Currently supported cards:
+	B1 ISA (all versions)
+	B1 PCI
+	T1/T1B (HEMA card)
+	M1
+	M2
+	B1 PCMCIA
 
 Installing
 ----------
@@ -26,32 +38,145 @@
 AVM GmbH provides several t4-files for the different D-channel
 protocols (b1.t4 for Euro-ISDN). Install these file in /lib/isdn.
 
-If you do not compile the driver as modules, you have to add the
-card(s) and load them after booting:
-
-avmcapictrl add 0x150 15
-avmcapictrl load /lib/isdn/b1.t4 1
-
-if you configure as modules you have two possibilities:
+if you configure as modules load the modules this way:
 
 insmod /lib/modules/current/misc/capiutil.o
-insmod /lib/modules/current/misc/kernelcapi.o portbase=0x150 irq=15
+insmod /lib/modules/current/misc/b1.o
+insmod /lib/modules/current/misc/kernelcapi.o
 insmod /lib/modules/current/misc/capidrv.o
 insmod /lib/modules/current/misc/capi.o
-avmcapictrl load /lib/isdn/b1.t4
 
-or
+if you have an B1-PCI card load the module b1pci.o
+insmod /lib/modules/current/misc/b1pci.o
+and load the firmware with
+avmcapictrl load /lib/isdn/b1.t4 1
 
-insmod /lib/modules/current/misc/capiutil.o
-insmod /lib/modules/current/misc/kernelcapi.o
-insmod /lib/modules/current/misc/capidrv.o
-insmod /lib/modules/current/misc/capi.o
+if you have an B1-ISA card load the module b1isa.o
+and add the card by calling
 avmcapictrl add 0x150 15
-avmcapictrl load /lib/isdn/b1.t4
+and load the firmware by calling
+avmcapictrl load /lib/isdn/b1.t4 1
+
+if you have an T1-ISA card load the module t1isa.o
+and add the card by calling
+avmcapictrl add 0x450 15 T1 0
+and load the firmware by calling
+avmcapictrl load /lib/isdn/t1.t4 1
+
+if you have an PCMCIA card (B1/M1/M2) load the module b1pcmcia.o
+before you insert the card.
+
+Leased Lines with B1
+--------------------
+Init card and load firmware.
+For an D64S use "FV: 1" as phone number
+For an D64S2 use "FV: 1" and "FV: 2" for multilink
+or "FV: 1,2" to use CAPI channel bundling.
+
+/proc-Interface
+-----------------
+
+/proc/capi:
+  dr-xr-xr-x   2 root     root            0 Jul  1 14:03 .
+  dr-xr-xr-x  82 root     root            0 Jun 30 19:08 ..
+  -r--r--r--   1 root     root            0 Jul  1 14:03 applications
+  -r--r--r--   1 root     root            0 Jul  1 14:03 applstats
+  -r--r--r--   1 root     root            0 Jul  1 14:03 capi20
+  -r--r--r--   1 root     root            0 Jul  1 14:03 capidrv
+  -r--r--r--   1 root     root            0 Jul  1 14:03 controller
+  -r--r--r--   1 root     root            0 Jul  1 14:03 contrstats
+  -r--r--r--   1 root     root            0 Jul  1 14:03 driver
+  -r--r--r--   1 root     root            0 Jul  1 14:03 ncci
+  -r--r--r--   1 root     root            0 Jul  1 14:03 users
+
+/proc/capi/applications:
+   applid level3cnt datablkcnt datablklen ncci-cnt recvqueuelen
+	level3cnt: capi_register parameter
+	datablkcnt: capi_register parameter
+	ncci-cnt: current number of nccis (connections)
+	recvqueuelen: number of messages on receive queue
+   for example:
+1 -2 16 2048 1 0
+2 2 7 2048 1 0
+
+/proc/capi/applstats:
+   applid recvctlmsg nrecvdatamsg nsentctlmsg nsentdatamsg
+	recvctlmsg: capi messages received without DATA_B3_IND
+	recvdatamsg: capi DATA_B3_IND received
+	sentctlmsg: capi messages sent without DATA_B3_REQ
+	sentdatamsg: capi DATA_B3_REQ sent
+   for example:
+1 2057 1699 1721 1699
+
+/proc/capi/capi20: statistics of capi.o (/dev/capi20)
+    minor nopen nrecvdropmsg nrecvctlmsg nrecvdatamsg sentctlmsg sentdatamsg
+	minor: minor device number of capi device
+	nopen: number of calls to devices open
+	nrecvdropmsg: capi messages dropped (messages in recvqueue in close)
+	nrecvctlmsg: capi messages received without DATA_B3_IND
+	nrecvdatamsg: capi DATA_B3_IND received
+	nsentctlmsg: capi messages sent without DATA_B3_REQ
+	nsentdatamsg: capi DATA_B3_REQ sent
+
+   for example:
+1 2 18 0 16 2
+
+/proc/capi/capidrv: statistics of capidrv.o (capi messages)
+    nrecvctlmsg nrecvdatamsg sentctlmsg sentdatamsg
+	nrecvctlmsg: capi messages received without DATA_B3_IND
+	nrecvdatamsg: capi DATA_B3_IND received
+	nsentctlmsg: capi messages sent without DATA_B3_REQ
+	nsentdatamsg: capi DATA_B3_REQ sent
+   for example:
+2780 2226 2256 2226
+
+/proc/capi/controller:
+   controller drivername state cardname   controllerinfo
+   for example:
+1 b1pci      running  b1pci-e000       B1 3.07-01 0xe000 19
+2 t1isa      running  t1isa-450        B1 3.07-01 0x450 11 0
+3 b1pcmcia   running  m2-150           B1 3.07-01 0x150 5
+
+/proc/capi/contrstats:
+    controller nrecvctlmsg nrecvdatamsg sentctlmsg sentdatamsg
+	nrecvctlmsg: capi messages received without DATA_B3_IND
+	nrecvdatamsg: capi DATA_B3_IND received
+	nsentctlmsg: capi messages sent without DATA_B3_REQ
+	nsentdatamsg: capi DATA_B3_REQ sent
+   for example:
+1 2845 2272 2310 2274
+2 2 0 2 0
+3 2 0 2 0
+
+/proc/capi/driver:
+   drivername ncontroller
+   for example:
+b1pci                            1
+t1isa                            1
+b1pcmcia                         1
+b1isa                            0
+
+/proc/capi/ncci:
+   apllid ncci winsize sendwindow
+   for example:
+1 0x10101 8 0
+
+/proc/capi/users: kernelmodules that use the kernelcapi.
+   name
+   for example:
+capidrv
+capi20
 
 Questions
 ---------
-Check out the FAQ (ftp.franken.de).
+Check out the FAQ (ftp.franken.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
+in the body.
+
+German documentaion and several scripts can be found at
+ftp://ftp.avm.de/cardware/b1/linux/
 
 Bugs 
 ----
diff -u --recursive --new-file v2.3.13/linux/Documentation/isdn/README.concap linux/Documentation/isdn/README.concap
--- v2.3.13/linux/Documentation/isdn/README.concap	Sun May 23 10:03:41 1999
+++ linux/Documentation/isdn/README.concap	Wed Aug 18 11:37:57 1999
@@ -118,7 +118,7 @@
 	   or when the device driver resets the interface. All services of the
 	   encapsulation protocol may be used after this*/
 	int (*restart)(struct concap_proto *cprot, 
-		       struct device *ndev,
+		       struct net_device *ndev,
 		       struct concap_device_ops *dops);
 
 	/* deactivate an encapsulation protocol instance. The encapsulation
@@ -174,7 +174,7 @@
 
 An encapsulation protocol itself is actually the
 struct concap_proto{
-	struct device *net_dev;		/* net device using our service  */
+	struct net_device *net_dev;		/* net device using our service  */
 	struct concap_device_ops *dops; /* callbacks provided by device */
  	struct concap_proto_ops  *pops; /* callbacks provided by us */
 	int flags;
@@ -199,7 +199,7 @@
 encapsulation services could look like this:
 
 struct concap_device{
-	struct device net_dev;
+	struct net_device net_dev;
 	struct my_priv  /* device->local stuff */
 			/* the my_priv struct might contain a 
 			   struct concap_device_ops *dops;
@@ -225,9 +225,9 @@
 
 
 If general linux network interfaces explicitly supported concap
-protocols (e.g. by a member struct concap_proto* in struct device)
+protocols (e.g. by a member struct concap_proto* in struct net_device)
 then the interface of the service function could be changed
-by passing a pointer of type (struct device*) instead of
+by passing a pointer of type (struct net_device*) instead of
 type (struct concap_proto*). Doing so would make many of the service
 functions compatible to network device support functions.
 
@@ -237,7 +237,7 @@
 
 we could have
 
-  int (*encap_and_xmit)(struct device *ndev, struct sk_buff *skb);
+  int (*encap_and_xmit)(struct net_device *ndev, struct sk_buff *skb);
 
 As this is compatible to the dev->hard_start_xmit() method, the device
 driver could directly register the concap protocol's encap_and_xmit()
@@ -247,7 +247,7 @@
 
 The device's data request function could also be defined as
  
-  int (*data_req)(struct device *ndev, struct sk_buff *skb);
+  int (*data_req)(struct net_device *ndev, struct sk_buff *skb);
 
 This might even allow for some protocol stacking. And the network
 interface might even register the same data_req() function directly
diff -u --recursive --new-file v2.3.13/linux/Documentation/isdn/README.diversion linux/Documentation/isdn/README.diversion
--- v2.3.13/linux/Documentation/isdn/README.diversion	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/isdn/README.diversion	Thu Aug 12 09:42:33 1999
@@ -0,0 +1,127 @@
+The isdn diversion services are a supporting module working together with
+the isdn4linux and the HiSax module for passive cards. 
+Active cards, TAs and cards using a own or other driver than the HiSax 
+module need to be adapted to the HL<->LL interface described in a separate 
+document. The diversion services may be used with all cards supported by 
+the HiSax driver.
+The diversion kernel interface and controlling tool divertctrl were written
+by Werner Cornelius (werner@isdn4linux.de or werner@titro.de) under the
+GNU Public License.
+
+    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.
+
+Table of contents
+=================
+
+1. Features of the i4l diversion services 
+   (Or what can the i4l diversion services do for me)
+
+2. Required hard- and software
+
+3. Compiling, installing and loading/unloading the module  
+   Tracing calling and diversion information 
+
+4. Tracing calling and diversion information
+ 
+5. Format of the divert device ASCII output
+ 
+
+1. Features of the i4l diversion services 
+   (Or what can the i4l diversion services do for me)
+
+   The i4l diversion services offers call forwarding and logging normally 
+   only supported by isdn phones. Incoming calls may be diverted 
+   unconditionally (CFU), when not reachable (CFNR) or on busy condition 
+   (CFB). 
+   The diversions may be invoked statically in the providers exchange
+   as normally done by isdn phones. In this case all incoming calls
+   with a special (or all) service identifiers are forwarded if the 
+   forwarding reason is met. Activated static services may also be 
+   interrogated (queried).
+   The i4l diversion services additionally offers a dynamic version of
+   call forwarding which is not preprogrammed inside the providers exchange
+   but dynamically activated by i4l.
+   In this case all incoming calls are checked by rules that may be
+   compared to the mechanism of ipfwadm or ipchains. If a given rule matches
+   the checking process is finished and the rule matching will be applied
+   to the call.
+   The rules include primary and secondary service indentifiers, called 
+   number and subaddress, callers number and subaddress and whether the rule
+   matches to all filtered calls or only those when all B-channel resources
+   are exhausted.
+   Actions that may be invoked by a rule are ignore, proceed, reject, 
+   direct divert or delayed divert of a call.
+   All incoming calls matching a rule except the ignore rule a reported and
+   logged as ASCII via the proc filesystem (/proc/net/isdn/divert). If proceed
+   is selected the call will be held in a proceeding state (without ringing)
+   for a certain amount of time to let an external program or client decide
+   how to handle the call. 
+            
+
+2. Required hard- and software
+   
+   For using the i4l diversion services the isdn line must be of a EURO/DSS1
+   type. Additionally the i4l services only work together with the HiSax 
+   driver for passive isdn cards. All HiSax supported cards may be used for
+   the diversion purposes.
+   The static diversion services require the provider having static services
+   CFU, CFNR, CFB activated on an MSN-line. The static services may not be 
+   used on a point-to-point connection. Further the static services are only
+   available in some countries (for example germany). Countries requiring the 
+   keypad protocol for activating static diversions (like the netherlands) are
+   not supported but may use the tty devices for this purpose.
+   The dynamic diversion servives may be used in all countries if the provider
+   enables the feature CF (call forwarding). This should work on both MSN- and
+   point-to-point lines.
+   To add and delete rules the additional divertctrl program is needed. This
+   program is part of the isdn4kutils package.   
+
+3. Compiling, installing and loading/unloading the module  
+   Tracing calling and diversion information 
+
+
+   To compile the i4l code with diversion support you need to say yes to the 
+   DSS1 diversion services when selecting the i4l options in the kernel 
+   config (menuconfig or config).
+   After having properly activated a make modules and make modules_install all
+   required modules will be correctly installed in the needed modules dirs.
+   As the diversion services are currently not included in the scripts of most
+   standard distributions you will have to add a "insmod dss1_divert" after
+   having loaded the global isdn module.
+   The module can be loaded without any command line parameters.
+   If the module is actually loaded and active may be checked with a 
+   "cat /proc/modules" or "ls /proc/net/isdn/divert". The divert file is 
+   dynamically created by the diversion module and removed when the module is
+   unloaded.
+
+
+4. Tracing calling and diversion information
+ 
+   You also may put a "cat /proc/net/isdn/divert" in the background with the
+   output redirected to a file. Then all actions of the module are logged.
+   The divert file in the proc system may be opened more than once, so in 
+   conjunction with inetd and a small remote client on other machines inside
+   your network incoming calls and reactions by the module may be shown on 
+   every listening machine. 
+   If a call is reported as proceeding an external program or client may 
+   specify during a certain amount of time (normally 4 to 10 seconds) what
+   to do with that call.      
+   To unload the module all open files to the device in the proc system must
+   be closed. Otherwise the module (and isdn.o) may not be unloaded. 
+
+5. Format of the divert device ASCII output
+ 
+   To be done later
+
diff -u --recursive --new-file v2.3.13/linux/Documentation/isdn/README.eicon linux/Documentation/isdn/README.eicon
--- v2.3.13/linux/Documentation/isdn/README.eicon	Sun May 23 10:03:41 1999
+++ linux/Documentation/isdn/README.eicon	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-$Id: README.eicon,v 1.3 1999/03/29 11:10:04 armin Exp $
+$Id: README.eicon,v 1.4 1999/07/11 17:17:30 armin Exp $
 
 (c) 1999 Cytronics & Melware
 
@@ -21,11 +21,7 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-NOTE : Since the eicon driver is still experimental, this README file
-       may be incomplete and not up to date.
 
-
-However, the driver should work under following conditions :
 
 Supported Cards
 ---------------
diff -u --recursive --new-file v2.3.13/linux/Documentation/isdn/README.fax linux/Documentation/isdn/README.fax
--- v2.3.13/linux/Documentation/isdn/README.fax	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/isdn/README.fax	Thu Aug 12 09:42:33 1999
@@ -0,0 +1,38 @@
+
+Fax with isdn4linux
+===================
+
+When enabled during kernel configuration, the tty emulator
+of the ISDN subsystem is capable of the Fax Class 2 commands.
+
+This only makes sense under the following conditions :
+
+- You need the commands as dummy, because you are using
+  hylafax (with patch) for AVM capi.
+- You want to use the fax capabillities of your isdn-card.
+  (supported cards are listed below)
+
+
+NOTE: This implementation does *not* support fax with passive
+      ISDN-cards (known as softfax). The low-level driver of
+      the ISDN-card and/or the card itself must support this.
+
+
+Supported ISDN-Cards
+--------------------
+
+Eicon DIVA Server BRI/PCI (will be ready soon)
+Eicon DIVA Server PRI/PCI (will be ready soon)
+
+
+
+The command set is known as Class 2 (not Class 2.0) and
+can be activated by AT+FCLASS=2
+
+
+The interface between the link-level-module and the hardware-level driver
+is described in the files INTERFACE.fax and INTERFACE.
+
+Armin
+mac@melware.de
+
diff -u --recursive --new-file v2.3.13/linux/Documentation/isdn/README.hfc-pci linux/Documentation/isdn/README.hfc-pci
--- v2.3.13/linux/Documentation/isdn/README.hfc-pci	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/isdn/README.hfc-pci	Thu Aug 12 09:42:33 1999
@@ -0,0 +1,26 @@
+The driver for the HFC-PCI and HFC-PCI-A chips from CCD may be used
+for many OEM cards using this chips.
+Additionally the driver has a special feature which makes it possible
+to read the echo-channel of the isdn bus. So all frames in both directions
+may be logged.
+When the echo logging feature is used the number of available B-channels
+for a HFC-PCI card is reduced to 1. Of course this is only relevant to
+the card, not to the isdn line.
+To activate the echo mode the following ioctls must be entered:
+
+hisaxctrl <driver/cardname> 10 1
+
+This reduces the available channels to 1. There must not be open connections
+through this card when entering the command.
+And then:
+
+hisaxctrl <driver/cardname> 12 1
+
+This enables the echo mode. If Hex logging is activated the isdnctrlx 
+devices show a output with a line beginning of HEX: for the providers
+exchange and ECHO: for isdn devices sending to the provider.
+
+Comments and reports to werner@isdn4linux.de or werner@titro.de .
+
+
+
diff -u --recursive --new-file v2.3.13/linux/Documentation/mca.txt linux/Documentation/mca.txt
--- v2.3.13/linux/Documentation/mca.txt	Sun Nov  8 13:29:31 1998
+++ linux/Documentation/mca.txt	Wed Aug 18 11:37:51 1999
@@ -19,7 +19,7 @@
 	#include <linux/mca.h>
 
 	unsigned char pos2, pos3, pos4, pos5;
-	struct device* dev;
+	struct net_device* dev;
 	int slot;
 
 	if( MCA_bus ) {
@@ -114,7 +114,7 @@
 
 	static int
 	dev_getinfo( char* buf, int slot, void* d ) {
-		struct device* dev = (struct device*) d;
+		struct net_device* dev = (struct net_device*) d;
 		int len = 0;
 
 		len += sprintf( buf+len, "Device: %s\n", dev->name );
diff -u --recursive --new-file v2.3.13/linux/Documentation/networking/cs89x0.txt linux/Documentation/networking/cs89x0.txt
--- v2.3.13/linux/Documentation/networking/cs89x0.txt	Thu Jul  8 15:42:19 1999
+++ linux/Documentation/networking/cs89x0.txt	Wed Aug 18 11:37:57 1999
@@ -323,20 +323,20 @@
 
 d.) In /linux/drivers/net/Space.c file, add the line:
 
-extern int cs89x0_probe(struct device *dev);
+extern int cs89x0_probe(struct net_device *dev);
 
 
 Example:
 
- extern int ultra_probe(struct device *dev);
- extern int wd_probe(struct device *dev);
- extern int el2_probe(struct device *dev);
+ extern int ultra_probe(struct net_device *dev);
+ extern int wd_probe(struct net_device *dev);
+ extern int el2_probe(struct net_device *dev);
 
- extern int cs89x0_probe(struct device *dev);
+ extern int cs89x0_probe(struct net_device *dev);
 
- extern int ne_probe(struct device *dev);
- extern int hp_probe(struct device *dev);
- extern int hp_plus_probe(struct 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);
 
 
 Also add:
diff -u --recursive --new-file v2.3.13/linux/Documentation/parport.txt linux/Documentation/parport.txt
--- v2.3.13/linux/Documentation/parport.txt	Thu Jul  8 15:42:19 1999
+++ linux/Documentation/parport.txt	Thu Aug 12 10:19:59 1999
@@ -139,8 +139,7 @@
 		peripherals.  This is a port-wide setting, i.e. it
 		applies to all devices on a particular port.
 
-timeslice	The number of jiffies (FIXME: this should be in
-		milliseconds or something) that a device driver is
+timeslice	The number of miliseconds that a device driver is
 		allowed to keep a port claimed for.  This is advisory,
 		and driver can ignore it if it must.
 
diff -u --recursive --new-file v2.3.13/linux/MAINTAINERS linux/MAINTAINERS
--- v2.3.13/linux/MAINTAINERS	Mon Aug  9 14:59:19 1999
+++ linux/MAINTAINERS	Sun Aug 15 11:50:35 1999
@@ -377,7 +377,7 @@
 
 HP100:	Driver for HP 10/100 Mbit/s Voice Grade Network Adapter Series
 P:	Jaroslav Kysela
-M:	perex@jcu.cz
+M:	perex@suse.cz
 S:	Maintained
 
 IBM MCA SCSI SUBSYSTEM DRIVER
@@ -433,6 +433,11 @@
 L:      linux-irda@list.uit.no
 W:      http://www.cs.uit.no/linux-irda/
 S:      Maintained
+
+ISAPNP
+P:	Jaroslav Kysela
+M:	perex@suse.cz
+S:	Maintained
 
 ISDN SUBSYSTEM
 P:	Fritz Elfert
diff -u --recursive --new-file v2.3.13/linux/Makefile linux/Makefile
--- v2.3.13/linux/Makefile	Mon Aug  9 14:59:19 1999
+++ linux/Makefile	Wed Aug 18 09:45:10 1999
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 3
-SUBLEVEL = 13
+SUBLEVEL = 14
 EXTRAVERSION =
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
@@ -111,6 +111,7 @@
 NETWORKS	=net/network.a
 DRIVERS		=drivers/block/block.a \
 		 drivers/char/char.o \
+		 drivers/misc/misc.o \
 	         drivers/parport/parport.a
 LIBS		=$(TOPDIR)/lib/lib.a
 SUBDIRS		=kernel drivers mm fs net ipc lib
@@ -134,7 +135,7 @@
 endif
 
 ifeq ($(CONFIG_SOUND),y)
-DRIVERS := $(DRIVERS) drivers/sound/sound.a
+DRIVERS := $(DRIVERS) drivers/sound/sounddrivers.o
 endif
 
 ifdef CONFIG_PCI
@@ -178,7 +179,7 @@
 endif
 
 ifdef CONFIG_HAMRADIO
-DRIVERS := $(DRIVERS) drivers/net/hamradio/hamradio.a
+DRIVERS := $(DRIVERS) drivers/net/hamradio/hamradio.o
 endif
 
 ifeq ($(CONFIG_TC),y)
@@ -333,6 +334,7 @@
 	if [ -f VIDEO_MODULES ]; then inst_mod VIDEO_MODULES video; fi; \
 	if [ -f FC4_MODULES   ]; then inst_mod FC4_MODULES   fc4;   fi; \
 	if [ -f IRDA_MODULES  ]; then inst_mod IRDA_MODULES  net;   fi; \
+	if [ -f USB_MODULES   ]; then inst_mod USB_MODULES   usb;   fi; \
 	\
 	ls *.o > $$MODLIB/.allmods; \
 	echo $$MODULES | tr ' ' '\n' | sort | comm -23 $$MODLIB/.allmods - > $$MODLIB/.misc; \
@@ -362,6 +364,8 @@
 	rm -f drivers/char/consolemap_deftbl.c drivers/video/promcon_tbl.c
 	rm -f drivers/char/conmakehash
 	rm -f drivers/sound/bin2hex drivers/sound/hex2hex
+	rm -f net/khttpd/make_times_h
+	rm -f net/khttpd/times.h
 	if [ -d modules ]; then \
 		rm -f core `find modules/ -type f -print`; \
 	fi
diff -u --recursive --new-file v2.3.13/linux/arch/alpha/kernel/bios32.c linux/arch/alpha/kernel/bios32.c
--- v2.3.13/linux/arch/alpha/kernel/bios32.c	Mon Aug  9 14:59:19 1999
+++ linux/arch/alpha/kernel/bios32.c	Fri Aug 13 11:53:50 1999
@@ -522,7 +522,6 @@
 			   Cypress.  */
 			if (dev->vendor == PCI_VENDOR_ID_CONTAQ
 			    && dev->device == PCI_DEVICE_ID_CONTAQ_82C693
-			    && dev->class >> 8 == PCI_CLASS_BRIDGE_ISA
 			    && idx < 2) {
 				continue;
 			}
diff -u --recursive --new-file v2.3.13/linux/arch/alpha/kernel/core_apecs.c linux/arch/alpha/kernel/core_apecs.c
--- v2.3.13/linux/arch/alpha/kernel/core_apecs.c	Sun Sep  6 10:34:33 1998
+++ linux/arch/alpha/kernel/core_apecs.c	Fri Aug 13 11:53:50 1999
@@ -17,6 +17,7 @@
 
 #include <asm/system.h>
 #include <asm/ptrace.h>
+#include <asm/smp.h>
 
 #define __EXTERN_INLINE inline
 #include <asm/io.h>
@@ -35,19 +36,16 @@
  * BIOS32-style PCI interface:
  */
 
-#ifdef DEBUG
-# define DBG(args)	printk args
+#define DEBUG_CONFIG 0
+
+#if DEBUG_CONFIG
+# define DBGC(args)	printk args
 #else
-# define DBG(args)
+# define DBGC(args)
 #endif
 
 #define vuip	volatile unsigned int  *
 
-volatile unsigned int apecs_mcheck_expected = 0;
-volatile unsigned int apecs_mcheck_taken = 0;
-static unsigned int apecs_jd, apecs_jd1, apecs_jd2;
-
-
 /*
  * Given a bus, device, and function number, compute resulting
  * configuration space address and setup the APECS_HAXR2 register
@@ -96,9 +94,9 @@
 {
 	unsigned long addr;
 
-	DBG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x,"
-	     " pci_addr=0x%p, type1=0x%p)\n",
-	     bus, device_fn, where, pci_addr, type1));
+	DBGC(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x,"
+	      " pci_addr=0x%p, type1=0x%p)\n",
+	      bus, device_fn, where, pci_addr, type1));
 
 	if (bus == 0) {
 		int device = device_fn >> 3;
@@ -106,8 +104,8 @@
 		/* type 0 configuration cycle: */
 
 		if (device > 20) {
-			DBG(("mk_conf_addr: device (%d) > 20, returning -1\n",
-			     device));
+			DBGC(("mk_conf_addr: device (%d) > 20, returning -1\n",
+			      device));
 			return -1;
 		}
 
@@ -119,7 +117,7 @@
 		addr = (bus << 16) | (device_fn << 8) | (where);
 	}
 	*pci_addr = addr;
-	DBG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
+	DBGC(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
 	return 0;
 }
 
@@ -132,25 +130,25 @@
 
 	__save_and_cli(flags);	/* avoid getting hit by machine check */
 
-	DBG(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1));
+	DBGC(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1));
 
 	/* Reset status register to avoid losing errors.  */
 	stat0 = *(vuip)APECS_IOC_DCSR;
 	*(vuip)APECS_IOC_DCSR = stat0;
 	mb();
-	DBG(("conf_read: APECS DCSR was 0x%x\n", stat0));
+	DBGC(("conf_read: APECS DCSR was 0x%x\n", stat0));
 
 	/* If Type1 access, must set HAE #2. */
 	if (type1) {
 		haxr2 = *(vuip)APECS_IOC_HAXR2;
 		mb();
 		*(vuip)APECS_IOC_HAXR2 = haxr2 | 1;
-		DBG(("conf_read: TYPE1 access\n"));
+		DBGC(("conf_read: TYPE1 access\n"));
 	}
 
 	draina();
-	apecs_mcheck_expected = 1;
-	apecs_mcheck_taken = 0;
+	mcheck_expected(0) = 1;
+	mcheck_taken(0) = 0;
 	mb();
 
 	/* Access configuration space.  */
@@ -159,12 +157,12 @@
 	asm volatile("ldl %0,%1; mb; mb" : "=r"(value) : "m"(*(vuip)addr)
 		     : "$9", "$10", "$11", "$12", "$13", "$14", "memory");
 
-	if (apecs_mcheck_taken) {
-		apecs_mcheck_taken = 0;
+	if (mcheck_taken(0)) {
+		mcheck_taken(0) = 0;
 		value = 0xffffffffU;
 		mb();
 	}
-	apecs_mcheck_expected = 0;
+	mcheck_expected(0) = 0;
 	mb();
 
 #if 1
@@ -178,7 +176,7 @@
 
 	/* Now look for any errors.  */
 	stat0 = *(vuip)APECS_IOC_DCSR;
-	DBG(("conf_read: APECS DCSR after read 0x%x\n", stat0));
+	DBGC(("conf_read: APECS DCSR after read 0x%x\n", stat0));
 
 	/* Is any error bit set? */
 	if (stat0 & 0xffe0U) {
@@ -228,14 +226,14 @@
 	}
 
 	draina();
-	apecs_mcheck_expected = 1;
+	mcheck_expected(0) = 1;
 	mb();
 
 	/* Access configuration space.  */
 	*(vuip)addr = value;
 	mb();
 	mb();  /* magic */
-	apecs_mcheck_expected = 0;
+	mcheck_expected(0) = 0;
 	mb();
 
 #if 1
@@ -438,20 +436,21 @@
 	*(vuip)APECS_IOC_HAXR2 = 0; mb();
 }
 
-int
+void
 apecs_pci_clr_err(void)
 {
-	apecs_jd = *(vuip)APECS_IOC_DCSR;
-	if (apecs_jd & 0xffe0L) {
-		apecs_jd1 = *(vuip)APECS_IOC_SEAR;
-		*(vuip)APECS_IOC_DCSR = apecs_jd | 0xffe1L;
-		apecs_jd = *(vuip)APECS_IOC_DCSR;
+	unsigned int jd;
+
+	jd = *(vuip)APECS_IOC_DCSR;
+	if (jd & 0xffe0L) {
+		*(vuip)APECS_IOC_SEAR;
+		*(vuip)APECS_IOC_DCSR = jd | 0xffe1L;
 		mb();
+		*(vuip)APECS_IOC_DCSR;
 	}
 	*(vuip)APECS_IOC_TBIA = (unsigned int)APECS_IOC_TBIA;
-	apecs_jd2 = *(vuip)APECS_IOC_TBIA;
 	mb();
-	return 0;
+	*(vuip)APECS_IOC_TBIA;
 }
 
 void
@@ -461,8 +460,6 @@
 	struct el_common *mchk_header;
 	struct el_apecs_procdata *mchk_procdata;
 	struct el_apecs_sysdata_mcheck *mchk_sysdata;
-	unsigned long *ptr;
-	int i;
 
 	mchk_header = (struct el_common *)la_ptr;
 
@@ -473,66 +470,16 @@
 	mchk_sysdata = (struct el_apecs_sysdata_mcheck *)
 		(la_ptr + mchk_header->sys_offset);
 
-#ifdef DEBUG
-	printk("apecs_machine_check: vector=0x%lx la_ptr=0x%lx\n",
-	       vector, la_ptr);
-	printk("        pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
-	       regs->pc, mchk_header->size, mchk_header->proc_offset,
-	       mchk_header->sys_offset);
-	printk("apecs_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n",
-	       apecs_mcheck_expected, mchk_sysdata->epic_dcsr,
-	       mchk_sysdata->epic_pear);
-	ptr = (unsigned long *)la_ptr;
-	for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
-		printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]);
-	}
-#endif
 
-	/*
-	 * Check if machine check is due to a badaddr() and if so,
-	 * ignore the machine check.
-	 */
+	/* Clear the error before any reporting.  */
+	mb();
+	mb(); /* magic */
+	draina();
+	apecs_pci_clr_err();
+	wrmces(0x7);		/* reset machine check pending flag */
+	mb();
 
-	if (apecs_mcheck_expected
-	    && (mchk_sysdata->epic_dcsr & 0x0c00UL)) {
-		apecs_mcheck_expected = 0;
-		apecs_mcheck_taken = 1;
-		mb();
-		mb(); /* magic */
-		apecs_pci_clr_err();
-		wrmces(0x7);
-		mb();
-		draina();
-		DBG(("apecs_machine_check: EXPECTED\n"));
-	}
-	else if (vector == 0x620 || vector == 0x630) {
-		/* Disable correctable from now on.  */
-		wrmces(0x1f);
-		mb();
-		draina();
-		printk("apecs_machine_check: HW correctable (0x%lx)\n",
-		       vector);
-	}
-	else {
-		printk(KERN_CRIT "APECS machine check:\n");
-		printk(KERN_CRIT "  vector=0x%lx la_ptr=0x%lx\n",
-		       vector, la_ptr);
-		printk(KERN_CRIT
-		       "  pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
-		       regs->pc, mchk_header->size, mchk_header->proc_offset,
-		       mchk_header->sys_offset);
-		printk(KERN_CRIT "  expected %d DCSR 0x%lx PEAR 0x%lx\n",
-		       apecs_mcheck_expected, mchk_sysdata->epic_dcsr,
-		       mchk_sysdata->epic_pear);
-
-		ptr = (unsigned long *)la_ptr;
-		for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
-			printk(KERN_CRIT " +%lx %lx %lx\n",
-			       i*sizeof(long), ptr[i], ptr[i+1]);
-		}
-#if 0
-		/* doesn't work with MILO */
-		show_regs(regs);
-#endif
-	}
+	process_mcheck_info(vector, la_ptr, regs, "APECS",
+			    (mcheck_expected(0)
+			     && (mchk_sysdata->epic_dcsr & 0x0c00UL)));
 }
diff -u --recursive --new-file v2.3.13/linux/arch/alpha/kernel/core_cia.c linux/arch/alpha/kernel/core_cia.c
--- v2.3.13/linux/arch/alpha/kernel/core_cia.c	Tue Jun 22 10:46:52 1999
+++ linux/arch/alpha/kernel/core_cia.c	Fri Aug 13 11:53:50 1999
@@ -31,30 +31,12 @@
  */
 
 /*
- * Machine check reasons.  Defined according to PALcode sources
- * (osf.h and platform.h).
- */
-#define MCHK_K_TPERR		0x0080
-#define MCHK_K_TCPERR		0x0082
-#define MCHK_K_HERR		0x0084
-#define MCHK_K_ECC_C		0x0086
-#define MCHK_K_ECC_NC		0x0088
-#define MCHK_K_OS_BUGCHECK	0x008A
-#define MCHK_K_PAL_BUGCHECK	0x0090
-
-/*
  * BIOS32-style PCI interface:
  */
 
-#define DEBUG_MCHECK 0
 #define DEBUG_CONFIG 0
-/* #define DEBUG_DUMP_REGS */
+#define DEBUG_DUMP_REGS 0
 
-#if DEBUG_MCHECK
-# define DBGM(args)	printk args
-#else
-# define DBGM(args)
-#endif
 #if DEBUG_CONFIG
 # define DBGC(args)	printk args
 #else
@@ -63,11 +45,6 @@
 
 #define vuip	volatile unsigned int  *
 
-static volatile unsigned int CIA_mcheck_expected = 0;
-static volatile unsigned int CIA_mcheck_taken = 0;
-static unsigned int CIA_jd;
-
-
 /*
  * Given a bus, device, and function number, compute resulting
  * configuration space address and setup the CIA_HAXR2 register
@@ -173,20 +150,20 @@
 
 	mb();
 	draina();
-	CIA_mcheck_expected = 1;
-	CIA_mcheck_taken = 0;
+	mcheck_expected(0) = 1;
+	mcheck_taken(0) = 0;
 	mb();
 
 	/* Access configuration space.  */
 	value = *(vuip)addr;
 	mb();
 	mb();  /* magic */
-	if (CIA_mcheck_taken) {
-		CIA_mcheck_taken = 0;
+	if (mcheck_taken(0)) {
+		mcheck_taken(0) = 0;
 		value = 0xffffffffU;
 		mb();
 	}
-	CIA_mcheck_expected = 0;
+	mcheck_expected(0) = 0;
 	mb();
 
 #if 0
@@ -249,7 +226,7 @@
 	}
 
 	draina();
-	CIA_mcheck_expected = 1;
+	mcheck_expected(0) = 1;
 	mb();
 
 	/* Access configuration space.  */
@@ -257,7 +234,7 @@
 	mb();
 	mb();  /* magic */
 
-	CIA_mcheck_expected = 0;
+	mcheck_expected(0) = 0;
 	mb();
 
 #if 0
@@ -395,7 +372,7 @@
 {
         unsigned int cia_tmp;
 
-#ifdef DEBUG_DUMP_REGS
+#if DEBUG_DUMP_REGS
 	{
 		unsigned int temp;
 		temp = *(vuip)CIA_IOC_CIA_REV; mb();
@@ -533,19 +510,26 @@
 	case 0:
 		/*
 		 * Set up the PCI->physical memory translation windows.
-		 * For now, windows 1,2 and 3 are disabled.  In the future,
+		 * For now, windows 2 and 3 are disabled.  In the future,
 		 * we may want to use them to do scatter/gather DMA. 
 		 *
 		 * Window 0 goes at 1 GB and is 1 GB large.
+		 * Window 1 goes at 2 GB and is 1 GB large.
 		 */
 
-		*(vuip)CIA_IOC_PCI_W0_BASE = 1U | (CIA_DMA_WIN_BASE_DEFAULT & 0xfff00000U);
-		*(vuip)CIA_IOC_PCI_W0_MASK = (CIA_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U;
-		*(vuip)CIA_IOC_PCI_T0_BASE = 0;
+		*(vuip)CIA_IOC_PCI_W0_BASE = CIA_DMA_WIN0_BASE_DEFAULT | 1U;
+		*(vuip)CIA_IOC_PCI_W0_MASK = (CIA_DMA_WIN0_SIZE_DEFAULT - 1) &
+					     0xfff00000U;
+		*(vuip)CIA_IOC_PCI_T0_BASE = CIA_DMA_WIN0_TRAN_DEFAULT >> 2;
+		
+		*(vuip)CIA_IOC_PCI_W1_BASE = CIA_DMA_WIN1_BASE_DEFAULT | 1U;
+		*(vuip)CIA_IOC_PCI_W1_MASK = (CIA_DMA_WIN1_SIZE_DEFAULT - 1) &
+					     0xfff00000U;
+		*(vuip)CIA_IOC_PCI_T1_BASE = CIA_DMA_WIN1_TRAN_DEFAULT >> 2;
 
-		*(vuip)CIA_IOC_PCI_W1_BASE = 0x0;
 		*(vuip)CIA_IOC_PCI_W2_BASE = 0x0;
 		*(vuip)CIA_IOC_PCI_W3_BASE = 0x0;
+		mb();
 		break;
 	}
 
@@ -593,128 +577,28 @@
         }
 }
 
-static int
+static inline void
 cia_pci_clr_err(void)
 {
-	CIA_jd = *(vuip)CIA_IOC_CIA_ERR;
-	DBGM(("CIA_pci_clr_err: CIA ERR after read 0x%x\n", CIA_jd));
-	*(vuip)CIA_IOC_CIA_ERR = CIA_jd;
+	unsigned int jd;
+
+	jd = *(vuip)CIA_IOC_CIA_ERR;
+	*(vuip)CIA_IOC_CIA_ERR = jd;
 	mb();
-	return 0;
+	*(vuip)CIA_IOC_CIA_ERR;		/* re-read to force write.  */
 }
 
 void
 cia_machine_check(unsigned long vector, unsigned long la_ptr,
 		  struct pt_regs * regs)
 {
-	struct el_common *mchk_header;
-	struct el_CIA_procdata *mchk_procdata;
-	struct el_CIA_sysdata_mcheck *mchk_sysdata;
-	unsigned long * ptr;
-	const char * reason;
-	char buf[128];
-	long i;
-
-	mchk_header = (struct el_common *)la_ptr;
-
-	mchk_procdata = (struct el_CIA_procdata *)
-		(la_ptr + mchk_header->proc_offset);
-
-	mchk_sysdata = (struct el_CIA_sysdata_mcheck *)
-		(la_ptr + mchk_header->sys_offset);
-
-	DBGM(("cia_machine_check: vector=0x%lx la_ptr=0x%lx\n",
-	      vector, la_ptr));
-	DBGM(("                     pc=0x%lx size=0x%x procoffset=0x%x "
-	      "sysoffset 0x%x\n", regs->pc, mchk_header->size,
-	      mchk_header->proc_offset, mchk_header->sys_offset));
-	DBGM(("cia_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n",
-	      CIA_mcheck_expected, mchk_sysdata->epic_dcsr,
-	      mchk_sysdata->epic_pear));
-
-#if DEBUG_MCHECK
-	{
-		unsigned long *ptr;
-		int i;
-
-		ptr = (unsigned long *)la_ptr;
-		for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
-			printk(" +%lx %lx %lx\n", i*sizeof(long),
-			       ptr[i], ptr[i+1]);
-		}
-	}
-#endif
-
-	/*
-	 * Check if machine check is due to a badaddr() and if so,
-	 * ignore the machine check.
-	 */
-	mb();
-	mb();  /* magic */
-	if (CIA_mcheck_expected) {
-		DBGM(("CIA machine check expected\n"));
-		CIA_mcheck_expected = 0;
-		CIA_mcheck_taken = 1;
-		mb();
-		mb();  /* magic */
-		draina();
-		cia_pci_clr_err();
-		wrmces(0x7);
-		mb();
-		return;
-	}
-
-	switch ((unsigned int) mchk_header->code) {
-	case MCHK_K_TPERR:	reason = "tag parity error"; break;
-	case MCHK_K_TCPERR:	reason = "tag control parity error"; break;
-	case MCHK_K_HERR:	reason = "generic hard error"; break;
-	case MCHK_K_ECC_C:	reason = "correctable ECC error"; break;
-	case MCHK_K_ECC_NC:	reason = "uncorrectable ECC error"; break;
-	case MCHK_K_OS_BUGCHECK:	reason = "OS-specific PAL bugcheck"; break;
-	case MCHK_K_PAL_BUGCHECK:	reason = "callsys in kernel mode"; break;
-	case 0x96: reason = "i-cache read retryable error"; break;
-	case 0x98: reason = "processor detected hard error"; break;
-
-		/* System specific (these are for Alcor, at least): */
-	case 0x203: reason = "system detected uncorrectable ECC error"; break;
-	case 0x205: reason = "parity error detected by CIA"; break;
-	case 0x207: reason = "non-existent memory error"; break;
-	case 0x209: reason = "PCI SERR detected"; break;
-	case 0x20b: reason = "PCI data parity error detected"; break;
-	case 0x20d: reason = "PCI address parity error detected"; break;
-	case 0x20f: reason = "PCI master abort error"; break;
-	case 0x211: reason = "PCI target abort error"; break;
-	case 0x213: reason = "scatter/gather PTE invalid error"; break;
-	case 0x215: reason = "flash ROM write error"; break;
-	case 0x217: reason = "IOA timeout detected"; break;
-	case 0x219: reason = "IOCHK#, EISA add-in board parity or other catastrophic error"; break;
-	case 0x21b: reason = "EISA fail-safe timer timeout"; break;
-	case 0x21d: reason = "EISA bus time-out"; break;
-	case 0x21f: reason = "EISA software generated NMI"; break;
-	case 0x221: reason = "unexpected ev5 IRQ[3] interrupt"; break;
-	default:
-		sprintf(buf, "reason for machine-check unknown (0x%x)",
-			(unsigned int) mchk_header->code);
-		reason = buf;
-		break;
-	}
+	/* Clear the error before any reporting.  */
 	mb();
 	mb();  /* magic */
 	draina();
 	cia_pci_clr_err();
-	wrmces(rdmces());	/* reset machine check pending flag */
+	wrmces(rdmces());	/* reset machine check pending flag.  */
 	mb();
 
-	printk(KERN_CRIT "CIA machine check: %s%s\n",
-	       reason, mchk_header->retry ? " (retryable)" : "");
-	printk(KERN_CRIT "   vector=0x%lx la_ptr=0x%lx pc=0x%lx\n",
-	       vector, la_ptr, regs->pc);
-
-	/* Dump the logout area to give all info.  */
-
-	ptr = (unsigned long *)la_ptr;
-	for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
-		printk(KERN_CRIT "   +%8lx %016lx %016lx\n",
-		       i*sizeof(long), ptr[i], ptr[i+1]);
-	}
+	process_mcheck_info(vector, la_ptr, regs, "CIA", mcheck_expected(0));
 }
diff -u --recursive --new-file v2.3.13/linux/arch/alpha/kernel/core_lca.c linux/arch/alpha/kernel/core_lca.c
--- v2.3.13/linux/arch/alpha/kernel/core_lca.c	Sun Sep  6 10:34:33 1998
+++ linux/arch/alpha/kernel/core_lca.c	Fri Aug 13 11:53:50 1999
@@ -430,18 +430,18 @@
 }
 
 void
-lca_machine_check (unsigned long vector, unsigned long la,
+lca_machine_check (unsigned long vector, unsigned long la_ptr,
 		   struct pt_regs *regs)
 {
-	unsigned long * ptr;
 	const char * reason;
 	union el_lca el;
-	char buf[128];
-	long i;
 
-	printk(KERN_CRIT "lca: machine check (la=0x%lx,pc=0x%lx)\n",
-	       la, regs->pc);
-	el.c = (struct el_common *) la;
+	el.c = (struct el_common *) la_ptr;
+
+	wrmces(rdmces());	/* reset machine check pending flag */
+
+	printk(KERN_CRIT "LCA machine check: vector=%#lx pc=%#lx code=%#x\n",
+	       vector, regs->pc, (unsigned int) el.c->code);
 
 	/*
 	 * The first quadword after the common header always seems to
@@ -450,13 +450,13 @@
 	 * logout frame, the upper 32 bits is the machine check
 	 * revision level, which we ignore for now.
 	 */
-	switch (el.c->code & 0xffffffff) {
+	switch ((unsigned int) el.c->code) {
 	case MCHK_K_TPERR:	reason = "tag parity error"; break;
 	case MCHK_K_TCPERR:	reason = "tag control parity error"; break;
 	case MCHK_K_HERR:	reason = "access to non-existent memory"; break;
 	case MCHK_K_ECC_C:	reason = "correctable ECC error"; break;
 	case MCHK_K_ECC_NC:	reason = "non-correctable ECC error"; break;
-	case MCHK_K_CACKSOFT:	reason = "MCHK_K_CACKSOFT"; break; /* what's this? */
+	case MCHK_K_CACKSOFT:	reason = "MCHK_K_CACKSOFT"; break;
 	case MCHK_K_BUGCHECK:	reason = "illegal exception in PAL mode"; break;
 	case MCHK_K_OS_BUGCHECK: reason = "callsys in kernel mode"; break;
 	case MCHK_K_DCPERR:	reason = "d-cache parity error"; break;
@@ -465,19 +465,13 @@
 	case MCHK_K_SIO_IOCHK:	reason = "SIO IOCHK occurred on ISA bus"; break;
 	case MCHK_K_DCSR:	reason = "MCHK_K_DCSR"; break;
 	case MCHK_K_UNKNOWN:
-	default:
-		sprintf(buf, "reason for machine-check unknown (0x%lx)",
-			el.c->code & 0xffffffff);
-		reason = buf;
-		break;
+	default:		reason = "unknown"; break;
 	}
 
-	wrmces(rdmces());	/* reset machine check pending flag */
-
 	switch (el.c->size) {
 	case sizeof(struct el_lca_mcheck_short):
 		printk(KERN_CRIT
-		       "  Reason: %s (short frame%s, dc_stat=%lx):\n",
+		       "  Reason: %s (short frame%s, dc_stat=%#lx):\n",
 		       reason, el.c->retry ? ", retryable" : "",
 		       el.s->dc_stat);
 		if (el.s->esr & ESR_EAV) {
@@ -492,9 +486,9 @@
 		printk(KERN_CRIT "  Reason: %s (long frame%s):\n",
 		       reason, el.c->retry ? ", retryable" : "");
 		printk(KERN_CRIT
-		       "    reason: %lx  exc_addr: %lx  dc_stat: %lx\n", 
+		       "    reason: %#lx  exc_addr: %#lx  dc_stat: %#lx\n", 
 		       el.l->pt[0], el.l->exc_addr, el.l->dc_stat);
-		printk(KERN_CRIT "    car: %lx\n", el.l->car);
+		printk(KERN_CRIT "    car: %#lx\n", el.l->car);
 		if (el.l->esr & ESR_EAV) {
 			mem_error(el.l->esr, el.l->ear);
 		}
@@ -508,12 +502,16 @@
 	}
 
 	/* Dump the logout area to give all info.  */
-
-	ptr = (unsigned long *) la;
-	for (i = 0; i < el.c->size / sizeof(long); i += 2) {
-		printk(KERN_CRIT " +%8lx %016lx %016lx\n",
-		       i*sizeof(long), ptr[i], ptr[i+1]);
+#if DEBUG_MCHECK > 1
+	{
+		unsigned long * ptr = (unsigned long *) la_ptr;
+		long i;
+		for (i = 0; i < el.c->size / sizeof(long); i += 2) {
+			printk(KERN_CRIT " +%8lx %016lx %016lx\n",
+			       i*sizeof(long), ptr[i], ptr[i+1]);
+		}
 	}
+#endif
 }
 
 /*
diff -u --recursive --new-file v2.3.13/linux/arch/alpha/kernel/core_mcpcia.c linux/arch/alpha/kernel/core_mcpcia.c
--- v2.3.13/linux/arch/alpha/kernel/core_mcpcia.c	Tue Jun 22 10:54:54 1999
+++ linux/arch/alpha/kernel/core_mcpcia.c	Fri Aug 13 11:53:50 1999
@@ -37,27 +37,14 @@
  * BIOS32-style PCI interface:
  */
 
-#undef DEBUG_CFG
+#define DEBUG_CFG 0
 
-#ifdef DEBUG_CFG
+#if DEBUG_CFG
 # define DBG_CFG(args)	printk args
 #else
 # define DBG_CFG(args)
 #endif
 
-
-#define DEBUG_MCHECK
-
-#ifdef DEBUG_MCHECK
-# define DBG_MCK(args)	printk args
-#else
-# define DBG_MCK(args)
-#endif
-
-static volatile unsigned int MCPCIA_mcheck_expected[NR_CPUS];
-static volatile unsigned int MCPCIA_mcheck_taken[NR_CPUS];
-static unsigned int MCPCIA_jd[NR_CPUS];
-
 #define MCPCIA_MAX_HOSES 2
 
 
@@ -126,8 +113,9 @@
 
 	mb();
 	draina();
-	MCPCIA_mcheck_expected[cpu] = 1;
-	MCPCIA_mcheck_taken[cpu] = 0;
+	mcheck_expected(cpu) = 1;
+	mcheck_taken(cpu) = 0;
+	mcheck_hose(cpu) = hoseno;
 	mb();
 
 	/* Access configuration space.  */
@@ -135,12 +123,12 @@
 	mb();
 	mb();  /* magic */
 
-	if (MCPCIA_mcheck_taken[cpu]) {
-		MCPCIA_mcheck_taken[cpu] = 0;
+	if (mcheck_taken(cpu)) {
+		mcheck_taken(cpu) = 0;
 		value = 0xffffffffU;
 		mb();
 	}
-	MCPCIA_mcheck_expected[cpu] = 0;
+	mcheck_expected(cpu) = 0;
 	mb();
 
 	DBG_CFG(("conf_read(): finished\n"));
@@ -168,7 +156,8 @@
 	DBG_CFG(("conf_write: MCPCIA CAP_ERR(%d) was 0x%x\n", hoseno, stat0));
 
 	draina();
-	MCPCIA_mcheck_expected[cpu] = 1;
+	mcheck_expected(cpu) = 1;
+	mcheck_hose(cpu) = hoseno;
 	mb();
 
 	/* Access configuration space.  */
@@ -176,7 +165,7 @@
 	mb();
 	mb();  /* magic */
 	temp = *(vuip)MCPCIA_CAP_ERR(hoseno); /* read to force the write */
-	MCPCIA_mcheck_expected[cpu] = 0;
+	mcheck_expected(cpu) = 0;
 	mb();
 
 	DBG_CFG(("conf_write(): finished\n"));
@@ -328,8 +317,8 @@
 		mb();
 		mb();
 		draina();
-		MCPCIA_mcheck_expected[cpu] = 1;
-		MCPCIA_mcheck_taken[cpu]    = 0;
+		mcheck_expected(cpu) = 1;
+		mcheck_taken(cpu) = 0;
 		mb();
 
 		/* Access the bus revision word. */
@@ -337,12 +326,12 @@
 
 		mb();
 		mb();  /* magic */
-		if (MCPCIA_mcheck_taken[cpu]) {
-			MCPCIA_mcheck_taken[cpu] = 0;
+		if (mcheck_taken(cpu)) {
+			mcheck_taken(cpu) = 0;
 			pci_rev = 0xffffffff;
 			mb();
 		}
-		MCPCIA_mcheck_expected[cpu] = 0;
+		mcheck_expected(cpu) = 0;
 		mb();
 
 #if 0
@@ -554,19 +543,13 @@
 	}
 }
 
-static int
-mcpcia_pci_clr_err(int h)
+static void
+mcpcia_pci_clr_err(int hose)
 {
-	unsigned int cpu = smp_processor_id();
-
-	MCPCIA_jd[cpu] = *(vuip)MCPCIA_CAP_ERR(h);
-#if 0
-	DBG_MCK(("MCPCIA_pci_clr_err: MCPCIA CAP_ERR(%d) after read 0x%x\n",
-		 h, MCPCIA_jd[cpu]));
-#endif
-	*(vuip)MCPCIA_CAP_ERR(h) = 0xffffffff; mb(); /* clear them all */
-	MCPCIA_jd[cpu] = *(vuip)MCPCIA_CAP_ERR(h);
-	return 0;
+	*(vuip)MCPCIA_CAP_ERR(hose);
+	*(vuip)MCPCIA_CAP_ERR(hose) = 0xffffffff;   /* Clear them all.  */
+	mb();
+	*(vuip)MCPCIA_CAP_ERR(hose);  /* Re-read for force write.  */
 }
 
 static void
@@ -642,70 +625,33 @@
 }
 
 void
-mcpcia_machine_check(unsigned long type, unsigned long la_ptr,
+mcpcia_machine_check(unsigned long vector, unsigned long la_ptr,
 		     struct pt_regs * regs)
 {
-#if 0
-        printk("mcpcia machine check ignored\n") ;
-#else
 	struct el_common *mchk_header;
 	struct el_MCPCIA_uncorrected_frame_mcheck *mchk_logout;
 	unsigned int cpu = smp_processor_id();
-	int h = 0;
 
 	mchk_header = (struct el_common *)la_ptr;
 	mchk_logout = (struct el_MCPCIA_uncorrected_frame_mcheck *)la_ptr;
 
-#if 0
-	DBG_MCK(("mcpcia_machine_check: type=0x%lx la_ptr=0x%lx\n",
-		 type, la_ptr));
-	DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
-		 regs->pc, mchk_header->size, mchk_header->proc_offset,
-		 mchk_header->sys_offset));
-#endif
-	/*
-	 * Check if machine check is due to a badaddr() and if so,
-	 * ignore the machine check.
-	 */
 	mb();
 	mb();  /* magic */
-	if (MCPCIA_mcheck_expected[cpu]) {
-#if 0
-		DBG_MCK(("MCPCIA machine check expected\n"));
-#endif
-		MCPCIA_mcheck_expected[cpu] = 0;
-		MCPCIA_mcheck_taken[cpu] = 1;
-		mb();
-		mb();  /* magic */
-		draina();
-		mcpcia_pci_clr_err(h);
-		wrmces(0x7);
-		mb();
+	draina();
+	if (mcheck_expected(cpu)) {
+		mcpcia_pci_clr_err(mcheck_hose(cpu));
+	} else {
+		/* FIXME: how do we figure out which hose the error was on?  */	
+		mcpcia_pci_clr_err(0);
+		mcpcia_pci_clr_err(1);
 	}
-#if 1
-	else {
-		printk("MCPCIA machine check NOT expected on CPU %d\n", cpu);
-		DBG_MCK(("mcpcia_machine_check: type=0x%lx pc=0x%lx"
-			 " code=0x%lx\n",
-			 type, regs->pc, mchk_header->code));
+	wrmces(0x7);
+	mb();
 
-		MCPCIA_mcheck_expected[cpu] = 0;
-		MCPCIA_mcheck_taken[cpu] = 1;
-		mb();
-		mb();  /* magic */
-		draina();
-		mcpcia_pci_clr_err(h);
-		wrmces(0x7);
-		mb();
-#ifdef DEBUG_MCHECK_DUMP
-		if (type == 0x620)
-			printk("MCPCIA machine check: system CORRECTABLE!\n");
-		else if (type == 0x630)
-			printk("MCPCIA machine check: processor CORRECTABLE!\n");
-		else
-#endif /* DEBUG_MCHECK_DUMP */
-			mcpcia_print_uncorrectable(mchk_logout);
+	process_mcheck_info(vector, la_ptr, regs, "MCPCIA",
+		            mcheck_expected(cpu));
+
+	if (vector != 0x620 && vector != 0x630) {
+		mcpcia_print_uncorrectable(mchk_logout);
 	}
-#endif
-#endif
 }
diff -u --recursive --new-file v2.3.13/linux/arch/alpha/kernel/core_polaris.c linux/arch/alpha/kernel/core_polaris.c
--- v2.3.13/linux/arch/alpha/kernel/core_polaris.c	Sun Jan 10 22:56:43 1999
+++ linux/arch/alpha/kernel/core_polaris.c	Fri Aug 13 11:53:50 1999
@@ -26,23 +26,14 @@
  * BIOS32-style PCI interface:
  */
 
-#ifdef DEBUG_CONFIG
+#define DEBUG_CONFIG 0
+
+#if DEBUG_CONFIG
 # define DBG_CFG(args)	printk args
 #else
 # define DBG_CFG(args)
 #endif
 
-#define DEBUG_MCHECK
-#ifdef DEBUG_MCHECK
-# define DBG_MCK(args)	printk args
-/* #define DEBUG_MCHECK_DUMP */
-#else
-# define DBG_MCK(args)
-#endif
-
-static volatile unsigned int POLARIS_mcheck_expected = 0;
-static volatile unsigned int POLARIS_mcheck_taken = 0;
-static volatile unsigned short POLARIS_jd = 0;
 
 /*
  * Given a bus, device, and function number, compute resulting
@@ -195,81 +186,28 @@
 #endif
 }
 
-int polaris_pci_clr_err(void)
+static inline void
+polaris_pci_clr_err(void)
 {
-	POLARIS_jd = *((vusp)POLARIS_W_STATUS);
-	DBG_MCK(("POLARIS_pci_clr_err: POLARIS_W_STATUS after read 0x%x\n",
-		 POLARIS_jd));
+	*(vusp)POLARIS_W_STATUS;
 	/* Write 1's to settable bits to clear errors */
-	*((vusp)POLARIS_W_STATUS) = 0x7800; mb();
-	POLARIS_jd = *((vusp)POLARIS_W_STATUS);
-	return 0;
+	*(vusp)POLARIS_W_STATUS = 0x7800;
+	mb();
+	*(vusp)POLARIS_W_STATUS;
 }
 
-void polaris_machine_check(unsigned long vector, unsigned long la_ptr,
-			 struct pt_regs * regs)
+void
+polaris_machine_check(unsigned long vector, unsigned long la_ptr,
+		      struct pt_regs * regs)
 {
-	struct el_common *mchk_header;
-	struct el_POLARIS_sysdata_mcheck *mchk_sysdata;
-
-	mchk_header = (struct el_common *)la_ptr;
-
-	mchk_sysdata = 
-	  (struct el_POLARIS_sysdata_mcheck *)(la_ptr+mchk_header->sys_offset);
-
-#if 0
-	DBG_MCK(("polaris_machine_check: vector=0x%lx la_ptr=0x%lx\n",
-	     vector, la_ptr));
-	DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
-	     regs->pc, mchk_header->size, mchk_header->proc_offset,
-	     mchk_header->sys_offset));
-	DBG_MCK(("polaris_machine_check: expected %d status 0x%lx\n",
-	     POLARIS_mcheck_expected, mchk_sysdata->psc_status));
-#endif
-#ifdef DEBUG_MCHECK_DUMP
-	{
-	    unsigned long *ptr;
-	    int i;
-
-	    ptr = (unsigned long *)la_ptr;
-	    for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
-		printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]);
-	    }
-	}
-#endif /* DEBUG_MCHECK_DUMP */
-	/*
-	 * Check if machine check is due to a badaddr() and if so,
-	 * ignore the machine check.
-	 */
+	/* Clear the error before any reporting.  */
 	mb();
 	mb();
-	if (POLARIS_mcheck_expected) {
-		DBG_MCK(("POLARIS machine check expected\n"));
-		POLARIS_mcheck_expected = 0;
-		POLARIS_mcheck_taken = 1;
-		mb();
-		mb();
-		draina();
-		polaris_pci_clr_err();
-		wrmces(0x7);
-		mb();
-	}
-#if 1
-	else {
-		printk("POLARIS machine check NOT expected\n") ;
-	DBG_MCK(("polaris_machine_check: vector=0x%lx la_ptr=0x%lx\n",
-	     vector, la_ptr));
-	DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
-	     regs->pc, mchk_header->size, mchk_header->proc_offset,
-	     mchk_header->sys_offset));
-		POLARIS_mcheck_expected = 0;
-		POLARIS_mcheck_taken = 1;
-		mb();
-		mb();
-		draina();
-		polaris_pci_clr_err();
-		wrmces(0x7);
-		mb();
-	}
-#endif
+	draina();
+	polaris_pci_clr_err();
+	wrmces(0x7);
+	mb();
+
+	process_mcheck_info(vector, la_ptr, regs, "POLARIS",
+			    mcheck_expected(0));
 }
diff -u --recursive --new-file v2.3.13/linux/arch/alpha/kernel/core_pyxis.c linux/arch/alpha/kernel/core_pyxis.c
--- v2.3.13/linux/arch/alpha/kernel/core_pyxis.c	Wed Jul 21 15:46:48 1999
+++ linux/arch/alpha/kernel/core_pyxis.c	Fri Aug 13 11:53:50 1999
@@ -32,7 +32,6 @@
  */
 
 #define DEBUG_CONFIG 0
-#define DEBUG_MCHECK 0
 
 #if DEBUG_CONFIG
 # define DBG_CNF(args)	printk args
@@ -40,18 +39,6 @@
 # define DBG_CNF(args)
 #endif
 
-#if DEBUG_MCHECK
-# define DBG_MCK(args)	printk args
-# define DEBUG_MCHECK_DUMP
-#else
-# define DBG_MCK(args)
-#endif
-
-
-static volatile unsigned int PYXIS_mcheck_expected = 0;
-static volatile unsigned int PYXIS_mcheck_taken = 0;
-static unsigned int PYXIS_jd;
-
 
 /*
  * Given a bus, device, and function number, compute resulting
@@ -132,8 +119,8 @@
 
 	mb();
 	draina();
-	PYXIS_mcheck_expected = 1;
-	PYXIS_mcheck_taken = 0;
+	mcheck_expected(0) = 1;
+	mcheck_taken(0) = 0;
 	mb();
 
 	/* Access configuration space.  */
@@ -141,12 +128,12 @@
 	mb();
 	mb();  /* magic */
 
-	if (PYXIS_mcheck_taken) {
-		PYXIS_mcheck_taken = 0;
+	if (mcheck_taken(0)) {
+		mcheck_taken(0) = 0;
 		value = 0xffffffffU;
 		mb();
 	}
-	PYXIS_mcheck_expected = 0;
+	mcheck_expected(0) = 0;
 	mb();
 
 	/* If Type1 access, must reset IOC CFG so normal IO space ops work.  */
@@ -186,15 +173,15 @@
 
 	mb();
 	draina();
-	PYXIS_mcheck_expected = 1;
-	PYXIS_mcheck_taken = 0;
+	mcheck_expected(0) = 1;
+	mcheck_taken(0) = 0;
 	mb();
 
 	/* Access configuration space.  */
 	*(vuip)addr = value;
 	mb();
 	temp = *(vuip)addr; /* read back to force the write */
-	PYXIS_mcheck_expected = 0;
+	mcheck_expected(0) = 0;
 	mb();
 
 	/* If Type1 access, must reset IOC CFG so normal IO space ops work.  */
@@ -432,14 +419,13 @@
 	 * Window 1 goes at 3 GB and is 1 GB large.
 	 */
 
-	*(vuip)PYXIS_W0_BASE = PYXIS_DMA_WIN_BASE_DEFAULT | 1UL;
-	*(vuip)PYXIS_W0_MASK = (PYXIS_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U;
-	*(vuip)PYXIS_T0_BASE = 0;
-
-	*(vuip)PYXIS_W1_BASE = (PYXIS_DMA_WIN_BASE_DEFAULT +
-				PYXIS_DMA_WIN_SIZE_DEFAULT) | 1U;
-	*(vuip)PYXIS_W1_MASK = (PYXIS_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U;
-	*(vuip)PYXIS_T1_BASE = PYXIS_DMA_WIN_SIZE_DEFAULT;
+	*(vuip)PYXIS_W0_BASE = PYXIS_DMA_WIN0_BASE_DEFAULT | 1U;
+	*(vuip)PYXIS_W0_MASK = (PYXIS_DMA_WIN0_SIZE_DEFAULT - 1) & 0xfff00000U;
+	*(vuip)PYXIS_T0_BASE = PYXIS_DMA_WIN0_TRAN_DEFAULT >> 2;
+
+	*(vuip)PYXIS_W1_BASE = PYXIS_DMA_WIN1_BASE_DEFAULT | 1U;
+	*(vuip)PYXIS_W1_MASK = (PYXIS_DMA_WIN1_SIZE_DEFAULT - 1) & 0xfff00000U;
+	*(vuip)PYXIS_T1_BASE = PYXIS_DMA_WIN1_TRAN_DEFAULT >> 2;
 
 	*(vuip)PYXIS_W2_BASE = 0x0;
 	*(vuip)PYXIS_W3_BASE = 0x0;
@@ -530,83 +516,26 @@
 	pyxis_finish_init_arch();
 }
 
-static int
+static inline void
 pyxis_pci_clr_err(void)
 {
-	PYXIS_jd = *(vuip)PYXIS_ERR;
-	DBG_MCK(("PYXIS_pci_clr_err: PYXIS ERR after read 0x%x\n", PYXIS_jd));
-	*(vuip)PYXIS_ERR = 0x0180; mb();
-	PYXIS_jd = *(vuip)PYXIS_ERR;  /* re-read to force write */
-	return 0;
+	*(vuip)PYXIS_ERR;
+	*(vuip)PYXIS_ERR = 0x0180;
+	mb();
+	*(vuip)PYXIS_ERR;  /* re-read to force write */
 }
 
 void
 pyxis_machine_check(unsigned long vector, unsigned long la_ptr,
 		    struct pt_regs * regs)
 {
-	struct el_common *mchk_header;
-	struct el_PYXIS_sysdata_mcheck *mchk_sysdata;
-
-	mchk_header = (struct el_common *)la_ptr;
-
-	mchk_sysdata = (struct el_PYXIS_sysdata_mcheck *)
-		(la_ptr + mchk_header->sys_offset);
-
-#if 0
-	DBG_MCK(("pyxis_machine_check: vector=0x%lx la_ptr=0x%lx\n",
-		 vector, la_ptr));
-	DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
-		 regs->pc, mchk_header->size, mchk_header->proc_offset,
-		 mchk_header->sys_offset));
-	DBG_MCK(("pyxis_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n",
-		 PYXIS_mcheck_expected, mchk_sysdata->epic_dcsr,
-		 mchk_sysdata->epic_pear));
-#endif
-
-	/*
-	 * Check if machine check is due to a badaddr() and if so,
-	 * ignore the machine check.
-	 */
+	/* Clear the error before reporting anything.  */
 	mb();
 	mb();  /* magic */
-	if (PYXIS_mcheck_expected) {
-		DBG_MCK(("PYXIS machine check expected\n"));
-		PYXIS_mcheck_expected = 0;
-		PYXIS_mcheck_taken = 1;
-		mb();
-		mb();  /* magic */
-		draina();
-		pyxis_pci_clr_err();
-		wrmces(0x7);
-		mb();
-	}
-	else {
-		printk("PYXIS machine check NOT expected\n") ;
-		DBG_MCK(("pyxis_machine_check: vector=0x%lx la_ptr=0x%lx\n",
-			 vector, la_ptr));
-		DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x"
-			 " sysoffset 0x%x\n",
-			 regs->pc, mchk_header->size, mchk_header->proc_offset,
-			 mchk_header->sys_offset));
-		PYXIS_mcheck_expected = 0;
-		PYXIS_mcheck_taken = 1;
-		mb();
-		mb();  /* magic */
-		draina();
-		pyxis_pci_clr_err();
-		wrmces(0x7);
-		mb();
+	draina();
+	pyxis_pci_clr_err();
+	wrmces(0x7);
+	mb();
 
-#ifdef DEBUG_MCHECK_DUMP
-		{
-			unsigned long *ptr = (unsigned long *)la_ptr;;
-			long n = mchk_header->size / (2*sizeof(long));
-
-			do
-				printk(" +%lx %lx %lx\n", i*sizeof(long),
-				       ptr[i], ptr[i+1]);
-			while (--i);
-		}
-#endif
-	}
+	process_mcheck_info(vector, la_ptr, regs, "PYXIS", mcheck_expected(0));
 }
diff -u --recursive --new-file v2.3.13/linux/arch/alpha/kernel/core_t2.c linux/arch/alpha/kernel/core_t2.c
--- v2.3.13/linux/arch/alpha/kernel/core_t2.c	Sat Jan  9 19:08:21 1999
+++ linux/arch/alpha/kernel/core_t2.c	Fri Aug 13 11:53:50 1999
@@ -33,36 +33,17 @@
  */
 
 /*
- * Machine check reasons.  Defined according to PALcode sources
- * (osf.h and platform.h).
- */
-#define MCHK_K_TPERR		0x0080
-#define MCHK_K_TCPERR		0x0082
-#define MCHK_K_HERR		0x0084
-#define MCHK_K_ECC_C		0x0086
-#define MCHK_K_ECC_NC		0x0088
-#define MCHK_K_OS_BUGCHECK	0x008A
-#define MCHK_K_PAL_BUGCHECK	0x0090
-
-/*
  * BIOS32-style PCI interface:
  */
 
-#ifdef DEBUG_CONF
+#define DEBUG_CONFIG 0
+
+#if DEBUG_CONFIG
 # define DBG(args)	printk args
 #else
 # define DBG(args)
 #endif
 
-#ifdef DEBUG_MCHECK
-# define DBGMC(args)	printk args
-#else
-# define DBGMC(args)
-#endif
-
-static volatile unsigned int T2_mcheck_expected[NR_CPUS];
-static volatile unsigned int T2_mcheck_taken[NR_CPUS];
-
 
 /*
  * Given a bus, device, and function number, compute resulting
@@ -173,8 +154,8 @@
 	mb();
 	draina();
 
-	T2_mcheck_expected[cpu] = 1;
-	T2_mcheck_taken[cpu] = 0;
+	mcheck_expected(cpu) = 1;
+	mcheck_taken(cpu) = 0;
 	mb();
 
 	/* Access configuration space. */
@@ -182,12 +163,12 @@
 	mb();
 	mb();  /* magic */
 
-	if (T2_mcheck_taken[cpu]) {
-		T2_mcheck_taken[cpu] = 0;
+	if (mcheck_taken(cpu)) {
+		mcheck_taken(cpu) = 0;
 		value = 0xffffffffU;
 		mb();
 	}
-	T2_mcheck_expected[cpu] = 0;
+	mcheck_expected(cpu) = 0;
 	mb();
 
 	/* If Type1 access, must reset T2 CFG so normal IO space ops work.  */
@@ -233,7 +214,7 @@
 	mb();
 	draina();
 
-	T2_mcheck_expected[cpu] = 1;
+	mcheck_expected(cpu) = 1;
 	mb();
 
 	/* Access configuration space.  */
@@ -241,7 +222,7 @@
 	mb();
 	mb();  /* magic */
 
-	T2_mcheck_expected[cpu] = 0;
+	mcheck_expected(cpu) = 0;
 	mb();
 
 	/* If Type1 access, must reset T2 CFG so normal IO space ops work.  */
@@ -355,8 +336,8 @@
 	unsigned int i;
 
 	for (i = 0; i < NR_CPUS; i++) {
-		T2_mcheck_expected[i] = 0;
-		T2_mcheck_taken[i] = 0;
+		mcheck_expected(i) = 0;
+		mcheck_taken(i) = 0;
 	}
 
 #if 0
@@ -481,27 +462,22 @@
 
 #define SIC_SEIC (1UL << 33)    /* System Event Clear */
 
-static int
-t2_clear_errors(void)
+static void
+t2_clear_errors(int cpu)
 {
-	unsigned int cpu = smp_processor_id();
-	static struct sable_cpu_csr *cpu_regs = NULL;
-
-	switch (cpu)
-	{
-	case 0: cpu_regs = (struct sable_cpu_csr *)T2_CPU0_BASE; break;
-	case 1: cpu_regs = (struct sable_cpu_csr *)T2_CPU1_BASE; break;
-	case 2: cpu_regs = (struct sable_cpu_csr *)T2_CPU2_BASE; break;
-	case 3: cpu_regs = (struct sable_cpu_csr *)T2_CPU3_BASE; break;
-	}
-
-	DBGMC(("???????? t2_clear_errors\n"));
+	struct sable_cpu_csr *cpu_regs;
 
+	cpu_regs = (struct sable_cpu_csr *)T2_CPU0_BASE;
+	if (cpu == 1)
+		cpu_regs = (struct sable_cpu_csr *)T2_CPU1_BASE;
+	if (cpu == 2)
+		cpu_regs = (struct sable_cpu_csr *)T2_CPU2_BASE;
+	if (cpu == 3)
+		cpu_regs = (struct sable_cpu_csr *)T2_CPU3_BASE;
+		
 	cpu_regs->sic &= ~SIC_SEIC;
 
-	/* 
-	 * clear CPU errors
-	 */
+	/* Clear CPU errors.  */
 	cpu_regs->bcce |= cpu_regs->bcce;
 	cpu_regs->cbe  |= cpu_regs->cbe;
 	cpu_regs->bcue |= cpu_regs->bcue;
@@ -512,116 +488,21 @@
 
 	mb();
 	mb();  /* magic */
-	return 0;
 }
 
 void
 t2_machine_check(unsigned long vector, unsigned long la_ptr,
 		 struct pt_regs * regs)
 {
-	struct el_t2_logout_header *mchk_header;
-	struct el_t2_procdata_mcheck *mchk_procdata;
-	struct el_t2_sysdata_mcheck *mchk_sysdata;
-	unsigned long * ptr;
-	const char * reason;
-	char buf[128];
-	long i;
-	unsigned int cpu = smp_processor_id();
-
-	DBGMC(("t2_machine_check: vector=0x%lx la_ptr=0x%lx\n",
-	       vector, la_ptr));
-
-	mchk_header = (struct el_t2_logout_header *)la_ptr;
-
-	DBGMC(("t2_machine_check: susoffset=0x%lx procoffset=0x%lx\n",
-	       mchk_header->elfl_sysoffset, mchk_header->elfl_procoffset));
-
-	mchk_sysdata = (struct el_t2_sysdata_mcheck *)
-		(la_ptr + mchk_header->elfl_sysoffset);
-	mchk_procdata = (struct el_t2_procdata_mcheck *)
-		(la_ptr + mchk_header->elfl_procoffset - sizeof(unsigned long)*32);
-
-	DBGMC(("         pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
-	       regs->pc, mchk_header->elfl_size, mchk_header->elfl_procoffset,
-	       mchk_header->elfl_sysoffset));
-	DBGMC(("t2_machine_check: expected %d\n", T2_mcheck_expected[cpu]));
+	int cpu = smp_processor_id();
 
-#ifdef DEBUG_DUMP
-	{
-		unsigned long *ptr;
-		int i;
-
-		ptr = (unsigned long *)la_ptr;
-		for (i = 0; i < mchk_header->elfl_size/sizeof(long); i += 2) {
-			printk(" +%lx %lx %lx\n", i*sizeof(long),
-			       ptr[i], ptr[i+1]);
-		}
-	}
-#endif /* DEBUG_DUMP */
-
-	/*
-	 * Check if machine check is due to a badaddr() and if so,
-	 * ignore the machine check.
-	 */
+	/* Clear the error before any reporting.  */
 	mb();
 	mb();  /* magic */
-	if (T2_mcheck_expected[cpu]) {
-		DBGMC(("T2 machine check expected\n"));
-		T2_mcheck_taken[cpu] = 1;
-		t2_clear_errors();
-		T2_mcheck_expected[cpu] = 0;
-		mb();
-		mb();  /* magic */
-		wrmces(rdmces()|1);/* ??? */
-		draina();
-		return;
-	}
-
-	switch ((unsigned int) mchk_header->elfl_error_type) {
-	case MCHK_K_TPERR:	reason = "tag parity error"; break;
-	case MCHK_K_TCPERR:	reason = "tag control parity error"; break;
-	case MCHK_K_HERR:	reason = "generic hard error"; break;
-	case MCHK_K_ECC_C:	reason = "correctable ECC error"; break;
-	case MCHK_K_ECC_NC:	reason = "uncorrectable ECC error"; break;
-	case MCHK_K_OS_BUGCHECK: reason = "OS-specific PAL bugcheck"; break;
-	case MCHK_K_PAL_BUGCHECK: reason = "callsys in kernel mode"; break;
-	case 0x96: reason = "i-cache read retryable error"; break;
-	case 0x98: reason = "processor detected hard error"; break;
-
-		/* System specific (these are for Alcor, at least): */
-	case 0x203: reason = "system detected uncorrectable ECC error"; break;
-	case 0x205: reason = "parity error detected by T2"; break;
-	case 0x207: reason = "non-existent memory error"; break;
-	case 0x209: reason = "PCI SERR detected"; break;
-	case 0x20b: reason = "PCI data parity error detected"; break;
-	case 0x20d: reason = "PCI address parity error detected"; break;
-	case 0x20f: reason = "PCI master abort error"; break;
-	case 0x211: reason = "PCI target abort error"; break;
-	case 0x213: reason = "scatter/gather PTE invalid error"; break;
-	case 0x215: reason = "flash ROM write error"; break;
-	case 0x217: reason = "IOA timeout detected"; break;
-	case 0x219: reason = "IOCHK#, EISA add-in board parity or other catastrophic error"; break;
-	case 0x21b: reason = "EISA fail-safe timer timeout"; break;
-	case 0x21d: reason = "EISA bus time-out"; break;
-	case 0x21f: reason = "EISA software generated NMI"; break;
-	case 0x221: reason = "unexpected ev5 IRQ[3] interrupt"; break;
-	default:
-		sprintf(buf, "reason for machine-check unknown (0x%x)",
-			(unsigned int) mchk_header->elfl_error_type);
-		reason = buf;
-		break;
-	}
-	wrmces(rdmces()|1);	/* reset machine check pending flag */
+	draina();
+	t2_clear_errors(cpu);
+	wrmces(rdmces()|1);	/* ??? */
 	mb();
 
-	printk(KERN_CRIT "  T2 machine check: %s%s\n",
-	       reason, mchk_header->elfl_retry ? " (retryable)" : "");
-
-	/* Dump the logout area to give all info.  */
-
-	ptr = (unsigned long *)la_ptr;
-	for (i = 0; i < mchk_header->elfl_size / sizeof(long); i += 2) {
-		printk(KERN_CRIT " +%8lx %016lx %016lx\n",
-		       i*sizeof(long), ptr[i], ptr[i+1]);
-	}
+	process_mcheck_info(vector, la_ptr, regs, "T2", mcheck_expected(cpu));
 }
diff -u --recursive --new-file v2.3.13/linux/arch/alpha/kernel/core_tsunami.c linux/arch/alpha/kernel/core_tsunami.c
--- v2.3.13/linux/arch/alpha/kernel/core_tsunami.c	Sun Jan 10 22:56:43 1999
+++ linux/arch/alpha/kernel/core_tsunami.c	Fri Aug 13 11:53:50 1999
@@ -17,6 +17,7 @@
 #include <asm/ptrace.h>
 #include <asm/system.h>
 #include <asm/pci.h>
+#include <asm/smp.h>
 
 #define __EXTERN_INLINE inline
 #include <asm/io.h>
@@ -26,6 +27,8 @@
 #include "proto.h"
 #include "bios32.h"
 
+int TSUNAMI_bootcpu;
+
 /*
  * NOTE: Herein lie back-to-back mb instructions.  They are magic. 
  * One plausible explanation is that the I/O controller does not properly
@@ -36,24 +39,15 @@
  * BIOS32-style PCI interface:
  */
 
-#ifdef DEBUG_CONFIG
+#define DEBUG_MCHECK 0		/* 0 = minimal, 1 = debug, 2 = debug+dump.  */
+#define DEBUG_CONFIG 0
+
+#if DEBUG_CONFIG
 # define DBG_CFG(args)	printk args
 #else
 # define DBG_CFG(args)
 #endif
 
-#define DEBUG_MCHECK
-#ifdef DEBUG_MCHECK
-# define DBG_MCK(args)	printk args
-#define DEBUG_MCHECK_DUMP
-#else
-# define DBG_MCK(args)
-#endif
-
-static volatile unsigned int TSUNAMI_mcheck_expected[NR_CPUS];
-static volatile unsigned int TSUNAMI_mcheck_taken[NR_CPUS];
-static unsigned int TSUNAMI_jd[NR_CPUS];
-int TSUNAMI_bootcpu;
 
 /*
  * Given a bus, device, and function number, compute resulting
@@ -207,13 +201,14 @@
 	int cpu = smp_processor_id();
 	int s = swpipl(6);	/* Block everything but machine checks. */
 
-	TSUNAMI_mcheck_taken[cpu] = 0;
-	TSUNAMI_mcheck_expected[cpu] = 1;
+	mcheck_taken(cpu) = 0;
+	mcheck_expected(cpu) = 1;
+	mb();
 	dont_care = *vaddr;
 	draina();
-	TSUNAMI_mcheck_expected[cpu] = 0;
-	probe_result = !TSUNAMI_mcheck_taken[cpu];
-	TSUNAMI_mcheck_taken[cpu] = 0;
+	mcheck_expected(cpu) = 0;
+	probe_result = !mcheck_taken(cpu);
+	mcheck_taken(cpu) = 0;
 	setipl(s);
 
 	printk("dont_care == 0x%lx\n", dont_care);
@@ -302,20 +297,18 @@
 		 * we may want to use them to do scatter/gather DMA. 
 		 *
 		 * Window 0 goes at 1 GB and is 1 GB large, mapping to 0.
+		 * Window 1 goes at 2 GB and is 1 GB large, mapping to 1GB.
 		 */
 
-		pchip->wsba[0].csr = 1L | (TSUNAMI_DMA_WIN_BASE_DEFAULT & 0xfff00000U);
-		pchip->wsm[0].csr = (TSUNAMI_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000UL;
-		pchip->tba[0].csr = 0;
-
-#if 0
-		pchip->wsba[1].csr = 0;
-#else
-		/* make the second window at 2Gb for 1Gb mapping to 1Gb */
-		pchip->wsba[1].csr = 1L | ((0x80000000U) & 0xfff00000U);
-		pchip->wsm[1].csr = (0x40000000UL - 1) & 0xfff00000UL;
-		pchip->tba[1].csr = 0x40000000;
-#endif
+		pchip->wsba[0].csr = TSUNAMI_DMA_WIN0_BASE_DEFAULT | 1UL;
+		pchip->wsm[0].csr  = (TSUNAMI_DMA_WIN0_SIZE_DEFAULT - 1) &
+				     0xfff00000UL;
+		pchip->tba[0].csr  = TSUNAMI_DMA_WIN0_TRAN_DEFAULT;
+		
+		pchip->wsba[1].csr = TSUNAMI_DMA_WIN1_BASE_DEFAULT | 1UL;
+		pchip->wsm[1].csr  = (TSUNAMI_DMA_WIN1_SIZE_DEFAULT - 1) &
+				     0xfff00000UL;
+		pchip->tba[1].csr  = TSUNAMI_DMA_WIN1_TRAN_DEFAULT;
 
 		pchip->wsba[2].csr = 0;
 		pchip->wsba[3].csr = 0;
@@ -364,107 +357,48 @@
 	/* Align memory to cache line; we'll be allocating from it.  */
 	*mem_start = (*mem_start | 31) + 1;
 
-	/* Find how many hoses we have, and initialize them.  */
+	TSUNAMI_bootcpu = __hard_smp_processor_id();
+
+	/* Find how many hoses we have, and initialize them.  TSUNAMI
+	   and TYPHOON can have 2, but might only have 1 (DS10).  */
 	tsunami_init_one_pchip(TSUNAMI_pchip0, 0, mem_start);
-	/* must change this for TYPHOON which may have 4 */
 	if (TSUNAMI_cchip->csc.csr & 1L<<14)
 	    tsunami_init_one_pchip(TSUNAMI_pchip1, 1, mem_start);
 }
 
 static inline void
-tsunami_pci_clr_err_1(tsunami_pchip *pchip, int cpu)
+tsunami_pci_clr_err_1(tsunami_pchip *pchip)
 {
-	TSUNAMI_jd[cpu] = pchip->perror.csr;
-	DBG_MCK(("TSUNAMI_pci_clr_err: PERROR after read 0x%x\n",
-		 TSUNAMI_jd[cpu]));
+	unsigned int jd;
+
+	jd = pchip->perror.csr;
 	pchip->perror.csr = 0x040;
 	mb();
-	TSUNAMI_jd[cpu] = pchip->perror.csr;
+	jd = pchip->perror.csr;
 }
 
-static int
+static inline void
 tsunami_pci_clr_err(void)
 {
-	int cpu = smp_processor_id();
-	tsunami_pci_clr_err_1(TSUNAMI_pchip0, cpu);
-	/* must change this for TYPHOON which may have 4 */
+	tsunami_pci_clr_err_1(TSUNAMI_pchip0);
+
+	/* TSUNAMI and TYPHOON can have 2, but might only have 1 (DS10) */
 	if (TSUNAMI_cchip->csc.csr & 1L<<14)
-	    tsunami_pci_clr_err_1(TSUNAMI_pchip1, cpu);
-	return 0;
+	    tsunami_pci_clr_err_1(TSUNAMI_pchip1);
 }
 
 void
 tsunami_machine_check(unsigned long vector, unsigned long la_ptr,
 		      struct pt_regs * regs)
 {
-#if 0
-        printk("TSUNAMI machine check ignored\n") ;
-#else
-	struct el_common *mchk_header;
-	struct el_TSUNAMI_sysdata_mcheck *mchk_sysdata;
-	unsigned int cpu = smp_processor_id();
-
-	mb();
-	mchk_header = (struct el_common *)la_ptr;
-
-	mchk_sysdata = (struct el_TSUNAMI_sysdata_mcheck *)
-		(la_ptr + mchk_header->sys_offset);
-
-#if 0
-	DBG_MCK(("tsunami_machine_check: vector=0x%lx la_ptr=0x%lx\n",
-		 vector, la_ptr));
-	DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
-		 regs->pc, mchk_header->size, mchk_header->proc_offset,
-		 mchk_header->sys_offset));
-	DBG_MCK(("tsunami_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n",
-		 TSUNAMI_mcheck_expected[cpu], mchk_sysdata->epic_dcsr,
-		 mchk_sysdata->epic_pear));
-#endif
-#ifdef DEBUG_MCHECK_DUMP
-	{
-		unsigned long *ptr;
-		int i;
-
-		ptr = (unsigned long *)la_ptr;
-		for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
-			printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]);
-		}
-	}
-#endif /* DEBUG_MCHECK_DUMP */
-	/*
-	 * Check if machine check is due to a badaddr() and if so,
-	 * ignore the machine check.
-	 */
+	/* Clear error before any reporting.  */
 	mb();
 	mb();  /* magic */
-	if (TSUNAMI_mcheck_expected[cpu]) {
-		DBG_MCK(("TSUNAMI machine check expected\n"));
-		TSUNAMI_mcheck_expected[cpu] = 0;
-		TSUNAMI_mcheck_taken[cpu] = 1;
-		mb();
-		mb();  /* magic */
-		draina();
-		tsunami_pci_clr_err();
-		wrmces(0x7);
-		mb();
-	}
-#if 1
-	else {
-		printk("TSUNAMI machine check NOT expected\n") ;
-		DBG_MCK(("tsunami_machine_check: vector=0x%lx la_ptr=0x%lx\n",
-			 vector, la_ptr));
-		DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
-			 regs->pc, mchk_header->size, mchk_header->proc_offset,
-			 mchk_header->sys_offset));
-		TSUNAMI_mcheck_expected[cpu] = 0;
-		TSUNAMI_mcheck_taken[cpu] = 1;
-		mb();
-		mb();  /* magic */
-		draina();
-		tsunami_pci_clr_err();
-		wrmces(0x7);
-		mb();
-	}
-#endif
-#endif
+	draina();
+	tsunami_pci_clr_err();
+	wrmces(0x7);
+	mb();
+
+	process_mcheck_info(vector, la_ptr, regs, "TSUNAMI",
+			    mcheck_expected(smp_processor_id()));
 }
diff -u --recursive --new-file v2.3.13/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c
--- v2.3.13/linux/arch/alpha/kernel/irq.c	Wed Jul 21 15:46:48 1999
+++ linux/arch/alpha/kernel/irq.c	Fri Aug 13 11:53:50 1999
@@ -904,3 +904,99 @@
 	wrent(entInt, 0);
 	alpha_mv.init_irq();
 }
+
+
+/*
+ */
+#define MCHK_K_TPERR           0x0080
+#define MCHK_K_TCPERR          0x0082
+#define MCHK_K_HERR            0x0084
+#define MCHK_K_ECC_C           0x0086
+#define MCHK_K_ECC_NC          0x0088
+#define MCHK_K_OS_BUGCHECK     0x008A
+#define MCHK_K_PAL_BUGCHECK    0x0090
+
+#ifndef __SMP__
+struct mcheck_info __mcheck_info;
+#endif
+
+void
+process_mcheck_info(unsigned long vector, unsigned long la_ptr,
+		    struct pt_regs *regs, const char *machine,
+		    int expected)
+{
+	struct el_common *mchk_header;
+	const char *reason;
+
+	/*
+	 * See if the machine check is due to a badaddr() and if so,
+	 * ignore it.
+	 */
+
+#if DEBUG_MCHECK > 0
+	 printk(KERN_CRIT "%s machine check %s\n", machine,
+	        expected ? "expected." : "NOT expected!!!");
+#endif
+
+	if (expected) {
+		int cpu = smp_processor_id();
+		mcheck_expected(cpu) = 0;
+		mcheck_taken(cpu) = 1;
+		return;
+	}
+
+	mchk_header = (struct el_common *)la_ptr;
+
+	printk(KERN_CRIT "%s machine check: vector=0x%lx pc=0x%lx code=0x%lx\n",
+	       machine, vector, regs->pc, mchk_header->code);
+
+	switch ((unsigned int) mchk_header->code) {
+	/* Machine check reasons.  Defined according to PALcode sources.  */
+	case 0x80: reason = "tag parity error"; break;
+	case 0x82: reason = "tag control parity error"; break;
+	case 0x84: reason = "generic hard error"; break;
+	case 0x86: reason = "correctable ECC error"; break;
+	case 0x88: reason = "uncorrectable ECC error"; break;
+	case 0x8A: reason = "OS-specific PAL bugcheck"; break;
+	case 0x90: reason = "callsys in kernel mode"; break;
+	case 0x96: reason = "i-cache read retryable error"; break;
+	case 0x98: reason = "processor detected hard error"; break;
+	
+	/* System specific (these are for Alcor, at least): */
+	case 0x203: reason = "system detected uncorrectable ECC error"; break;
+	case 0x204: reason = "SIO SERR occurred on PCI bus"; break;
+	case 0x205: reason = "parity error detected by CIA"; break;
+	case 0x206: reason = "SIO IOCHK occurred on ISA bus"; break;
+	case 0x207: reason = "non-existent memory error"; break;
+	case 0x208: reason = "MCHK_K_DCSR"; break;
+	case 0x209: reason = "PCI SERR detected"; break;
+	case 0x20b: reason = "PCI data parity error detected"; break;
+	case 0x20d: reason = "PCI address parity error detected"; break;
+	case 0x20f: reason = "PCI master abort error"; break;
+	case 0x211: reason = "PCI target abort error"; break;
+	case 0x213: reason = "scatter/gather PTE invalid error"; break;
+	case 0x215: reason = "flash ROM write error"; break;
+	case 0x217: reason = "IOA timeout detected"; break;
+	case 0x219: reason = "IOCHK#, EISA add-in board parity or other catastrophic error"; break;
+	case 0x21b: reason = "EISA fail-safe timer timeout"; break;
+	case 0x21d: reason = "EISA bus time-out"; break;
+	case 0x21f: reason = "EISA software generated NMI"; break;
+	case 0x221: reason = "unexpected ev5 IRQ[3] interrupt"; break;
+	default: reason = "unknown"; break;
+	}
+
+	printk(KERN_CRIT "machine check type: %s%s\n",
+	       reason, mchk_header->retry ? " (retryable)" : "");
+	
+#if DEBUG_MCHECK > 1
+	{
+		/* Dump the logout area to give all info.  */
+		unsigned long *ptr = (unsigned long *)la_ptr;
+		long i;
+		for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
+			printk(KERN_CRIT "   +%8lx %016lx %016lx\n",
+			       i*sizeof(long), ptr[i], ptr[i+1]);
+		}
+	}
+#endif
+}
diff -u --recursive --new-file v2.3.13/linux/arch/alpha/kernel/machvec.h linux/arch/alpha/kernel/machvec.h
--- v2.3.13/linux/arch/alpha/kernel/machvec.h	Mon Aug  9 14:59:19 1999
+++ linux/arch/alpha/kernel/machvec.h	Mon Aug 16 10:33:58 1999
@@ -71,7 +71,8 @@
 	mv_writew:		CAT(low1,_writew),			\
 	mv_writel:		CAT(low1,_writel),			\
 	mv_writeq:		CAT(low1,_writeq),			\
-	mv_dense_mem:		CAT(low2,_dense_mem)
+	mv_ioremap:		CAT(low2,_ioremap),			\
+	mv_is_ioaddr:		CAT(low2,_is_ioaddr)
 
 #define IO(UP,low1,low2)						\
 	IO_LITE(UP,low1,low2),						\
diff -u --recursive --new-file v2.3.13/linux/arch/alpha/kernel/proto.h linux/arch/alpha/kernel/proto.h
--- v2.3.13/linux/arch/alpha/kernel/proto.h	Mon Aug  9 14:59:19 1999
+++ linux/arch/alpha/kernel/proto.h	Fri Aug 13 11:53:50 1999
@@ -25,7 +25,7 @@
 
 extern volatile unsigned int apecs_mcheck_expected;
 extern volatile unsigned int apecs_mcheck_taken;
-extern int apecs_pci_clr_err(void);
+extern void apecs_pci_clr_err(void);
 extern void apecs_machine_check(u64, u64, struct pt_regs *);
 
 /* core_cia.c */
@@ -202,3 +202,28 @@
 
 /* ../mm/init.c */
 void srm_paging_stop(void);
+
+/* irq.h */
+
+#ifdef __SMP__
+#define mcheck_expected(cpu)	(cpu_data[cpu].mcheck_expected)
+#define mcheck_taken(cpu)	(cpu_data[cpu].mcheck_taken)
+#define mcheck_hose(cpu)	(cpu_data[cpu].mcheck_hose)
+#else
+extern struct mcheck_info
+{
+	unsigned char expected __attribute__((aligned(8)));
+	unsigned char taken;
+	unsigned char hose;
+} __mcheck_info;
+
+#define mcheck_expected(cpu)	(__mcheck_info.expected)
+#define mcheck_taken(cpu)	(__mcheck_info.taken)
+#define mcheck_hose(cpu)	(__mcheck_info.hose)
+#endif
+
+#define DEBUG_MCHECK 0          /* 0 = minimal, 1 = debug, 2 = debug+dump.  */
+
+extern void process_mcheck_info(unsigned long vector, unsigned long la_ptr,
+				struct pt_regs *regs, const char *machine,
+				int expected);
diff -u --recursive --new-file v2.3.13/linux/arch/alpha/kernel/setup.c linux/arch/alpha/kernel/setup.c
--- v2.3.13/linux/arch/alpha/kernel/setup.c	Wed Jun 30 13:38:18 1999
+++ linux/arch/alpha/kernel/setup.c	Fri Aug 13 11:53:50 1999
@@ -224,9 +224,15 @@
 	alpha_using_srm = strncmp((const char *)hwrpb->ssn, "MILO", 4) != 0;
 #endif
 
-	printk("Booting on %s%s%s using machine vector %s\n",
+	printk("Booting "
+#ifdef CONFIG_ALPHA_GENERIC
+	       "GENERIC "
+#endif
+	       "on %s%s%s using machine vector %s from %s\n",
 	       type_name, (*var_name ? " variation " : ""),
-	       var_name, alpha_mv.vector_name);
+	       var_name, alpha_mv.vector_name,
+	       (alpha_using_srm ? "SRM" : "MILO"));
+
 	printk("Command line: %s\n", command_line);
 
 	/* 
diff -u --recursive --new-file v2.3.13/linux/arch/alpha/kernel/smp.c linux/arch/alpha/kernel/smp.c
--- v2.3.13/linux/arch/alpha/kernel/smp.c	Mon Aug  9 14:59:19 1999
+++ linux/arch/alpha/kernel/smp.c	Fri Aug 13 11:53:50 1999
@@ -7,7 +7,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
-#include <linux/tasks.h>
+#include <linux/threads.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.3.13/linux/arch/alpha/kernel/sys_miata.c linux/arch/alpha/kernel/sys_miata.c
--- v2.3.13/linux/arch/alpha/kernel/sys_miata.c	Sun Feb 21 19:06:36 1999
+++ linux/arch/alpha/kernel/sys_miata.c	Fri Aug 13 11:53:50 1999
@@ -271,6 +271,17 @@
 	es1888_init();
 }
 
+static void
+miata_kill_arch (int mode, char *reboot_cmd)
+{
+	/* Who said DEC engineers have no sense of humor? ;-)  */
+	if (alpha_using_srm) {
+		*(vuip) PYXIS_RESET = 0x0000dead;
+		mb();
+	}
+	generic_kill_arch(mode, reboot_cmd);
+}
+
 
 /*
  * The System Vector
@@ -295,6 +306,6 @@
 	init_irq:		miata_init_irq,
 	init_pit:		generic_init_pit,
 	pci_fixup:		miata_pci_fixup,
-	kill_arch:		generic_kill_arch,
+	kill_arch:		miata_kill_arch,
 };
 ALIAS_MV(miata)
diff -u --recursive --new-file v2.3.13/linux/arch/alpha/kernel/sys_mikasa.c linux/arch/alpha/kernel/sys_mikasa.c
--- v2.3.13/linux/arch/alpha/kernel/sys_mikasa.c	Sun Sep  6 10:34:33 1998
+++ linux/arch/alpha/kernel/sys_mikasa.c	Fri Aug 13 11:53:50 1999
@@ -151,92 +151,34 @@
 	common_pci_fixup(mikasa_map_irq, common_swizzle);
 }
 
+#if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_PRIMO)
 static void
-mikasa_machine_check(unsigned long vector, unsigned long la_ptr,
-		     struct pt_regs * regs)
+mikasa_apecs_machine_check(unsigned long vector, unsigned long la_ptr,
+		           struct pt_regs * regs)
 {
 #define MCHK_NO_DEVSEL 0x205L
 #define MCHK_NO_TABT 0x204L
 
 	struct el_common *mchk_header;
-	struct el_apecs_procdata *mchk_procdata;
-	struct el_apecs_mikasa_sysdata_mcheck *mchk_sysdata;
-	unsigned long *ptr;
-	int i;
+	unsigned int code;
 
 	mchk_header = (struct el_common *)la_ptr;
 
-	mchk_procdata = (struct el_apecs_procdata *)
-		(la_ptr + mchk_header->proc_offset
-		 - sizeof(mchk_procdata->paltemp));
-
-	mchk_sysdata = (struct el_apecs_mikasa_sysdata_mcheck *)
-		(la_ptr + mchk_header->sys_offset);
-
-#ifdef DEBUG
-	printk("mikasa_machine_check: vector=0x%lx la_ptr=0x%lx\n",
-	       vector, la_ptr);
-	printk("        pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
-	       regs->pc, mchk_header->size, mchk_header->proc_offset,
-	       mchk_header->sys_offset);
-	printk("mikasa_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n",
-	       apecs_mcheck_expected, mchk_sysdata->epic_dcsr,
-	       mchk_sysdata->epic_pear);
-	ptr = (unsigned long *)la_ptr;
-	for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
-		printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]);
-	}
-#endif
-
-	/*
-	 * Check if machine check is due to a badaddr() and if so,
-	 * ignore the machine check.
-	 */
-
-	if (apecs_mcheck_expected
-	    && ((unsigned int)mchk_header->code == MCHK_NO_DEVSEL
-		|| (unsigned int)mchk_header->code == MCHK_NO_TABT)) {
-		apecs_mcheck_expected = 0;
-		apecs_mcheck_taken = 1;
-		mb();
-		mb(); /* magic */
-		apecs_pci_clr_err();
-		wrmces(0x7);
-		mb();
-		draina();
-	}
-	else if (vector == 0x620 || vector == 0x630) {
-		/* Disable correctable from now on.  */
-		wrmces(0x1f);
-		mb();
-		draina();
-		printk("mikasa_machine_check: HW correctable (0x%lx)\n",
-		       vector);
-	}
-	else {
-		printk(KERN_CRIT "APECS machine check:\n");
-		printk(KERN_CRIT "  vector=0x%lx la_ptr=0x%lx\n",
-		       vector, la_ptr);
-		printk(KERN_CRIT
-		       "  pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
-		       regs->pc, mchk_header->size, mchk_header->proc_offset,
-		       mchk_header->sys_offset);
-		printk(KERN_CRIT "  expected %d DCSR 0x%lx PEAR 0x%lx\n",
-		       apecs_mcheck_expected, mchk_sysdata->epic_dcsr,
-		       mchk_sysdata->epic_pear);
-
-		ptr = (unsigned long *)la_ptr;
-		for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
-			printk(KERN_CRIT " +%lx %lx %lx\n",
-			       i*sizeof(long), ptr[i], ptr[i+1]);
-		}
-#if 0
-		/* doesn't work with MILO */
-		show_regs(regs);
-#endif
-	}
+	/* Clear the error before any reporting.  */
+	mb();
+	mb(); /* magic */
+	draina();
+	apecs_pci_clr_err();
+	wrmces(0x7);
+	mb();
+
+	code = mchk_header->code;
+	process_mcheck_info(vector, la_ptr, regs, "MIKASA APECS",
+			    (mcheck_expected(0)
+			     && (code == MCHK_NO_DEVSEL
+			         || code == MCHK_NO_TABT)));
 }
-
+#endif
 
 /*
  * The System Vector
@@ -249,7 +191,7 @@
 	DO_DEFAULT_RTC,
 	DO_APECS_IO,
 	DO_APECS_BUS,
-	machine_check:		mikasa_machine_check,
+	machine_check:		mikasa_apecs_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
 
 	nr_irqs:		32,
@@ -274,7 +216,7 @@
 	DO_DEFAULT_RTC,
 	DO_CIA_IO,
 	DO_CIA_BUS,
-	machine_check:		mikasa_machine_check,
+	machine_check:		cia_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
 
 	nr_irqs:		32,
diff -u --recursive --new-file v2.3.13/linux/arch/alpha/kernel/sys_rx164.c linux/arch/alpha/kernel/sys_rx164.c
--- v2.3.13/linux/arch/alpha/kernel/sys_rx164.c	Sun Jan 24 21:29:53 1999
+++ linux/arch/alpha/kernel/sys_rx164.c	Fri Aug 13 11:53:50 1999
@@ -45,10 +45,10 @@
 		outb(mask, 0x21);	/* ISA PIC1 */
 }
 
+#if 0
 static void
 rx164_srm_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
 {
-#if 0
 	if (irq >= 16) {
 		if (unmask_p)
 			cserve_ena(irq - 16);
@@ -59,8 +59,8 @@
 		outb(mask >> 8, 0xA1);	/* ISA PIC2 */
 	else
 		outb(mask, 0x21);	/* ISA PIC1 */
-#endif
 }
+#endif
 
 static void
 rx164_isa_device_interrupt(unsigned long vector, struct pt_regs * regs)
@@ -107,7 +107,8 @@
         printk("PLD 0x%lx\n", pld);
 #endif
 
-        if (pld & 0xffffffff00000000UL) pld &= 0x00000000ffffffffUL;
+        if (pld & 0xffffffff00000000UL)
+		pld &= 0x00000000ffffffffUL;
 
         /*
          * Now for every possible bit set, work through them and call
diff -u --recursive --new-file v2.3.13/linux/arch/alpha/lib/io.c linux/arch/alpha/lib/io.c
--- v2.3.13/linux/arch/alpha/lib/io.c	Thu Apr 15 05:42:31 1999
+++ linux/arch/alpha/lib/io.c	Mon Aug 16 10:33:58 1999
@@ -37,45 +37,96 @@
 	__outl(b, addr);
 }
 
+unsigned long ___raw_readb(unsigned long addr)
+{
+	return __readb(addr);
+}
+
+unsigned long ___raw_readw(unsigned long addr)
+{
+	return __readw(addr);
+}
+
+unsigned long ___raw_readl(unsigned long addr)
+{
+	return __readl(addr);
+}
+
+unsigned long ___raw_readq(unsigned long addr)
+{
+	return __readq(addr);
+}
 
 unsigned long _readb(unsigned long addr)
 {
-	return __readb(addr);
+	unsigned long r = __readb(addr);
+	mb();
+	return r;
 }
 
 unsigned long _readw(unsigned long addr)
 {
-	return __readw(addr);
+	unsigned long r = __readw(addr);
+	mb();
+	return r;
 }
 
 unsigned long _readl(unsigned long addr)
 {
-	return __readl(addr);
+	unsigned long r = __readl(addr);
+	mb();
+	return r;
 }
 
 unsigned long _readq(unsigned long addr)
 {
-	return __readq(addr);
+	unsigned long r = __readq(addr);
+	mb();
+	return r;
+}
+
+void ___raw_writeb(unsigned char b, unsigned long addr)
+{
+	__writeb(b, addr);
+}
+
+void ___raw_writeb(unsigned short b, unsigned long addr)
+{
+	__writew(b, addr);
+}
+
+void ___raw_writel(unsigned int b, unsigned long addr)
+{
+	__writel(b, addr);
+}
+
+void ___raw_writeq(unsigned long b, unsigned long addr)
+{
+	__writeq(b, addr);
 }
 
 void _writeb(unsigned char b, unsigned long addr)
 {
 	__writeb(b, addr);
+	mb();
 }
 
 void _writew(unsigned short b, unsigned long addr)
 {
 	__writew(b, addr);
+	mb();
 }
 
 void _writel(unsigned int b, unsigned long addr)
 {
 	__writel(b, addr);
+	mb();
 }
 
 void _writeq(unsigned long b, unsigned long addr)
 {
 	__writeq(b, addr);
+	mb();
 }
 
 /*
@@ -363,7 +414,7 @@
 	if (count >= 8 && ((long)to & 7) == (from & 7)) {
 		count -= 8;
 		do {
-			*(u64 *)to = readq(from);
+			*(u64 *)to = __raw_readq(from);
 			count -= 8;
 			to += 8;
 			from += 8;
@@ -374,7 +425,7 @@
 	if (count >= 4 && ((long)to & 3) == (from & 3)) {
 		count -= 4;
 		do {
-			*(u32 *)to = readl(from);
+			*(u32 *)to = __raw_readl(from);
 			count -= 4;
 			to += 4;
 			from += 4;
@@ -385,7 +436,7 @@
 	if (count >= 2 && ((long)to & 1) == (from & 1)) {
 		count -= 2;
 		do {
-			*(u16 *)to = readw(from);
+			*(u16 *)to = __raw_readw(from);
 			count -= 2;
 			to += 2;
 			from += 2;
@@ -394,7 +445,7 @@
 	}
 
 	while (count > 0) {
-		*(u8 *) to = readb(from);
+		*(u8 *) to = __raw_readb(from);
 		count--;
 		to++;
 		from++;
@@ -414,7 +465,7 @@
 	if (count >= 8 && (to & 7) == ((long)from & 7)) {
 		count -= 8;
 		do {
-			writeq(*(const u64 *)from, to);
+			__raw_writeq(*(const u64 *)from, to);
 			count -= 8;
 			to += 8;
 			from += 8;
@@ -425,7 +476,7 @@
 	if (count >= 4 && (to & 3) == ((long)from & 3)) {
 		count -= 4;
 		do {
-			writel(*(const u32 *)from, to);
+			__raw_writel(*(const u32 *)from, to);
 			count -= 4;
 			to += 4;
 			from += 4;
@@ -436,7 +487,7 @@
 	if (count >= 2 && (to & 1) == ((long)from & 1)) {
 		count -= 2;
 		do {
-			writew(*(const u16 *)from, to);
+			__raw_writeb(*(const u16 *)from, to);
 			count -= 2;
 			to += 2;
 			from += 2;
@@ -445,11 +496,12 @@
 	}
 
 	while (count > 0) {
-		writeb(*(const u8 *) from, to);
+		__raw_writeb(*(const u8 *) from, to);
 		count--;
 		to++;
 		from++;
 	}
+	mb();
 }
 
 /*
@@ -459,21 +511,21 @@
 {
 	/* Handle any initial odd byte */
 	if (count > 0 && (to & 1)) {
-		writeb(c, to);
+		__raw_writeb(c, to);
 		to++;
 		count--;
 	}
 
 	/* Handle any initial odd halfword */
 	if (count >= 2 && (to & 2)) {
-		writew(c, to);
+		__raw_writeb(c, to);
 		to += 2;
 		count -= 2;
 	}
 
 	/* Handle any initial odd word */
 	if (count >= 4 && (to & 4)) {
-		writel(c, to);
+		__raw_writel(c, to);
 		to += 4;
 		count -= 4;
 	}
@@ -483,7 +535,7 @@
 	count -= 8;
 	if (count >= 0) {
 		do {
-			writeq(c, to);
+			__raw_writeq(c, to);
 			to += 8;
 			count -= 8;
 		} while (count >= 0);
@@ -492,20 +544,21 @@
 
 	/* The tail is word-aligned if we still have count >= 4 */
 	if (count >= 4) {
-		writel(c, to);
+		__raw_writel(c, to);
 		to += 4;
 		count -= 4;
 	}
 
 	/* The tail is half-word aligned if we have count >= 2 */
 	if (count >= 2) {
-		writew(c, to);
+		__raw_writeb(c, to);
 		to += 2;
 		count -= 2;
 	}
 
 	/* And finally, one last byte.. */
 	if (count) {
-		writeb(c, to);
+		__raw_writeb(c, to);
 	}
+	mb();
 }
diff -u --recursive --new-file v2.3.13/linux/arch/alpha/mm/fault.c linux/arch/alpha/mm/fault.c
--- v2.3.13/linux/arch/alpha/mm/fault.c	Mon Aug  9 14:59:19 1999
+++ linux/arch/alpha/mm/fault.c	Fri Aug 13 11:53:50 1999
@@ -22,6 +22,7 @@
 #include <linux/mman.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
+#include <linux/interrupt.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.3.13/linux/arch/i386/Makefile linux/arch/i386/Makefile
--- v2.3.13/linux/arch/i386/Makefile	Wed Jul 21 15:46:48 1999
+++ linux/arch/i386/Makefile	Thu Aug 12 11:53:22 1999
@@ -35,8 +35,8 @@
 endif
 
 ifdef CONFIG_M486
-CFLAGS := $(CFLAGS) -m486 -DCPU=486
-CFLAGS += $(shell if $(CC) -march=i486 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=i486"; fi)
+CFLAGS := $(CFLAGS) -DCPU=486
+CFLAGS += $(shell if $(CC) -march=i486 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=i486"; else echo "-m486"; fi)
 AFLAGS := $(AFLAGS) -DCPU=486
 endif
 
@@ -111,6 +111,7 @@
 	@$(MAKEBOOT) clean
 
 archmrproper:
+	rm -f arch/i386/vmlinux.lds
 
 archdep:
 	@$(MAKEBOOT) dep
diff -u --recursive --new-file v2.3.13/linux/arch/i386/boot/bootsect.S linux/arch/i386/boot/bootsect.S
--- v2.3.13/linux/arch/i386/boot/bootsect.S	Tue Jun  8 10:47:57 1999
+++ linux/arch/i386/boot/bootsect.S	Wed Aug 18 10:03:05 1999
@@ -98,7 +98,7 @@
  *		fs = 0, gs is unused.
  */
 
-! cx contains 0 from rep movsw above
+! cx contains 0 from rep movsd above
 
 	mov	fs,cx
 	mov	bx,#0x78		! fs:bx is parameter table address
diff -u --recursive --new-file v2.3.13/linux/arch/i386/config.in linux/arch/i386/config.in
--- v2.3.13/linux/arch/i386/config.in	Mon Aug  9 14:59:19 1999
+++ linux/arch/i386/config.in	Wed Aug 18 11:18:11 1999
@@ -167,6 +167,8 @@
 
 source drivers/usb/Config.in
 
+source drivers/misc/Config.in
+
 source fs/Config.in
 
 if [ "$CONFIG_VT" = "y" ]; then
diff -u --recursive --new-file v2.3.13/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.3.13/linux/arch/i386/defconfig	Mon Aug  9 14:59:19 1999
+++ linux/arch/i386/defconfig	Sun Aug 15 16:02:03 1999
@@ -70,6 +70,12 @@
 # CONFIG_I2O_PROC is not set
 
 #
+# Plug and Play configuration
+#
+CONFIG_PNP=y
+CONFIG_ISAPNP=y
+
+#
 # Block devices
 #
 CONFIG_BLK_DEV_FD=y
@@ -331,6 +337,10 @@
 # CONFIG_USB is not set
 
 #
+# Misc devices
+#
+
+#
 # Filesystems
 #
 # CONFIG_QUOTA is not set
@@ -366,10 +376,9 @@
 #
 # Partition Types
 #
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_MAC_PARTITION is not set
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
 # CONFIG_SMD_DISKLABEL is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_SGI_DISKLABEL is not set
 # CONFIG_NLS is not set
 
diff -u --recursive --new-file v2.3.13/linux/arch/i386/kernel/Makefile linux/arch/i386/kernel/Makefile
--- v2.3.13/linux/arch/i386/kernel/Makefile	Mon Aug  9 14:59:19 1999
+++ linux/arch/i386/kernel/Makefile	Wed Aug 18 11:11:15 1999
@@ -14,7 +14,7 @@
 
 O_TARGET := kernel.o
 O_OBJS   := process.o signal.o entry.o traps.o irq.o vm86.o \
-            ptrace.o ioport.o ldt.o setup.o time.o sys_i386.o
+	    ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o
 OX_OBJS  := i386_ksyms.o
 MX_OBJS  :=
 
diff -u --recursive --new-file v2.3.13/linux/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c
--- v2.3.13/linux/arch/i386/kernel/apm.c	Mon Aug  9 14:59:19 1999
+++ linux/arch/i386/kernel/apm.c	Thu Aug 12 11:53:22 1999
@@ -288,7 +288,7 @@
 /*
  * Local variables
  */
-static asmlinkage struct {
+static struct {
 	unsigned long	offset;
 	unsigned short	segment;
 }				apm_bios_entry;
diff -u --recursive --new-file v2.3.13/linux/arch/i386/kernel/bios32.c linux/arch/i386/kernel/bios32.c
--- v2.3.13/linux/arch/i386/kernel/bios32.c	Mon Aug  9 14:59:19 1999
+++ linux/arch/i386/kernel/bios32.c	Wed Aug 18 11:24:23 1999
@@ -93,7 +93,7 @@
 #include <asm/smp.h>
 #include <asm/spinlock.h>
 
-#include "irq.h"
+#include <linux/irq.h>
 
 #undef DEBUG
 
@@ -353,7 +353,7 @@
  * This should be close to trivial, but it isn't, because there are buggy
  * chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
  */
-__initfunc(int pci_sanity_check(struct pci_access *a))
+int __init pci_sanity_check(struct pci_access *a)
 {
 	u16 dfn, x;
 
@@ -373,7 +373,7 @@
 	return 0;
 }
 
-__initfunc(static struct pci_access *pci_check_direct(void))
+static struct pci_access * __init pci_check_direct(void)
 {
 	unsigned int tmp;
 	unsigned long flags;
@@ -528,7 +528,7 @@
 
 static int pci_bios_present;
 
-__initfunc(static int check_pcibios(void))
+static int __init check_pcibios(void)
 {
 	u32 signature, eax, ebx, ecx;
 	u8 status, major_ver, minor_ver, hw_mech, last_bus;
@@ -602,8 +602,8 @@
 
 #endif
 
-__initfunc(static int pci_bios_find_device (unsigned short vendor, unsigned short device_id,
-	unsigned short index, unsigned char *bus, unsigned char *device_fn))
+static int __init pci_bios_find_device (unsigned short vendor, unsigned short device_id,
+	unsigned short index, unsigned char *bus, unsigned char *device_fn)
 {
 	unsigned short bx;
 	unsigned short ret;
@@ -756,7 +756,7 @@
  * Try to find PCI BIOS.
  */
 
-__initfunc(static struct pci_access *pci_find_bios(void))
+static struct pci_access * __init pci_find_bios(void)
 {
 	union bios32 *check;
 	unsigned char sum;
@@ -1194,7 +1194,7 @@
  * Arch-dependent fixups.
  */
 
-__initfunc(void pcibios_fixup(void))
+void __init pcibios_fixup(void)
 {
 	if (!(pci_probe & PCI_NO_PEER_FIXUP))
 		pcibios_fixup_peer_bridges();
@@ -1206,7 +1206,7 @@
 #endif
 }
 
-__initfunc(void pcibios_fixup_bus(struct pci_bus *b))
+void __init pcibios_fixup_bus(struct pci_bus *b)
 {
 	pcibios_fixup_ghosts(b);
 	pcibios_scan_buglist(b);
@@ -1219,7 +1219,7 @@
  * compatible with 2.0.X. This should go away in 2.3.
  */
 
-__initfunc(void pcibios_init(void))
+void __init pcibios_init(void)
 {
 	struct pci_access *bios = NULL;
 	struct pci_access *dir = NULL;
diff -u --recursive --new-file v2.3.13/linux/arch/i386/kernel/i8259.c linux/arch/i386/kernel/i8259.c
--- v2.3.13/linux/arch/i386/kernel/i8259.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/i386/kernel/i8259.c	Wed Aug 18 11:23:31 1999
@@ -0,0 +1,410 @@
+#include <linux/config.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/kernel_stat.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <linux/malloc.h>
+#include <linux/random.h>
+#include <linux/smp.h>
+#include <linux/tasks.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/smp.h>
+#include <asm/pgtable.h>
+#include <asm/delay.h>
+#include <asm/desc.h>
+
+#include <linux/irq.h>
+
+
+/*
+ * Intel specific no controller code
+ * odd that no-controller should be architecture dependent
+ * but see the ifdef __SMP__ 
+ */
+
+static void enable_none(unsigned int irq) { }
+static unsigned int startup_none(unsigned int irq) { return 0; }
+static void disable_none(unsigned int irq) { }
+static void ack_none(unsigned int irq)
+{
+#ifdef __SMP__
+	/*
+	 * [currently unexpected vectors happen only on SMP and APIC.
+	 *  if we want to have non-APIC and non-8259A controllers
+	 *  in the future with unexpected vectors, this ack should
+	 *  probably be made controller-specific.]
+	 */
+	ack_APIC_irq();
+#endif
+}
+
+/* startup is the same as "enable", shutdown is same as "disable" */
+#define shutdown_none	disable_none
+#define end_none	enable_none
+
+struct hw_interrupt_type no_irq_type = {
+	"none",
+	startup_none,
+	shutdown_none,
+	enable_none,
+	disable_none,
+	ack_none,
+	end_none
+};
+
+
+/*
+ * This is the 'legacy' 8259A Programmable Interrupt Controller,
+ * present in the majority of PC/AT boxes.
+ * plus some generic x86 specific things if generic specifics makes
+ * any sense at all.
+ * this file should become arch/i386/kernel/irq.c when the old irq.c
+ * moves to arch independent land
+ */
+/*
+ * This builds up the IRQ handler stubs using some ugly macros in irq.h
+ *
+ * These macros create the low-level assembly IRQ routines that save
+ * register context and call do_IRQ(). do_IRQ() then does all the
+ * operations that are needed to keep the AT (or SMP IOAPIC)
+ * interrupt-controller happy.
+ */
+
+
+BUILD_COMMON_IRQ()
+
+#define BI(x,y) \
+	BUILD_IRQ(##x##y)
+
+#define BUILD_16_IRQS(x) \
+	BI(x,0) BI(x,1) BI(x,2) BI(x,3) \
+	BI(x,4) BI(x,5) BI(x,6) BI(x,7) \
+	BI(x,8) BI(x,9) BI(x,a) BI(x,b) \
+	BI(x,c) BI(x,d) BI(x,e) BI(x,f)
+
+/*
+ * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
+ * (these are usually mapped to vectors 0x20-0x30)
+ */
+BUILD_16_IRQS(0x0)
+
+#ifdef CONFIG_X86_IO_APIC
+/*
+ * The IO-APIC gives us many more interrupt sources. Most of these 
+ * are unused but an SMP system is supposed to have enough memory ...
+ * sometimes (mostly wrt. hw bugs) we get corrupted vectors all
+ * across the spectrum, so we really want to be prepared to get all
+ * of these. Plus, more powerful systems might have more than 64
+ * IO-APIC registers.
+ *
+ * (these are usually mapped into the 0x30-0xff vector range)
+ */
+		   BUILD_16_IRQS(0x1) BUILD_16_IRQS(0x2) BUILD_16_IRQS(0x3)
+BUILD_16_IRQS(0x4) BUILD_16_IRQS(0x5) BUILD_16_IRQS(0x6) BUILD_16_IRQS(0x7)
+BUILD_16_IRQS(0x8) BUILD_16_IRQS(0x9) BUILD_16_IRQS(0xa) BUILD_16_IRQS(0xb)
+BUILD_16_IRQS(0xc) BUILD_16_IRQS(0xd)
+#endif
+
+#undef BUILD_16_IRQS
+#undef BI
+
+
+#ifdef __SMP__
+/*
+ * The following vectors are part of the Linux architecture, there
+ * is no hardware IRQ pin equivalent for them, they are triggered
+ * through the ICC by us (IPIs)
+ */
+BUILD_SMP_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR)
+BUILD_SMP_INTERRUPT(invalidate_interrupt,INVALIDATE_TLB_VECTOR)
+BUILD_SMP_INTERRUPT(stop_cpu_interrupt,STOP_CPU_VECTOR)
+BUILD_SMP_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR)
+BUILD_SMP_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR)
+
+/*
+ * every pentium local APIC has two 'local interrupts', with a
+ * soft-definable vector attached to both interrupts, one of
+ * which is a timer interrupt, the other one is error counter
+ * overflow. Linux uses the local APIC timer interrupt to get
+ * a much simpler SMP time architecture:
+ */
+BUILD_SMP_TIMER_INTERRUPT(apic_timer_interrupt,LOCAL_TIMER_VECTOR)
+
+#endif
+
+#define IRQ(x,y) \
+	IRQ##x##y##_interrupt
+
+#define IRQLIST_16(x) \
+	IRQ(x,0), IRQ(x,1), IRQ(x,2), IRQ(x,3), \
+	IRQ(x,4), IRQ(x,5), IRQ(x,6), IRQ(x,7), \
+	IRQ(x,8), IRQ(x,9), IRQ(x,a), IRQ(x,b), \
+	IRQ(x,c), IRQ(x,d), IRQ(x,e), IRQ(x,f)
+
+static void (*interrupt[NR_IRQS])(void) = {
+	IRQLIST_16(0x0),
+
+#ifdef CONFIG_X86_IO_APIC
+			 IRQLIST_16(0x1), IRQLIST_16(0x2), IRQLIST_16(0x3),
+	IRQLIST_16(0x4), IRQLIST_16(0x5), IRQLIST_16(0x6), IRQLIST_16(0x7),
+	IRQLIST_16(0x8), IRQLIST_16(0x9), IRQLIST_16(0xa), IRQLIST_16(0xb),
+	IRQLIST_16(0xc), IRQLIST_16(0xd)
+#endif
+};
+
+#undef IRQ
+#undef IRQLIST_16
+
+
+
+
+static void enable_8259A_irq(unsigned int irq);
+void disable_8259A_irq(unsigned int irq);
+
+/* shutdown is same as "disable" */
+#define end_8259A_irq		enable_8259A_irq
+#define shutdown_8259A_irq	disable_8259A_irq
+
+static void mask_and_ack_8259A(unsigned int);
+
+static unsigned int startup_8259A_irq(unsigned int irq)
+{ 
+	enable_8259A_irq(irq);
+	return 0; /* never anything pending */
+}
+
+static struct hw_interrupt_type i8259A_irq_type = {
+	"XT-PIC",
+	startup_8259A_irq,
+	shutdown_8259A_irq,
+	enable_8259A_irq,
+	disable_8259A_irq,
+	mask_and_ack_8259A,
+	end_8259A_irq
+};
+
+/*
+ * 8259A PIC functions to handle ISA devices:
+ */
+
+/*
+ * This contains the irq mask for both 8259A irq controllers,
+ */
+static unsigned int cached_irq_mask = 0xffff;
+
+#define __byte(x,y) 	(((unsigned char *)&(y))[x])
+#define cached_21	(__byte(0,cached_irq_mask))
+#define cached_A1	(__byte(1,cached_irq_mask))
+
+/*
+ * Not all IRQs can be routed through the IO-APIC, eg. on certain (older)
+ * boards the timer interrupt is not connected to any IO-APIC pin, it's
+ * fed to the CPU IRQ line directly.
+ *
+ * Any '1' bit in this mask means the IRQ is routed through the IO-APIC.
+ * this 'mixed mode' IRQ handling costs nothing because it's only used
+ * at IRQ setup time.
+ */
+unsigned long io_apic_irqs = 0;
+
+/*
+ * These have to be protected by the irq controller spinlock
+ * before being called.
+ */
+void disable_8259A_irq(unsigned int irq)
+{
+	unsigned int mask = 1 << irq;
+	cached_irq_mask |= mask;
+	if (irq & 8) {
+		outb(cached_A1,0xA1);
+	} else {
+		outb(cached_21,0x21);
+	}
+}
+
+static void enable_8259A_irq(unsigned int irq)
+{
+	unsigned int mask = ~(1 << irq);
+	cached_irq_mask &= mask;
+	if (irq & 8) {
+		outb(cached_A1,0xA1);
+	} else {
+		outb(cached_21,0x21);
+	}
+}
+
+int i8259A_irq_pending(unsigned int irq)
+{
+	unsigned int mask = 1<<irq;
+
+	if (irq < 8)
+		return (inb(0x20) & mask);
+	return (inb(0xA0) & (mask >> 8));
+}
+
+void make_8259A_irq(unsigned int irq)
+{
+	disable_irq_nosync(irq);
+	io_apic_irqs &= ~(1<<irq);
+	irq_desc[irq].handler = &i8259A_irq_type;
+	enable_irq(irq);
+}
+
+/*
+ * Careful! The 8259A is a fragile beast, it pretty
+ * much _has_ to be done exactly like this (mask it
+ * first, _then_ send the EOI, and the order of EOI
+ * to the two 8259s is important!
+ */
+static void mask_and_ack_8259A(unsigned int irq)
+{
+	cached_irq_mask |= 1 << irq;
+	if (irq & 8) {
+		inb(0xA1);	/* DUMMY */
+		outb(cached_A1,0xA1);
+		outb(0x62,0x20);	/* Specific EOI to cascade */
+		outb(0x20,0xA0);
+	} else {
+		inb(0x21);	/* DUMMY */
+		outb(cached_21,0x21);
+		outb(0x20,0x20);
+	}
+}
+
+#ifndef CONFIG_VISWS
+/*
+ * Note that on a 486, we don't want to do a SIGFPE on an irq13
+ * as the irq is unreliable, and exception 16 works correctly
+ * (ie as explained in the intel literature). On a 386, you
+ * can't use exception 16 due to bad IBM design, so we have to
+ * rely on the less exact irq13.
+ *
+ * Careful.. Not only is IRQ13 unreliable, but it is also
+ * leads to races. IBM designers who came up with it should
+ * be shot.
+ */
+ 
+static void math_error_irq(int cpl, void *dev_id, struct pt_regs *regs)
+{
+	outb(0,0xF0);
+	if (ignore_irq13 || !boot_cpu_data.hard_math)
+		return;
+	math_error();
+}
+
+static struct irqaction irq13 = { math_error_irq, 0, 0, "fpu", NULL, NULL };
+
+/*
+ * IRQ2 is cascade interrupt to second interrupt controller
+ */
+
+static struct irqaction irq2  = { no_action, 0, 0, "cascade", NULL, NULL};
+#endif
+
+
+void init_ISA_irqs (void)
+{
+	int i;
+
+	for (i = 0; i < NR_IRQS; i++) {
+		irq_desc[i].status = IRQ_DISABLED;
+		irq_desc[i].action = 0;
+		irq_desc[i].depth = 0;
+
+		if (i < 16) {
+			/*
+			 * 16 old-style INTA-cycle interrupts:
+			 */
+			irq_desc[i].handler = &i8259A_irq_type;
+		} else {
+			/*
+			 * 'high' PCI IRQs filled in on demand
+			 */
+			irq_desc[i].handler = &no_irq_type;
+		}
+	}
+}
+
+void __init init_IRQ(void)
+{
+	int i;
+
+#ifndef CONFIG_X86_VISWS_APIC
+	init_ISA_irqs();
+#else
+	init_VISWS_APIC_irqs();
+#endif
+	/*
+	 * Cover the whole vector space, no vector can escape
+	 * us. (some of these will be overridden and become
+	 * 'special' SMP interrupts)
+	 */
+	for (i = 0; i < NR_IRQS; i++) {
+		int vector = FIRST_EXTERNAL_VECTOR + i;
+		if (vector != SYSCALL_VECTOR) 
+			set_intr_gate(vector, interrupt[i]);
+	}
+
+#ifdef __SMP__	
+
+	/*
+	  IRQ0 must be given a fixed assignment and initialized
+	  before init_IRQ_SMP.
+	*/
+	set_intr_gate(IRQ0_TRAP_VECTOR, interrupt[0]);
+
+	/*
+	 * The reschedule interrupt is a CPU-to-CPU reschedule-helper
+	 * IPI, driven by wakeup.
+	 */
+	set_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
+
+	/* IPI for invalidation */
+	set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);
+
+	/* IPI for CPU halt */
+	set_intr_gate(STOP_CPU_VECTOR, stop_cpu_interrupt);
+
+	/* self generated IPI for local APIC timer */
+	set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
+
+	/* IPI for generic function call */
+	set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
+
+	/* IPI vector for APIC spurious interrupts */
+	set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
+#endif	
+
+	/*
+	 * Set the clock to 100 Hz, we already have a valid
+	 * vector now:
+	 */
+	outb_p(0x34,0x43);		/* binary, mode 2, LSB/MSB, ch 0 */
+	outb_p(LATCH & 0xff , 0x40);	/* LSB */
+	outb(LATCH >> 8 , 0x40);	/* MSB */
+
+#ifndef CONFIG_VISWS
+	setup_irq(2, &irq2);
+	setup_irq(13, &irq13);
+#endif
+}
+
+#ifdef CONFIG_X86_IO_APIC
+void __init init_IRQ_SMP(void)
+{
+	int i;
+	for (i = 0; i < NR_IRQS ; i++)
+		if (IO_APIC_VECTOR(i) > 0)
+			set_intr_gate(IO_APIC_VECTOR(i), interrupt[i]);
+}
+#endif
diff -u --recursive --new-file v2.3.13/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c
--- v2.3.13/linux/arch/i386/kernel/io_apic.c	Mon Aug  9 14:59:19 1999
+++ linux/arch/i386/kernel/io_apic.c	Wed Aug 18 11:11:15 1999
@@ -19,7 +19,7 @@
 #include <linux/delay.h>
 #include <asm/io.h>
 
-#include "irq.h"
+#include <linux/irq.h>
 
 /*
  * volatile is justified in this case, IO-APIC register contents
@@ -957,24 +957,13 @@
  * better to do it this way as thus we do not have to be aware of
  * 'pending' interrupts in the IRQ path, except at this point.
  */
-static inline void self_IPI(unsigned int irq)
-{
-	irq_desc_t *desc = irq_desc + irq;
-	unsigned int status = desc->status;
-
-	if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
-		desc->status = status | IRQ_REPLAY;
-		send_IPI_self(IO_APIC_VECTOR(irq));
-	}
-}
-
 /*
  * Edge triggered needs to resend any interrupt
- * that was delayed.
+ * that was delayed but this is now handled in the device
+ * independent code.
  */
 static void enable_edge_ioapic_irq(unsigned int irq)
 {
-	self_IPI(irq);
 	enable_IO_APIC_irq(irq);
 }
 
@@ -987,129 +976,52 @@
  * Starting up a edge-triggered IO-APIC interrupt is
  * nasty - we need to make sure that we get the edge.
  * If it is already asserted for some reason, we need
- * to fake an edge by marking it IRQ_PENDING..
+ * return 1 to indicate that is was pending.
  *
  * This is not complete - we should be able to fake
  * an edge even if it isn't on the 8259A...
  */
 
-static void startup_edge_ioapic_irq(unsigned int irq)
+static unsigned int startup_edge_ioapic_irq(unsigned int irq)
 {
+	int was_pending = 0;
 	if (irq < 16) {
 		disable_8259A_irq(irq);
 		if (i8259A_irq_pending(irq))
-			irq_desc[irq].status |= IRQ_PENDING;
+			was_pending = 1;
 	}
 	enable_edge_ioapic_irq(irq);
+	return was_pending;
 }
 
 #define shutdown_edge_ioapic_irq	disable_edge_ioapic_irq
+void static ack_edge_ioapic_irq(unsigned int i)
+{
+	ack_APIC_irq();
+}
+void static end_edge_ioapic_irq(unsigned int i){}
+
 
 /*
  * Level triggered interrupts can just be masked,
  * and shutting down and starting up the interrupt
- * is the same as enabling and disabling them.
+ * is the same as enabling and disabling them -- except
+ * with a startup need to return a "was pending" value.
  */
-#define startup_level_ioapic_irq	unmask_IO_APIC_irq
-#define shutdown_level_ioapic_irq	mask_IO_APIC_irq
-#define enable_level_ioapic_irq		unmask_IO_APIC_irq
-#define disable_level_ioapic_irq	mask_IO_APIC_irq
-
-static void do_edge_ioapic_IRQ(unsigned int irq, struct pt_regs * regs)
+static unsigned int startup_level_ioapic_irq(unsigned int irq)
 {
-	irq_desc_t *desc = irq_desc + irq;
-	struct irqaction * action;
-	unsigned int status;
-
-	spin_lock(&irq_controller_lock);
-
-	/*
-	 * Edge triggered IRQs can be acknowledged immediately
-	 * and do not need to be masked.
-	 */
-	ack_APIC_irq();
-	status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
-	status |= IRQ_PENDING;
-
-	/*
-	 * If the IRQ is disabled for whatever reason, we cannot
-	 * use the action we have.
-	 */
-	action = NULL;
-	if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
-		action = desc->action;
-		status &= ~IRQ_PENDING;
-		status |= IRQ_INPROGRESS;
-	}
-	desc->status = status;
-	spin_unlock(&irq_controller_lock);
-
-	/*
-	 * If there is no IRQ handler or it was disabled, exit early.
-	 */
-	if (!action)
-		return;
-
-	/*
-	 * Edge triggered interrupts need to remember
-	 * pending events.
-	 */
-	for (;;) {
-		handle_IRQ_event(irq, regs, action);
-
-		spin_lock(&irq_controller_lock);
-		if (!(desc->status & IRQ_PENDING))
-			break;
-		desc->status &= ~IRQ_PENDING;
-		spin_unlock(&irq_controller_lock);
-	}
-	desc->status &= ~IRQ_INPROGRESS;
-	spin_unlock(&irq_controller_lock);
+	unmask_IO_APIC_irq(irq);
+	return 0; /* don't check for pending */
 }
 
-static void do_level_ioapic_IRQ(unsigned int irq, struct pt_regs * regs)
+#define shutdown_level_ioapic_irq	mask_IO_APIC_irq
+#define enable_level_ioapic_irq		unmask_IO_APIC_irq
+#define disable_level_ioapic_irq	mask_IO_APIC_irq
+#define end_level_ioapic_irq		unmask_IO_APIC_irq	
+void static mask_and_ack_level_ioapic_irq(unsigned int i)
 {
-	irq_desc_t *desc = irq_desc + irq;
-	struct irqaction * action;
-	unsigned int status;
-
-	spin_lock(&irq_controller_lock);
-	/*
-	 * In the level triggered case we first disable the IRQ
-	 * in the IO-APIC, then we 'early ACK' the IRQ, then we
-	 * handle it and enable the IRQ when finished.
-	 *
-	 * disable has to happen before the ACK, to avoid IRQ storms.
-	 * So this all has to be within the spinlock.
-	 */
-	mask_IO_APIC_irq(irq);
-	status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
-
-	/*
-	 * If the IRQ is disabled for whatever reason, we must
-	 * not enter the IRQ action.
-	 */
-	action = NULL;
-	if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
-		action = desc->action;
-		status |= IRQ_INPROGRESS;
-	}
-	desc->status = status;
-
+	mask_IO_APIC_irq(i);
 	ack_APIC_irq();
-	spin_unlock(&irq_controller_lock);
-
-	/* Exit early if we had no action or it was disabled */
-	if (!action)
-		return;
-
-	handle_IRQ_event(irq, regs, action);
-
-	spin_lock(&irq_controller_lock);
-	desc->status &= ~IRQ_INPROGRESS;
-	if (!(desc->status & IRQ_DISABLED))
-		unmask_IO_APIC_irq(irq);
-	spin_unlock(&irq_controller_lock);
 }
 
 /*
@@ -1125,18 +1037,20 @@
 	"IO-APIC-edge",
 	startup_edge_ioapic_irq,
 	shutdown_edge_ioapic_irq,
-	do_edge_ioapic_IRQ,
 	enable_edge_ioapic_irq,
-	disable_edge_ioapic_irq
+	disable_edge_ioapic_irq,
+	ack_edge_ioapic_irq,
+	end_edge_ioapic_irq
 };
 
 static struct hw_interrupt_type ioapic_level_irq_type = {
 	"IO-APIC-level",
 	startup_level_ioapic_irq,
 	shutdown_level_ioapic_irq,
-	do_level_ioapic_IRQ,
 	enable_level_ioapic_irq,
-	disable_level_ioapic_irq
+	disable_level_ioapic_irq,
+	mask_and_ack_level_ioapic_irq,
+	end_level_ioapic_irq
 };
 
 static inline void init_IO_APIC_traps(void)
diff -u --recursive --new-file v2.3.13/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
--- v2.3.13/linux/arch/i386/kernel/irq.c	Mon Aug  9 14:59:19 1999
+++ linux/arch/i386/kernel/irq.c	Wed Aug 18 11:17:37 1999
@@ -1,3 +1,8 @@
+/* mostly architecture independent
+   some moved to i8259.c
+   the beautiful visws architecture code needs to be updated too.
+   and, finally, the BUILD_IRQ and SMP_BUILD macros in irq.h need fixed.
+   */
 /*
  *	linux/arch/i386/kernel/irq.c
  *
@@ -32,14 +37,14 @@
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/irq.h>
 #include <asm/bitops.h>
 #include <asm/smp.h>
 #include <asm/pgtable.h>
 #include <asm/delay.h>
 #include <asm/desc.h>
+#include <asm/irq.h>
+#include <linux/irq.h>
 
-#include "irq.h"
 
 unsigned int local_bh_count[NR_CPUS];
 unsigned int local_irq_count[NR_CPUS];
@@ -67,334 +72,18 @@
  * system. We never hold this lock when we call the actual
  * IRQ handler.
  */
-spinlock_t irq_controller_lock;
-
-/*
- * Dummy controller type for unused interrupts
- */
-static void do_none(unsigned int irq, struct pt_regs * regs)
-{
-	/*
-	 * we are careful. While for ISA irqs it's common to happen
-	 * outside of any driver (think autodetection), this is not
-	 * at all nice for PCI interrupts. So we are stricter and
-	 * print a warning when such spurious interrupts happen.
-	 * Spurious interrupts can confuse other drivers if the PCI
-	 * IRQ line is shared.
-	 *
-	 * Such spurious interrupts are either driver bugs, or
-	 * sometimes hw (chipset) bugs.
-	 */
-	printk("unexpected IRQ vector %d on CPU#%d!\n",irq, smp_processor_id());
-
-#ifdef __SMP__
-	/*
-	 * [currently unexpected vectors happen only on SMP and APIC.
-	 *  if we want to have non-APIC and non-8259A controllers
-	 *  in the future with unexpected vectors, this ack should
-	 *  probably be made controller-specific.]
-	 */
-	ack_APIC_irq();
-#endif
-}
-static void enable_none(unsigned int irq) { }
-static void disable_none(unsigned int irq) { }
-
-/* startup is the same as "enable", shutdown is same as "disable" */
-#define startup_none	enable_none
-#define shutdown_none	disable_none
-
-struct hw_interrupt_type no_irq_type = {
-	"none",
-	startup_none,
-	shutdown_none,
-	do_none,
-	enable_none,
-	disable_none
-};
-
-/*
- * This is the 'legacy' 8259A Programmable Interrupt Controller,
- * present in the majority of PC/AT boxes.
- */
-
-static void do_8259A_IRQ(unsigned int irq, struct pt_regs * regs);
-static void enable_8259A_irq(unsigned int irq);
-void disable_8259A_irq(unsigned int irq);
-
-/* startup is the same as "enable", shutdown is same as "disable" */
-#define startup_8259A_irq	enable_8259A_irq
-#define shutdown_8259A_irq	disable_8259A_irq
-
-static struct hw_interrupt_type i8259A_irq_type = {
-	"XT-PIC",
-	startup_8259A_irq,
-	shutdown_8259A_irq,
-	do_8259A_IRQ,
-	enable_8259A_irq,
-	disable_8259A_irq
-};
-
+spinlock_t irq_controller_lock ={0};
 /*
  * Controller mappings for all interrupt sources:
  */
 irq_desc_t irq_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = { 0, &no_irq_type, }};
 
-
-/*
- * 8259A PIC functions to handle ISA devices:
- */
-
-/*
- * This contains the irq mask for both 8259A irq controllers,
- */
-static unsigned int cached_irq_mask = 0xffff;
-
-#define __byte(x,y) 	(((unsigned char *)&(y))[x])
-#define cached_21	(__byte(0,cached_irq_mask))
-#define cached_A1	(__byte(1,cached_irq_mask))
-
-/*
- * Not all IRQs can be routed through the IO-APIC, eg. on certain (older)
- * boards the timer interrupt is not connected to any IO-APIC pin, it's
- * fed to the CPU IRQ line directly.
- *
- * Any '1' bit in this mask means the IRQ is routed through the IO-APIC.
- * this 'mixed mode' IRQ handling costs nothing because it's only used
- * at IRQ setup time.
- */
-unsigned long io_apic_irqs = 0;
-
-/*
- * These have to be protected by the irq controller spinlock
- * before being called.
- */
-void disable_8259A_irq(unsigned int irq)
-{
-	unsigned int mask = 1 << irq;
-	cached_irq_mask |= mask;
-	if (irq & 8) {
-		outb(cached_A1,0xA1);
-	} else {
-		outb(cached_21,0x21);
-	}
-}
-
-static void enable_8259A_irq(unsigned int irq)
-{
-	unsigned int mask = ~(1 << irq);
-	cached_irq_mask &= mask;
-	if (irq & 8) {
-		outb(cached_A1,0xA1);
-	} else {
-		outb(cached_21,0x21);
-	}
-}
-
-int i8259A_irq_pending(unsigned int irq)
-{
-	unsigned int mask = 1<<irq;
-
-	if (irq < 8)
-                return (inb(0x20) & mask);
-        return (inb(0xA0) & (mask >> 8));
-}
-
-void make_8259A_irq(unsigned int irq)
-{
-	disable_irq_nosync(irq);
-	io_apic_irqs &= ~(1<<irq);
-	irq_desc[irq].handler = &i8259A_irq_type;
-	enable_irq(irq);
-}
-
-/*
- * Careful! The 8259A is a fragile beast, it pretty
- * much _has_ to be done exactly like this (mask it
- * first, _then_ send the EOI, and the order of EOI
- * to the two 8259s is important!
- */
-static inline void mask_and_ack_8259A(unsigned int irq)
-{
-	cached_irq_mask |= 1 << irq;
-	if (irq & 8) {
-		inb(0xA1);	/* DUMMY */
-		outb(cached_A1,0xA1);
-		outb(0x62,0x20);	/* Specific EOI to cascade */
-		outb(0x20,0xA0);
-	} else {
-		inb(0x21);	/* DUMMY */
-		outb(cached_21,0x21);
-		outb(0x20,0x20);
-	}
-}
-
-static void do_8259A_IRQ(unsigned int irq, struct pt_regs * regs)
-{
-	struct irqaction * action;
-	irq_desc_t *desc = irq_desc + irq;
-
-	spin_lock(&irq_controller_lock);
-	{
-		unsigned int status;
-		mask_and_ack_8259A(irq);
-		status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
-		action = NULL;
-		if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
-			action = desc->action;
-			status |= IRQ_INPROGRESS;
-		}
-		desc->status = status;
-	}
-	spin_unlock(&irq_controller_lock);
-
-	/* Exit early if we had no action or it was disabled */
-	if (!action)
-		return;
-
-	handle_IRQ_event(irq, regs, action);
-
-	spin_lock(&irq_controller_lock);
-	{
-		unsigned int status = desc->status & ~IRQ_INPROGRESS;
-		desc->status = status;
-		if (!(status & IRQ_DISABLED))
-			enable_8259A_irq(irq);
-	}
-	spin_unlock(&irq_controller_lock);
-}
-
-/*
- * This builds up the IRQ handler stubs using some ugly macros in irq.h
- *
- * These macros create the low-level assembly IRQ routines that save
- * register context and call do_IRQ(). do_IRQ() then does all the
- * operations that are needed to keep the AT (or SMP IOAPIC)
- * interrupt-controller happy.
- */
-
-
-BUILD_COMMON_IRQ()
-
-#define BI(x,y) \
-	BUILD_IRQ(##x##y)
-
-#define BUILD_16_IRQS(x) \
-	BI(x,0) BI(x,1) BI(x,2) BI(x,3) \
-	BI(x,4) BI(x,5) BI(x,6) BI(x,7) \
-	BI(x,8) BI(x,9) BI(x,a) BI(x,b) \
-	BI(x,c) BI(x,d) BI(x,e) BI(x,f)
-
-/*
- * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
- * (these are usually mapped to vectors 0x20-0x30)
- */
-BUILD_16_IRQS(0x0)
-
-#ifdef CONFIG_X86_IO_APIC
-/*
- * The IO-APIC gives us many more interrupt sources. Most of these 
- * are unused but an SMP system is supposed to have enough memory ...
- * sometimes (mostly wrt. hw bugs) we get corrupted vectors all
- * across the spectrum, so we really want to be prepared to get all
- * of these. Plus, more powerful systems might have more than 64
- * IO-APIC registers.
- *
- * (these are usually mapped into the 0x30-0xff vector range)
- */
-                   BUILD_16_IRQS(0x1) BUILD_16_IRQS(0x2) BUILD_16_IRQS(0x3)
-BUILD_16_IRQS(0x4) BUILD_16_IRQS(0x5) BUILD_16_IRQS(0x6) BUILD_16_IRQS(0x7)
-BUILD_16_IRQS(0x8) BUILD_16_IRQS(0x9) BUILD_16_IRQS(0xa) BUILD_16_IRQS(0xb)
-BUILD_16_IRQS(0xc) BUILD_16_IRQS(0xd)
-#endif
-
-#undef BUILD_16_IRQS
-#undef BI
-
-
-#ifdef __SMP__
-/*
- * The following vectors are part of the Linux architecture, there
- * is no hardware IRQ pin equivalent for them, they are triggered
- * through the ICC by us (IPIs)
- */
-BUILD_SMP_INTERRUPT(reschedule_interrupt)
-BUILD_SMP_INTERRUPT(invalidate_interrupt)
-BUILD_SMP_INTERRUPT(stop_cpu_interrupt)
-BUILD_SMP_INTERRUPT(call_function_interrupt)
-BUILD_SMP_INTERRUPT(spurious_interrupt)
-
-/*
- * every pentium local APIC has two 'local interrupts', with a
- * soft-definable vector attached to both interrupts, one of
- * which is a timer interrupt, the other one is error counter
- * overflow. Linux uses the local APIC timer interrupt to get
- * a much simpler SMP time architecture:
- */
-BUILD_SMP_TIMER_INTERRUPT(apic_timer_interrupt)
-
-#endif
-
-#define IRQ(x,y) \
-	IRQ##x##y##_interrupt
-
-#define IRQLIST_16(x) \
-	IRQ(x,0), IRQ(x,1), IRQ(x,2), IRQ(x,3), \
-	IRQ(x,4), IRQ(x,5), IRQ(x,6), IRQ(x,7), \
-	IRQ(x,8), IRQ(x,9), IRQ(x,a), IRQ(x,b), \
-	IRQ(x,c), IRQ(x,d), IRQ(x,e), IRQ(x,f)
-
-static void (*interrupt[NR_IRQS])(void) = {
-	IRQLIST_16(0x0),
-
-#ifdef CONFIG_X86_IO_APIC
-	                 IRQLIST_16(0x1), IRQLIST_16(0x2), IRQLIST_16(0x3),
-	IRQLIST_16(0x4), IRQLIST_16(0x5), IRQLIST_16(0x6), IRQLIST_16(0x7),
-	IRQLIST_16(0x8), IRQLIST_16(0x9), IRQLIST_16(0xa), IRQLIST_16(0xb),
-	IRQLIST_16(0xc), IRQLIST_16(0xd)
-#endif
-};
-
-#undef IRQ
-#undef IRQLIST_16
-
-
 /*
  * Special irq handlers.
  */
 
 void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
 
-#ifndef CONFIG_VISWS
-/*
- * Note that on a 486, we don't want to do a SIGFPE on an irq13
- * as the irq is unreliable, and exception 16 works correctly
- * (ie as explained in the intel literature). On a 386, you
- * can't use exception 16 due to bad IBM design, so we have to
- * rely on the less exact irq13.
- *
- * Careful.. Not only is IRQ13 unreliable, but it is also
- * leads to races. IBM designers who came up with it should
- * be shot.
- */
- 
-static void math_error_irq(int cpl, void *dev_id, struct pt_regs *regs)
-{
-	outb(0,0xF0);
-	if (ignore_irq13 || !boot_cpu_data.hard_math)
-		return;
-	math_error();
-}
-
-static struct irqaction irq13 = { math_error_irq, 0, 0, "fpu", NULL, NULL };
-
-/*
- * IRQ2 is cascade interrupt to second interrupt controller
- */
-
-static struct irqaction irq2  = { no_action, 0, 0, "cascade", NULL, NULL};
-#endif
-
 /*
  * Generic, controller-independent functions:
  */
@@ -780,10 +469,16 @@
 
 	spin_lock_irqsave(&irq_controller_lock, flags);
 	switch (irq_desc[irq].depth) {
-	case 1:
-		irq_desc[irq].status &= ~IRQ_DISABLED;
+	case 1: {
+		unsigned int status = irq_desc[irq].status & ~IRQ_DISABLED;
+		irq_desc[irq].status = status;
+		if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
+			irq_desc[irq].status = status | IRQ_REPLAY;
+			hw_resend_irq(irq_desc[irq].handler,irq);
+		}
 		irq_desc[irq].handler->enable(irq);
-		/* fall throught */
+		/* fall-through */
+	}
 	default:
 		irq_desc[irq].depth--;
 		break;
@@ -799,7 +494,7 @@
  * SMP cross-CPU interrupts have their own specific
  * handlers).
  */
-asmlinkage void do_IRQ(struct pt_regs regs)
+asmlinkage unsigned int do_IRQ(struct pt_regs regs)
 {	
 	/* 
 	 * We ack quickly, we don't want the irq controller
@@ -811,76 +506,81 @@
 	 * 0 return value means that this irq is already being
 	 * handled by some other CPU. (or is disabled)
 	 */
-	int irq = regs.orig_eax & 0xff; /* subtle, see irq.h */
+	int irq = regs.orig_eax & 0xff; /* high bits used in ret_from_ code  */
 	int cpu = smp_processor_id();
+	irq_desc_t *desc;
+	struct irqaction * action;
+	unsigned int status;
 
 	kstat.irqs[cpu][irq]++;
-	irq_desc[irq].handler->handle(irq, &regs);
+	desc = irq_desc + irq;
+	spin_lock(&irq_controller_lock);
+	irq_desc[irq].handler->ack(irq);
+	/*
+	   REPLAY is when Linux resends an IRQ that was dropped earlier
+	   WAITING is used by probe to mark irqs that are being tested
+	   */
+	status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
+	status |= IRQ_PENDING; /* we _want_ to handle it */
 
 	/*
-	 * This should be conditional: we should really get
-	 * a return code from the irq handler to tell us
-	 * whether the handler wants us to do software bottom
-	 * half handling or not..
+	 * If the IRQ is disabled for whatever reason, we cannot
+	 * use the action we have.
 	 */
-	if (1) {
-		if (bh_active & bh_mask)
-			do_bottom_half();
+	action = NULL;
+	if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
+		action = desc->action;
+		status &= ~IRQ_PENDING; /* we commit to handling */
+		status |= IRQ_INPROGRESS; /* we are handling it */
 	}
-}
-
-int setup_x86_irq(unsigned int irq, struct irqaction * new)
-{
-	int shared = 0;
-	struct irqaction *old, **p;
-	unsigned long flags;
+	desc->status = status;
+	spin_unlock(&irq_controller_lock);
 
 	/*
-	 * Some drivers like serial.c use request_irq() heavily,
-	 * so we have to be careful not to interfere with a
-	 * running system.
+	 * If there is no IRQ handler or it was disabled, exit early.
+	   Since we set PENDING, if another processor is handling
+	   a different instance of this same irq, the other processor
+	   will take care of it.
 	 */
-	if (new->flags & SA_SAMPLE_RANDOM) {
-		/*
-		 * This function might sleep, we want to call it first,
-		 * outside of the atomic block.
-		 * Yes, this might clear the entropy pool if the wrong
-		 * driver is attempted to be loaded, without actually
-		 * installing a new handler, but is this really a problem,
-		 * only the sysadmin is able to do this.
-		 */
-		rand_initialize_irq(irq);
-	}
+	if (!action)
+		return 1;
 
 	/*
-	 * The following block of code has to be executed atomically
+	 * Edge triggered interrupts need to remember
+	 * pending events.
+	 * This applies to any hw interrupts that allow a second
+	 * instance of the same irq to arrive while we are in do_IRQ
+	 * or in the handler. But the code here only handles the _second_
+	 * instance of the irq, not the third or fourth. So it is mostly
+	 * useful for irq hardware that does not mask cleanly in an
+	 * SMP environment.
 	 */
-	spin_lock_irqsave(&irq_controller_lock,flags);
-	p = &irq_desc[irq].action;
-	if ((old = *p) != NULL) {
-		/* Can't share interrupts unless both agree to */
-		if (!(old->flags & new->flags & SA_SHIRQ)) {
-			spin_unlock_irqrestore(&irq_controller_lock,flags);
-			return -EBUSY;
-		}
-
-		/* add new interrupt at end of irq queue */
-		do {
-			p = &old->next;
-			old = *p;
-		} while (old);
-		shared = 1;
+	for (;;) {
+		handle_IRQ_event(irq, &regs, action);
+		spin_lock(&irq_controller_lock);
+		
+		if (!(desc->status & IRQ_PENDING))
+			break;
+		desc->status &= ~IRQ_PENDING;
+		spin_unlock(&irq_controller_lock);
+	}
+	desc->status &= ~IRQ_INPROGRESS;
+	if (!(desc->status & IRQ_DISABLED)){
+			irq_desc[irq].handler->end(irq);
 	}
+	spin_unlock(&irq_controller_lock);
 
-	*p = new;
-
-	if (!shared) {
-		irq_desc[irq].depth = 0;
-		irq_desc[irq].status &= ~IRQ_DISABLED;
-		irq_desc[irq].handler->startup(irq);
+	/*
+	 * This should be conditional: we should really get
+	 * a return code from the irq handler to tell us
+	 * whether the handler wants us to do software bottom
+	 * half handling or not..
+	 */
+	if (1) {
+		if (bh_active & bh_mask)
+			do_bottom_half();
 	}
-	spin_unlock_irqrestore(&irq_controller_lock,flags);
-	return 0;
+	return 1;
 }
 
 int request_irq(unsigned int irq, 
@@ -909,8 +609,7 @@
 	action->next = NULL;
 	action->dev_id = dev_id;
 
-	retval = setup_x86_irq(irq, action);
-
+	retval = setup_irq(irq, action);
 	if (retval)
 		kfree(action);
 	return retval;
@@ -935,13 +634,6 @@
 			irq_desc[irq].status |= IRQ_DISABLED;
 			irq_desc[irq].handler->shutdown(irq);
 		}
-		spin_unlock_irqrestore(&irq_controller_lock,flags);
-
-		/* Wait to make sure it's not being used on another CPU */
-		while (irq_desc[irq].status & IRQ_INPROGRESS)
-			barrier();
-		kfree(action);
-		return;
 	}
 	printk("Trying to free free IRQ%d\n",irq);
 	spin_unlock_irqrestore(&irq_controller_lock,flags);
@@ -967,7 +659,8 @@
 	for (i = NR_IRQS-1; i > 0; i--) {
 		if (!irq_desc[i].action) {
 			irq_desc[i].status |= IRQ_AUTODETECT | IRQ_WAITING;
-			irq_desc[i].handler->startup(i);
+			if(irq_desc[i].handler->startup(i))
+				irq_desc[i].status |= IRQ_PENDING;
 		}
 	}
 	spin_unlock_irq(&irq_controller_lock);
@@ -1030,100 +723,58 @@
 	return irq_found;
 }
 
-void init_ISA_irqs (void)
+/* this was setup_x86_irq but it seems pretty generic */
+int setup_irq(unsigned int irq, struct irqaction * new)
 {
-	int i;
-
-	for (i = 0; i < NR_IRQS; i++) {
-		irq_desc[i].status = IRQ_DISABLED;
-		irq_desc[i].action = 0;
-		irq_desc[i].depth = 0;
-
-		if (i < 16) {
-			/*
-			 * 16 old-style INTA-cycle interrupts:
-			 */
-			irq_desc[i].handler = &i8259A_irq_type;
-		} else {
-			/*
-			 * 'high' PCI IRQs filled in on demand
-			 */
-			irq_desc[i].handler = &no_irq_type;
-		}
-	}
-}
-
-__initfunc(void init_IRQ(void))
-{
-	int i;
+	int shared = 0;
+	struct irqaction *old, **p;
+	unsigned long flags;
 
-#ifndef CONFIG_X86_VISWS_APIC
-	init_ISA_irqs();
-#else
-	init_VISWS_APIC_irqs();
-#endif
 	/*
-	 * Cover the whole vector space, no vector can escape
-	 * us. (some of these will be overridden and become
-	 * 'special' SMP interrupts)
+	 * Some drivers like serial.c use request_irq() heavily,
+	 * so we have to be careful not to interfere with a
+	 * running system.
 	 */
-	for (i = 0; i < NR_IRQS; i++) {
-		int vector = FIRST_EXTERNAL_VECTOR + i;
-		if (vector != SYSCALL_VECTOR) 
-			set_intr_gate(vector, interrupt[i]);
+	if (new->flags & SA_SAMPLE_RANDOM) {
+		/*
+		 * This function might sleep, we want to call it first,
+		 * outside of the atomic block.
+		 * Yes, this might clear the entropy pool if the wrong
+		 * driver is attempted to be loaded, without actually
+		 * installing a new handler, but is this really a problem,
+		 * only the sysadmin is able to do this.
+		 */
+		rand_initialize_irq(irq);
 	}
 
-#ifdef __SMP__	
-
-	/*
-	  IRQ0 must be given a fixed assignment and initialized
-	  before init_IRQ_SMP.
-	*/
-	set_intr_gate(IRQ0_TRAP_VECTOR, interrupt[0]);
-
 	/*
-	 * The reschedule interrupt is a CPU-to-CPU reschedule-helper
-	 * IPI, driven by wakeup.
+	 * The following block of code has to be executed atomically
 	 */
-	set_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
-
-	/* IPI for invalidation */
-	set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);
-
-	/* IPI for CPU halt */
-	set_intr_gate(STOP_CPU_VECTOR, stop_cpu_interrupt);
-
-	/* self generated IPI for local APIC timer */
-	set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
-
-	/* IPI for generic function call */
-	set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
+	spin_lock_irqsave(&irq_controller_lock,flags);
+	p = &irq_desc[irq].action;
+	if ((old = *p) != NULL) {
+		/* Can't share interrupts unless both agree to */
+		if (!(old->flags & new->flags & SA_SHIRQ)) {
+			spin_unlock_irqrestore(&irq_controller_lock,flags);
+			return -EBUSY;
+		}
 
-	/* IPI vector for APIC spurious interrupts */
-	set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
-#endif
+		/* add new interrupt at end of irq queue */
+		do {
+			p = &old->next;
+			old = *p;
+		} while (old);
+		shared = 1;
+	}
 
-	/*
-	 * Set the clock to 100 Hz, we already have a valid
-	 * vector now:
-	 */
-	outb_p(0x34,0x43);		/* binary, mode 2, LSB/MSB, ch 0 */
-	outb_p(LATCH & 0xff , 0x40);	/* LSB */
-	outb(LATCH >> 8 , 0x40);	/* MSB */
-
-#ifndef CONFIG_VISWS
-	setup_x86_irq(2, &irq2);
-	setup_x86_irq(13, &irq13);
-#endif
-}
+	*p = new;
 
-#ifdef CONFIG_X86_IO_APIC
-__initfunc(void init_IRQ_SMP(void))
-{
-	int i;
-	for (i = 0; i < NR_IRQS ; i++)
-		if (IO_APIC_VECTOR(i) > 0)
-			set_intr_gate(IO_APIC_VECTOR(i), interrupt[i]);
+	if (!shared) {
+		irq_desc[irq].depth = 0;
+		irq_desc[irq].status &= ~IRQ_DISABLED;
+		irq_desc[irq].handler->startup(irq);
+	}
+	spin_unlock_irqrestore(&irq_controller_lock,flags);
+	return 0;
 }
-#endif
 
diff -u --recursive --new-file v2.3.13/linux/arch/i386/kernel/irq.h linux/arch/i386/kernel/irq.h
--- v2.3.13/linux/arch/i386/kernel/irq.h	Wed Jul 28 14:47:42 1999
+++ linux/arch/i386/kernel/irq.h	Wed Dec 31 16:00:00 1969
@@ -1,253 +0,0 @@
-#ifndef __irq_h
-#define __irq_h
-
-#include <asm/irq.h>
-
-/*
- * Interrupt controller descriptor. This is all we need
- * to describe about the low-level hardware.
- */
-struct hw_interrupt_type {
-	const char * typename;
-	void (*startup)(unsigned int irq);
-	void (*shutdown)(unsigned int irq);
-	void (*handle)(unsigned int irq, struct pt_regs * regs);
-	void (*enable)(unsigned int irq);
-	void (*disable)(unsigned int irq);
-};
-
-extern struct hw_interrupt_type no_irq_type;
-
-/*
- * IRQ line status.
- */
-#define IRQ_INPROGRESS	1	/* IRQ handler active - do not enter! */
-#define IRQ_DISABLED	2	/* IRQ disabled - do not enter! */
-#define IRQ_PENDING	4	/* IRQ pending - replay on enable */
-#define IRQ_REPLAY	8	/* IRQ has been replayed but not acked yet */
-#define IRQ_AUTODETECT	16	/* IRQ is being autodetected */
-#define IRQ_WAITING	32	/* IRQ not yet seen - for autodetection */
-
-/*
- * This is the "IRQ descriptor", which contains various information
- * about the irq, including what kind of hardware handling it has,
- * whether it is disabled etc etc.
- *
- * Pad this out to 32 bytes for cache and indexing reasons.
- */
-typedef struct {
-	unsigned int status;			/* IRQ status - IRQ_INPROGRESS, IRQ_DISABLED */
-	struct hw_interrupt_type *handler;	/* handle/enable/disable functions */
-	struct irqaction *action;		/* IRQ action list */
-	unsigned int depth;			/* Disable depth for nested irq disables */
-} irq_desc_t;
-
-/*
- * IDT vectors usable for external interrupt sources start
- * at 0x20:
- */
-#define FIRST_EXTERNAL_VECTOR	0x20
-
-#define SYSCALL_VECTOR		0x80
-
-/*
- * Vectors 0x20-0x2f are used for ISA interrupts.
- */
-
-/*
- * Special IRQ vectors used by the SMP architecture:
- *
- * (some of the following vectors are 'rare', they are merged
- *  into a single vector (FUNCTION_VECTOR) to save vector space.
- *  TLB, reschedule and local APIC vectors are performance-critical.)
- */
-#define RESCHEDULE_VECTOR	0x30
-#define INVALIDATE_TLB_VECTOR	0x31
-#define STOP_CPU_VECTOR		0x40
-#define LOCAL_TIMER_VECTOR	0x41
-#define CALL_FUNCTION_VECTOR	0x50
-
-/*
- * First APIC vector available to drivers: (vectors 0x51-0xfe)
- */
-#define IRQ0_TRAP_VECTOR	0x51
-
-/*
- * This IRQ should never happen, but we print a message nevertheless.
- */
-#define SPURIOUS_APIC_VECTOR	0xff
-
-extern irq_desc_t irq_desc[NR_IRQS];
-extern int irq_vector[NR_IRQS];
-#define IO_APIC_VECTOR(irq)	irq_vector[irq]
-
-extern void init_IRQ_SMP(void);
-extern int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
-extern int setup_x86_irq(unsigned int, struct irqaction *);
-
-/*
- * Various low-level irq details needed by irq.c, process.c,
- * time.c, io_apic.c and smp.c
- *
- * Interrupt entry/exit code at both C and assembly level
- */
-
-extern void no_action(int cpl, void *dev_id, struct pt_regs *regs);
-extern void mask_irq(unsigned int irq);
-extern void unmask_irq(unsigned int irq);
-extern void disable_8259A_irq(unsigned int irq);
-extern int i8259A_irq_pending(unsigned int irq);
-extern void ack_APIC_irq(void);
-extern void FASTCALL(send_IPI_self(int vector));
-extern void init_VISWS_APIC_irqs(void);
-extern void setup_IO_APIC(void);
-extern int IO_APIC_get_PCI_irq_vector(int bus, int slot, int fn);
-extern void make_8259A_irq(unsigned int irq);
-extern void send_IPI(int dest, int vector);
-extern void init_pic_mode(void);
-extern void print_IO_APIC(void);
-
-extern unsigned long io_apic_irqs;
-
-extern char _stext, _etext;
-
-#define MAX_IRQ_SOURCES 128
-#define MAX_MP_BUSSES 32
-enum mp_bustype {
-	MP_BUS_ISA,
-	MP_BUS_EISA,
-	MP_BUS_PCI
-};
-extern int mp_bus_id_to_type [MAX_MP_BUSSES];
-extern int mp_bus_id_to_pci_bus [MAX_MP_BUSSES];
-
-extern spinlock_t irq_controller_lock;
-
-#ifdef __SMP__
-
-#include <asm/atomic.h>
-
-static inline void irq_enter(int cpu, unsigned int irq)
-{
-	hardirq_enter(cpu);
-	while (test_bit(0,&global_irq_lock)) {
-		/* nothing */;
-	}
-}
-
-static inline void irq_exit(int cpu, unsigned int irq)
-{
-	hardirq_exit(cpu);
-}
-
-#define IO_APIC_IRQ(x) (((x) >= 16) || ((1<<(x)) & io_apic_irqs))
-
-#else
-
-#define irq_enter(cpu, irq)	(++local_irq_count[cpu])
-#define irq_exit(cpu, irq)	(--local_irq_count[cpu])
-
-#define IO_APIC_IRQ(x)	(0)
-
-#endif
-
-#define __STR(x) #x
-#define STR(x) __STR(x)
-
-#define SAVE_ALL \
-	"cld\n\t" \
-	"pushl %es\n\t" \
-	"pushl %ds\n\t" \
-	"pushl %eax\n\t" \
-	"pushl %ebp\n\t" \
-	"pushl %edi\n\t" \
-	"pushl %esi\n\t" \
-	"pushl %edx\n\t" \
-	"pushl %ecx\n\t" \
-	"pushl %ebx\n\t" \
-	"movl $" STR(__KERNEL_DS) ",%edx\n\t" \
-	"movl %dx,%ds\n\t" \
-	"movl %dx,%es\n\t"
-
-#define IRQ_NAME2(nr) nr##_interrupt(void)
-#define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
-
-#define GET_CURRENT \
-	"movl %esp, %ebx\n\t" \
-	"andl $-8192, %ebx\n\t"
-
-#ifdef __SMP__
-
-/*
- *	SMP has a few special interrupts for IPI messages
- */
-
-#define BUILD_SMP_INTERRUPT(x) \
-asmlinkage void x(void); \
-__asm__( \
-"\n"__ALIGN_STR"\n" \
-SYMBOL_NAME_STR(x) ":\n\t" \
-	"pushl $-1\n\t" \
-	SAVE_ALL \
-	"call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
-	"jmp ret_from_intr\n");
-
-#define BUILD_SMP_TIMER_INTERRUPT(x) \
-asmlinkage void x(struct pt_regs * regs); \
-__asm__( \
-"\n"__ALIGN_STR"\n" \
-SYMBOL_NAME_STR(x) ":\n\t" \
-	"pushl $-1\n\t" \
-	SAVE_ALL \
-	"movl %esp,%eax\n\t" \
-	"pushl %eax\n\t" \
-	"call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
-	"addl $4,%esp\n\t" \
-	"jmp ret_from_intr\n");
-
-#endif /* __SMP__ */
-
-#define BUILD_COMMON_IRQ() \
-__asm__( \
-	"\n" __ALIGN_STR"\n" \
-	"common_interrupt:\n\t" \
-	SAVE_ALL \
-	"pushl $ret_from_intr\n\t" \
-	"jmp "SYMBOL_NAME_STR(do_IRQ));
-
-/*
- * subtle. orig_eax is used by the signal code to distinct between
- * system calls and interrupted 'random user-space'. Thus we have
- * to put a negative value into orig_eax here. (the problem is that
- * both system calls and IRQs want to have small integer numbers in
- * orig_eax, and the syscall code has won the optimization conflict ;)
- */
-#define BUILD_IRQ(nr) \
-asmlinkage void IRQ_NAME(nr); \
-__asm__( \
-"\n"__ALIGN_STR"\n" \
-SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
-	"pushl $"#nr"-256\n\t" \
-	"jmp common_interrupt");
-
-/*
- * x86 profiling function, SMP safe. We might want to do this in
- * assembly totally?
- */
-static inline void x86_do_profile (unsigned long eip)
-{
-	if (prof_buffer) {
-		eip -= (unsigned long) &_stext;
-		eip >>= prof_shift;
-		/*
-		 * Don't ignore out-of-bounds EIP values silently,
-		 * put them into the last histogram slot, so if
-		 * present, they will show up as a sharp peak.
-		 */
-		if (eip > prof_len-1)
-			eip = prof_len-1;
-		atomic_inc((atomic_t *)&prof_buffer[eip]);
-	}
-}
-
-#endif
diff -u --recursive --new-file v2.3.13/linux/arch/i386/kernel/mca.c linux/arch/i386/kernel/mca.c
--- v2.3.13/linux/arch/i386/kernel/mca.c	Wed Jul 21 15:46:48 1999
+++ linux/arch/i386/kernel/mca.c	Wed Aug 18 11:25:29 1999
@@ -222,7 +222,7 @@
 
 #define MCA_STANDARD_RESOURCES	(sizeof(mca_standard_resources)/sizeof(struct resource))
 
-__initfunc(void mca_init(void))
+void __init mca_init(void)
 {
 	unsigned int i, j;
 	unsigned long flags;
@@ -698,7 +698,7 @@
 
 /*--------------------------------------------------------------------*/
 
-__initfunc(void mca_do_proc_init(void))
+void __init mca_do_proc_init(void)
 {
 	int i;
 	struct proc_dir_entry* node = NULL;
diff -u --recursive --new-file v2.3.13/linux/arch/i386/kernel/mtrr.c linux/arch/i386/kernel/mtrr.c
--- v2.3.13/linux/arch/i386/kernel/mtrr.c	Wed Jun 30 13:38:18 1999
+++ linux/arch/i386/kernel/mtrr.c	Wed Aug 18 11:27:04 1999
@@ -235,7 +235,7 @@
 #include <asm/msr.h>
 
 #include <asm/hardirq.h>
-#include "irq.h"
+#include <linux/irq.h>
 
 #define MTRR_VERSION            "1.35 (19990512)"
 
@@ -731,8 +731,8 @@
 
 
 /*  Get the MSR pair relating to a var range  */
-__initfunc(static void get_mtrr_var_range (unsigned int index,
-					   struct mtrr_var_range *vr))
+static void __init get_mtrr_var_range (unsigned int index,
+					   struct mtrr_var_range *vr)
 {
     rdmsr (MTRRphysBase_MSR (index), vr->base_lo, vr->base_hi);
     rdmsr (MTRRphysMask_MSR (index), vr->mask_lo, vr->mask_hi);
@@ -741,8 +741,8 @@
 
 /*  Set the MSR pair relating to a var range. Returns TRUE if
     changes are made  */
-__initfunc(static int set_mtrr_var_range_testing (unsigned int index,
-						  struct mtrr_var_range *vr))
+static int __init set_mtrr_var_range_testing (unsigned int index,
+						  struct mtrr_var_range *vr)
 {
     unsigned int lo, hi;
     int changed = FALSE;
@@ -764,7 +764,7 @@
     return changed;
 }   /*  End Function set_mtrr_var_range_testing  */
 
-__initfunc(static void get_fixed_ranges(mtrr_type *frs))
+static void __init get_fixed_ranges(mtrr_type *frs)
 {
     unsigned long *p = (unsigned long *)frs;
     int i;
@@ -777,7 +777,7 @@
 	rdmsr(MTRRfix4K_C0000_MSR + i, p[6 + i*2], p[7 + i*2]);
 }   /*  End Function get_fixed_ranges  */
 
-__initfunc(static int set_fixed_ranges_testing(mtrr_type *frs))
+static int __init set_fixed_ranges_testing(mtrr_type *frs)
 {
     unsigned long *p = (unsigned long *)frs;
     int changed = FALSE;
@@ -819,7 +819,7 @@
 
 
 /*  Grab all of the MTRR state for this CPU into *state  */
-__initfunc(static void get_mtrr_state(struct mtrr_state *state))
+static void __init get_mtrr_state(struct mtrr_state *state)
 {
     unsigned int nvrs, i;
     struct mtrr_var_range *vrs;
@@ -842,14 +842,14 @@
 
 
 /*  Free resources associated with a struct mtrr_state  */
-__initfunc(static void finalize_mtrr_state(struct mtrr_state *state))
+static void __init finalize_mtrr_state(struct mtrr_state *state)
 {
     if (state->var_ranges) kfree (state->var_ranges);
 }   /*  End Function finalize_mtrr_state  */
 
 
-__initfunc(static unsigned long set_mtrr_state (struct mtrr_state *state,
-						struct set_mtrr_context *ctxt))
+static unsigned long __init set_mtrr_state (struct mtrr_state *state,
+						struct set_mtrr_context *ctxt)
 /*  [SUMMARY] Set the MTRR state for this CPU.
     <state> The MTRR state information to read.
     <ctxt> Some relevant CPU context.
@@ -948,7 +948,7 @@
 
 
 /*  Some BIOS's are fucked and don't set all MTRRs the same!  */
-__initfunc(static void mtrr_state_warn (unsigned long mask))
+static void __init mtrr_state_warn(unsigned long mask)
 {
     if (!mask) return;
     if (mask & MTRR_CHANGE_MASK_FIXED)
@@ -1532,7 +1532,7 @@
 
 unsigned char ccr_state[7] __initdata = { 0, 0, 0, 0, 0, 0, 0 };
 
-__initfunc(static void cyrix_arr_init_secondary(void))
+static void __init cyrix_arr_init_secondary(void)
 {
     struct set_mtrr_context ctxt;
     int i;
@@ -1565,7 +1565,7 @@
  *   - (maybe) disable ARR3
  * Just to be sure, we enable ARR usage by the processor (CCR5 bit 5 set)
  */
-__initfunc(static void cyrix_arr_init(void))
+static void __init cyrix_arr_init(void)
 {
     struct set_mtrr_context ctxt;
     unsigned char ccr[7];
@@ -1631,7 +1631,7 @@
     if ( ccrc[6] ) printk ("mtrr: ARR3 was write protected, unprotected\n");
 }   /*  End Function cyrix_arr_init  */
 
-__initfunc(static void centaur_mcr_init (void))
+static void __init centaur_mcr_init(void)
 {
     unsigned i;
     struct set_mtrr_context ctxt;
@@ -1655,7 +1655,7 @@
     set_mtrr_done (&ctxt);
 }   /*  End Function centaur_mcr_init  */
 
-__initfunc(static void mtrr_setup (void))
+static void __init mtrr_setup(void)
 {
     printk ("mtrr: v%s Richard Gooch (rgooch@atnf.csiro.au)\n", MTRR_VERSION);
     switch (boot_cpu_data.x86_vendor)
@@ -1685,7 +1685,7 @@
 static volatile unsigned long smp_changes_mask __initdata = 0;
 static struct mtrr_state smp_mtrr_state __initdata = {0, 0};
 
-__initfunc(void mtrr_init_boot_cpu (void))
+void __init mtrr_init_boot_cpu(void)
 {
     if ( !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR) ) return;
     mtrr_setup ();
@@ -1703,7 +1703,7 @@
     }
 }   /*  End Function mtrr_init_boot_cpu  */
 
-__initfunc(static void intel_mtrr_init_secondary_cpu (void))
+static void __init intel_mtrr_init_secondary_cpu(void)
 {
     unsigned long mask, count;
     struct set_mtrr_context ctxt;
@@ -1722,7 +1722,7 @@
     }
 }   /*  End Function intel_mtrr_init_secondary_cpu  */
 
-__initfunc(void mtrr_init_secondary_cpu (void))
+void __init mtrr_init_secondary_cpu(void)
 {
     if ( !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR) ) return;
     switch (boot_cpu_data.x86_vendor)
@@ -1746,7 +1746,7 @@
 }   /*  End Function mtrr_init_secondary_cpu  */
 #endif  /*  __SMP__  */
 
-__initfunc(int mtrr_init(void))
+int __init mtrr_init(void)
 {
     if ( !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR) ) return 0;
 #  ifdef __SMP__
diff -u --recursive --new-file v2.3.13/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c
--- v2.3.13/linux/arch/i386/kernel/process.c	Mon Aug  9 14:59:19 1999
+++ linux/arch/i386/kernel/process.c	Wed Aug 18 11:11:15 1999
@@ -45,7 +45,7 @@
 #include <asm/math_emu.h>
 #endif
 
-#include "irq.h"
+#include <linux/irq.h>
 
 spinlock_t semaphore_wake_lock = SPIN_LOCK_UNLOCKED;
 
@@ -63,53 +63,10 @@
 	hlt_counter--;
 }
 
-static void default_idle(void)
-{
-	while (1) {
-		while (!current->need_resched) {
-			if (!current_cpu_data.hlt_works_ok)
-				continue;
-			if (hlt_counter)
-				continue;
-			asm volatile("sti ; hlt" : : : "memory");
-		}
-		schedule();
-		check_pgt_cache();
-	}
-}	
-
-void (*idle)(void) = default_idle;
-
-#if 1
-
-#include <linux/pci.h>
-
-static int __init piix4_idle_init(void)
-{
-	/* This is the PIIX4 ACPI device */
-	struct pci_dev *dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
-
-	if (dev) {
-		u32 base;
-
-		printk("Found PIIX4 ACPI device\n");
-		pci_read_config_dword(dev, 0x40, &base);
-		printk("  Base address %04x\n", base);
-#ifdef __SMP__
-		/*
-		 * We can't really do idle things with multiple CPU's, I'm
-		 * afraid.  We'd need a per-CPU ACPI device.
-		 */
-		if (smp_num_cpus > 1)
-			return 0;
-#endif
-	}
-	return 0;
-}
-
-__initcall(piix4_idle_init);
-
-#endif
+/*
+ * Powermanagement idle function, if any..
+ */
+void (*acpi_idle)(void) = NULL;
 
 /*
  * The idle thread. There's no useful work to be
@@ -123,7 +80,20 @@
 	init_idle();
 	current->priority = 0;
 	current->counter = -100;
-	idle();
+
+	while (1) {
+		while (!current->need_resched) {
+			if (!current_cpu_data.hlt_works_ok)
+				continue;
+			if (hlt_counter)
+				continue;
+			asm volatile("sti ; hlt" : : : "memory");
+		}
+		schedule();
+		check_pgt_cache();
+		if (acpi_idle)
+			acpi_idle();
+	}
 }
 
 /*
diff -u --recursive --new-file v2.3.13/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v2.3.13/linux/arch/i386/kernel/setup.c	Mon Aug  9 14:59:19 1999
+++ linux/arch/i386/kernel/setup.c	Wed Aug 18 11:25:12 1999
@@ -14,6 +14,9 @@
  *      Bart Hartgers <bart@etpmod.phys.tue.nl>, May 1999.
  *
  *  Intel Mobile Pentium II detection fix. Sean Gilley, June 1999.
+ *
+ *  IDT Winchip tweaks, misc clean ups.
+ *	Dave Jones <dave@powertweak.com>, August 1999
  */
 
 /*
@@ -90,7 +93,7 @@
 #endif
 
 extern int root_mountflags;
-extern int _etext, _edata, _end;
+extern int _text, _etext, _edata, _end;
 extern unsigned long cpu_hz;
 
 /*
@@ -248,7 +251,7 @@
 static char command_line[COMMAND_LINE_SIZE] = { 0, };
        char saved_command_line[COMMAND_LINE_SIZE];
 
-struct resource standard_resources[] = {
+struct resource standard_io_resources[] = {
 	{ "dma1", 0x00, 0x1f },
 	{ "pic1", 0x20, 0x3f },
 	{ "timer", 0x40, 0x5f },
@@ -259,14 +262,90 @@
 	{ "fpu", 0xf0, 0xff }
 };
 
-/* For demonstration purposes only.. */
-#define keyboard_resources (standard_resources+3)
-struct resource kbd_status_resource = { "status", 0x60, 0x60 };
+#define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource))
 
-#define STANDARD_RESOURCES (sizeof(standard_resources)/sizeof(struct resource))
+/* System RAM - interrupted by the 640kB-1M hole */
+#define code_resource (ram_resources[3])
+#define data_resource (ram_resources[4])
+static struct resource ram_resources[] = {
+	{ "System RAM", 0x000000, 0x09ffff, IORESOURCE_BUSY },
+	{ "System RAM", 0x100000, 0x100000, IORESOURCE_BUSY },
+	{ "Video RAM area", 0x0a0000, 0x0bffff },
+	{ "Kernel code", 0x100000, 0 },
+	{ "Kernel data", 0, 0 }
+};
+
+/* System ROM resources */
+#define MAXROMS 6
+static struct resource rom_resources[MAXROMS] = {
+	{ "System ROM", 0xF0000, 0xFFFFF, IORESOURCE_BUSY },
+	{ "Video ROM", 0xc0000, 0xc7fff }
+};
+
+#define romsignature(x) (*(unsigned short *)(x) == 0xaa55)
+
+static void __init probe_roms(void)
+{
+	int roms = 1;
+	unsigned long base;
+	unsigned char *romstart;
+
+	request_resource(&iomem_resource, rom_resources+0);
+
+	/* Video ROM is standard at C000:0000 - C7FF:0000, check signature */
+	for (base = 0xC0000; base < 0xE0000; base += 2048) {
+		romstart = bus_to_virt(base);
+		if (!romsignature(romstart))
+			continue;
+		request_resource(&iomem_resource, rom_resources + roms);
+		roms++;
+		break;
+	}
+
+	/* Extension roms at C800:0000 - DFFF:0000 */
+	for (base = 0xC8000; base < 0xE0000; base += 2048) {
+		unsigned long length;
+
+		romstart = bus_to_virt(base);
+		if (!romsignature(romstart))
+			continue;
+		length = romstart[2] * 512;
+		if (length) {
+			unsigned int i;
+			unsigned char chksum;
+
+			chksum = 0;
+			for (i = 0; i < length; i++)
+				chksum += romstart[i];
+
+			/* Good checksum? */
+			if (!chksum) {
+				rom_resources[roms].start = base;
+				rom_resources[roms].end = base + length - 1;
+				rom_resources[roms].name = "Extension ROM";
+
+				request_resource(&iomem_resource, rom_resources + roms);
+				roms++;
+				if (roms >= MAXROMS)
+					return;
+			}
+		}
+	}
+
+	/* Final check for motherboard extension rom at E000:0000 */
+	base = 0xE0000;
+	romstart = bus_to_virt(base);
+
+	if (romsignature(romstart)) {
+		rom_resources[roms].start = base;
+		rom_resources[roms].end = base + 65535;
+		rom_resources[roms].name = "Extension ROM";
 
-__initfunc(void setup_arch(char **cmdline_p,
-	unsigned long * memory_start_p, unsigned long * memory_end_p))
+		request_resource(&iomem_resource, rom_resources + roms);
+	}
+}
+
+void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * memory_end_p)
 {
 	unsigned long memory_start, memory_end;
 	char c = ' ', *to = command_line, *from = COMMAND_LINE;
@@ -298,6 +377,8 @@
 	}
 #endif
 
+	ram_resources[1].end = memory_end-1;
+
 	memory_end &= PAGE_MASK;
 #ifdef CONFIG_BLK_DEV_RAM
 	rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
@@ -307,11 +388,16 @@
 	if (!MOUNT_ROOT_RDONLY)
 		root_mountflags &= ~MS_RDONLY;
 	memory_start = (unsigned long) &_end;
-	init_mm.start_code = PAGE_OFFSET;
+	init_mm.start_code = (unsigned long) &_text;
 	init_mm.end_code = (unsigned long) &_etext;
 	init_mm.end_data = (unsigned long) &_edata;
 	init_mm.brk = (unsigned long) &_end;
 
+	code_resource.start = virt_to_bus(&_text);
+	code_resource.end = virt_to_bus(&_etext)-1;
+	data_resource.start = virt_to_bus(&_etext);
+	data_resource.end = virt_to_bus(&_edata)-1;
+
 	/* Save unparsed command line copy for /proc/cmdline */
 	memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
 	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
@@ -336,6 +422,8 @@
 					memory_end = memory_end << 20;
 					from++;
 				}
+				if (memory_end > ram_resources[1].end)
+					ram_resources[1].end = memory_end-1;
 			}
 		}
 		c = *(from++);
@@ -348,6 +436,14 @@
 	*to = '\0';
 	*cmdline_p = command_line;
 
+	/* Request the standard RAM and ROM resources - they eat up PCI memory space */
+	request_resource(&iomem_resource, ram_resources+0);
+	request_resource(&iomem_resource, ram_resources+1);
+	request_resource(&iomem_resource, ram_resources+2);
+	request_resource(ram_resources+1, &code_resource);
+	request_resource(ram_resources+1, &data_resource);
+	probe_roms();
+
 #define VMALLOC_RESERVE	(128 << 20)	/* 128MB for vmalloc and initrd */
 #define MAXMEM	((unsigned long)(-PAGE_OFFSET-VMALLOC_RESERVE))
 
@@ -383,9 +479,8 @@
 #endif
 
 	/* request I/O space for devices used on all i[345]86 PCs */
-	for (i = 0; i < STANDARD_RESOURCES; i++)
-		request_resource(&ioport_resource, standard_resources+i);
-	request_resource(keyboard_resources, &kbd_status_resource);
+	for (i = 0; i < STANDARD_IO_RESOURCES; i++)
+		request_resource(&ioport_resource, standard_io_resources+i);
 
 #ifdef CONFIG_VT
 #if defined(CONFIG_VGA_CONSOLE)
@@ -396,7 +491,7 @@
 #endif
 }
 
-__initfunc(static int get_model_name(struct cpuinfo_x86 *c))
+static int __init get_model_name(struct cpuinfo_x86 *c)
 {
 	unsigned int n, dummy, *v;
 
@@ -424,7 +519,7 @@
 	return 1;
 }
 
-__initfunc(static int amd_model(struct cpuinfo_x86 *c))
+static int __init amd_model(struct cpuinfo_x86 *c)
 {
 	u32 l, h;
 	unsigned long flags;
@@ -553,7 +648,7 @@
 static char cyrix_model_mult1[] __initdata = "12??43";
 static char cyrix_model_mult2[] __initdata = "12233445";
 
-__initfunc(static void cyrix_model(struct cpuinfo_x86 *c))
+static void __init cyrix_model(struct cpuinfo_x86 *c)
 {
 	unsigned char dir0, dir0_msn, dir0_lsn, dir1 = 0;
 	char *buf = c->x86_model_id;
@@ -661,7 +756,7 @@
 	return;
 }
 
-__initfunc(void get_cpu_vendor(struct cpuinfo_x86 *c))
+void __init get_cpu_vendor(struct cpuinfo_x86 *c)
 {
 	char *v = c->x86_vendor_id;
 
@@ -721,7 +816,7 @@
 	    NULL, NULL, NULL, NULL, NULL, NULL, NULL }},
 };
 
-__initfunc(void identify_cpu(struct cpuinfo_x86 *c))
+void __init identify_cpu(struct cpuinfo_x86 *c)
 {
 	int i;
 	char *p = NULL;
@@ -818,7 +913,6 @@
 					p = "Celeron (Dixon)";
 			}
 		}
-			
 	}
 
 	if (p) {
@@ -833,7 +927,7 @@
  *	Perform early boot up checks for a valid TSC. See arch/i386/kernel/time.c
  */
  
-__initfunc(void dodgy_tsc(void))
+void __init dodgy_tsc(void)
 {
 	get_cpu_vendor(&boot_cpu_data);
 	
@@ -850,7 +944,7 @@
 	"Intel", "Cyrix", "AMD", "UMC", "NexGen", "Centaur" };
 
 
-__initfunc(void print_cpu_info(struct cpuinfo_x86 *c))
+void __init print_cpu_info(struct cpuinfo_x86 *c)
 {
 	char *vendor = NULL;
 
@@ -868,22 +962,25 @@
 		printk("%s", c->x86_model_id);
 
 	if (c->x86_mask || c->cpuid_level>=0) 
-		printk(" stepping %02x", c->x86_mask);
+		printk(" stepping %02x\n", c->x86_mask);
 
-	if(c->x86_vendor == X86_VENDOR_CENTAUR)
-	{
+	if(c->x86_vendor == X86_VENDOR_CENTAUR) {
 		u32 hv,lv;
 		rdmsr(0x107, lv, hv);
-		printk("\nCentaur FSR was 0x%X ",lv);
-		lv|=(1<<8);
-		lv|=(1<<7);
+		printk("Centaur FSR was 0x%X ",lv);
+		lv|=(1<<1 | 1<<2 | 1<<7);
 		/* lv|=(1<<6);	- may help too if the board can cope */
-		printk("now 0x%X", lv);
+		printk("now 0x%X\n", lv);
 		wrmsr(0x107, lv, hv);
 		/* Emulate MTRRs using Centaur's MCR. */
-		c->x86_capability |= X86_FEATURE_MTRR;	   	
+		c->x86_capability |= X86_FEATURE_MTRR;
+
+		/* Set 3DNow! on Winchip 2 and above. */
+		if (c->x86_model >=8)
+		    c->x86_capability |= X86_FEATURE_AMD3D;
+
+		c->x86_capability |=X86_FEATURE_CX8;
 	}
-	printk("\n");
 }
 
 /*
@@ -918,7 +1015,7 @@
 			       c->x86 + '0',
 			       c->x86_model,
 			       c->x86_model_id[0] ? c->x86_model_id : "unknown");
-		
+
 		if (c->x86_mask || c->cpuid_level >= 0)
 			p += sprintf(p, "stepping\t: %d\n", c->x86_mask);
 		else
@@ -934,14 +1031,20 @@
 			p += sprintf(p, "cache size\t: %d KB\n", c->x86_cache_size);
 		
 		/* Modify the capabilities according to chip type */
-		if (c->x86_vendor == X86_VENDOR_CYRIX) {
+		switch (c->x86_vendor) {
+
+		    case X86_VENDOR_CYRIX:
 			x86_cap_flags[24] = "cxmmx";
-		} else if (c->x86_vendor == X86_VENDOR_AMD) {
-			x86_cap_flags[16] = "fcmov";
-			x86_cap_flags[31] = "3dnow";
+			break;
+
+		    case X86_VENDOR_AMD:
 			if (c->x86 == 5 && c->x86_model == 6)
 				x86_cap_flags[10] = "sep";
-		} else if (c->x86_vendor == X86_VENDOR_INTEL) {
+			x86_cap_flags[16] = "fcmov";
+			x86_cap_flags[31] = "3dnow";
+			break;
+
+		    case X86_VENDOR_INTEL:
 			x86_cap_flags[6] = "pae";
 			x86_cap_flags[9] = "apic";
 			x86_cap_flags[14] = "mca";
@@ -949,6 +1052,16 @@
 			x86_cap_flags[17] = "pse36";
 			x86_cap_flags[18] = "psn";
 			x86_cap_flags[24] = "osfxsr";
+			break;
+
+		    case X86_VENDOR_CENTAUR:
+			if (c->x86_model >=8)	/* Only Winchip2 and above */
+			    x86_cap_flags[31] = "3dnow";
+			break;
+
+		    default:
+			/* Unknown CPU manufacturer. Transmeta ? :-) */
+			break;
 		}
 
 		sep_bug = c->x86_vendor == X86_VENDOR_INTEL &&
diff -u --recursive --new-file v2.3.13/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c
--- v2.3.13/linux/arch/i386/kernel/smp.c	Mon Aug  9 14:59:19 1999
+++ linux/arch/i386/kernel/smp.c	Wed Aug 18 11:34:50 1999
@@ -42,7 +42,7 @@
 #include <asm/mtrr.h>
 #include <asm/msr.h>
 
-#include "irq.h"
+#include <linux/irq.h>
 
 #define JIFFIE_TIMEOUT 100
 
@@ -164,14 +164,6 @@
  *	SMP mode to <NUM>.
  */
 
-void __init smp_setup(char *str, int *ints)
-{
-	if (ints && ints[0] > 0)
-		max_cpus = ints[1];
-	else
-		max_cpus = 0;
-}
-
 static int __init nosmp(char *str)
 {
 	max_cpus = 0;
@@ -186,7 +178,7 @@
 	return 1;
 }
 
-__setup("maxcpus", maxcpus);
+__setup("maxcpus=", maxcpus);
 
 void ack_APIC_irq(void)
 {
@@ -935,6 +927,14 @@
 	unsigned short ss;
 } stack_start;
 
+static int __init fork_by_hand(void)
+{
+	struct pt_regs regs;
+	/* don't care about the eip and regs settings since we'll never
+	   reschedule the forked task. */
+	return do_fork(CLONE_VM|CLONE_PID, 0, &regs);
+}
+
 static void __init do_boot_cpu(int i)
 {
 	unsigned long cfg;
@@ -944,11 +944,11 @@
 	int timeout, num_starts, j;
 	unsigned long start_eip;
 
-	/*
-	 *	We need an idle process for each processor.
-	 */
-	kernel_thread(start_secondary, NULL, CLONE_PID);
 	cpucount++;
+	/* We can't use kernel_thread since we must _avoid_ to reschedule
+	   the child. */
+	if (fork_by_hand() < 0)
+		panic("failed fork for CPU %d", i);
 
 	/*
 	 * We remove it from the pidhash and the runqueue
diff -u --recursive --new-file v2.3.13/linux/arch/i386/kernel/time.c linux/arch/i386/kernel/time.c
--- v2.3.13/linux/arch/i386/kernel/time.c	Thu Apr 29 11:53:41 1999
+++ linux/arch/i386/kernel/time.c	Wed Aug 18 11:27:23 1999
@@ -59,7 +59,7 @@
 /*
  * for x86_do_profile()
  */
-#include "irq.h"
+#include <linux/irq.h>
 
 
 unsigned long cpu_hz;	/* Detected as we calibrate the TSC */
@@ -547,7 +547,7 @@
 #define CALIBRATE_LATCH	(5 * LATCH)
 #define CALIBRATE_TIME	(5 * 1000020/HZ)
 
-__initfunc(static unsigned long calibrate_tsc(void))
+static unsigned long __init calibrate_tsc(void)
 {
        /* Set the Gate high, disable speaker */
 	outb((inb(0x61) & ~0x02) | 0x01, 0x61);
@@ -612,7 +612,7 @@
 	return 0;
 }
 
-__initfunc(void time_init(void))
+void __init time_init(void)
 {
 	xtime.tv_sec = get_cmos_time();
 	xtime.tv_usec = 0;
@@ -681,8 +681,8 @@
 	co_cpu_write(CO_CPU_CTRL, co_cpu_read(CO_CPU_CTRL) & ~CO_CTRL_TIMEMASK);
 
 	/* Wire cpu IDT entry to s/w handler (and Cobalt APIC to IDT) */
-	setup_x86_irq(CO_IRQ_TIMER, &irq0);
+	setup_irq(CO_IRQ_TIMER, &irq0);
 #else
-	setup_x86_irq(0, &irq0);
+	setup_irq(0, &irq0);
 #endif
 }
diff -u --recursive --new-file v2.3.13/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
--- v2.3.13/linux/arch/i386/kernel/traps.c	Wed Jul 21 15:46:48 1999
+++ linux/arch/i386/kernel/traps.c	Wed Aug 18 11:27:34 1999
@@ -42,7 +42,7 @@
 #include <asm/lithium.h>
 #endif
 
-#include "irq.h"
+#include <linux/irq.h>
 
 asmlinkage int system_call(void);
 asmlinkage void lcall7(void);
@@ -480,7 +480,7 @@
 
 #endif /* CONFIG_MATH_EMULATION */
 
-__initfunc(void trap_init_f00f_bug(void))
+void __init trap_init_f00f_bug(void)
 {
 	unsigned long page;
 	pgd_t * pgd;
diff -u --recursive --new-file v2.3.13/linux/arch/i386/vmlinux.lds linux/arch/i386/vmlinux.lds
--- v2.3.13/linux/arch/i386/vmlinux.lds	Mon Aug  9 14:59:19 1999
+++ linux/arch/i386/vmlinux.lds	Wed Dec 31 16:00:00 1969
@@ -1,75 +0,0 @@
-/* ld script to make i386 Linux kernel
- * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>;
- */
-OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
-OUTPUT_ARCH(i386)
-ENTRY(_start)
-SECTIONS
-{
-  . = 0xC0000000  + 0x100000;
-  _text = .;			/* Text and read-only data */
-  .text : {
-	*(.text)
-	*(.fixup)
-	*(.gnu.warning)
-	} = 0x9090
-  .text.lock : { *(.text.lock) }	/* out-of-line lock text */
-  .rodata : { *(.rodata) }
-  .kstrtab : { *(.kstrtab) }
-
-  . = ALIGN(16);		/* Exception table */
-  __start___ex_table = .;
-  __ex_table : { *(__ex_table) }
-  __stop___ex_table = .;
-
-  __start___ksymtab = .;	/* Kernel symbol table */
-  __ksymtab : { *(__ksymtab) }
-  __stop___ksymtab = .;
-
-  _etext = .;			/* End of text section */
-
-  .data : {			/* Data */
-	*(.data)
-	CONSTRUCTORS
-	}
-
-  _edata = .;			/* End of data section */
-
-  . = ALIGN(8192);		/* init_task */
-  .data.init_task : { *(.data.init_task) }
-
-  . = ALIGN(4096);		/* Init code and data */
-  __init_begin = .;
-  .text.init : { *(.text.init) }
-  .data.init : { *(.data.init) }
-  . = ALIGN(16);
-  __setup_start = .;
-  .setup.init : { *(.setup.init) }
-  __setup_end = .;
-  __initcall_start = .;
-  .initcall.init : { *(.initcall.init) }
-  __initcall_end = .;
-  . = ALIGN(4096);
-  __init_end = .;
-
-  . = ALIGN(4096);
-  .data.page_aligned : { *(.data.idt) }
-
-  . = ALIGN(32);
-  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
-  __bss_start = .;		/* BSS */
-  .bss : {
-	*(.bss)
-	}
-  _end = . ;
-
-  /* Stabs debugging sections.  */
-  .stab 0 : { *(.stab) }
-  .stabstr 0 : { *(.stabstr) }
-  .stab.excl 0 : { *(.stab.excl) }
-  .stab.exclstr 0 : { *(.stab.exclstr) }
-  .stab.index 0 : { *(.stab.index) }
-  .stab.indexstr 0 : { *(.stab.indexstr) }
-  .comment 0 : { *(.comment) }
-}
diff -u --recursive --new-file v2.3.13/linux/arch/m68k/Makefile linux/arch/m68k/Makefile
--- v2.3.13/linux/arch/m68k/Makefile	Tue May 11 09:57:14 1999
+++ linux/arch/m68k/Makefile	Sun Aug 15 11:47:29 1999
@@ -116,6 +116,11 @@
 SUBDIRS := $(SUBDIRS) arch/m68k/ifpsp060
 endif
 
+ifdef CONFIG_M68KFPU_EMU
+CORE_FILES := $(CORE_FILES) arch/m68k/math-emu/mathemu.o
+SUBDIRS := $(SUBDIRS) arch/m68k/math-emu
+endif
+
 lilo:	vmlinux
 	if [ -f $(INSTALL_PATH)/vmlinux ]; then mv -f $(INSTALL_PATH)/vmlinux $(INSTALL_PATH)/vmlinux.old; fi
 	if [ -f $(INSTALL_PATH)/System.map ]; then mv -f $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi
diff -u --recursive --new-file v2.3.13/linux/arch/m68k/amiga/amiints.c linux/arch/m68k/amiga/amiints.c
--- v2.3.13/linux/arch/m68k/amiga/amiints.c	Thu Jan  7 08:41:55 1999
+++ linux/arch/m68k/amiga/amiints.c	Sun Aug 15 11:47:29 1999
@@ -19,6 +19,20 @@
  *                           called again.
  *           The whole interrupt handling for CIAs is moved to cia.c
  *           /Roman Zippel
+ *
+ * 07/08/99: rewamp of the interrupt handling - we now have two types of
+ *           interrupts, normal and fast handlers, fast handlers being
+ *           marked with SA_INTERRUPT and runs with all other interrupts
+ *           disabled. Normal interrupts disable their own source but
+ *           run with all other interrupt sources enabled.
+ *           PORTS and EXTER interrupts are always shared even if the
+ *           drivers do not explicitly mark this when calling
+ *           request_irq which they really should do.
+ *           This is similar to the way interrupts are handled on all
+ *           other architectures and makes a ton of sense besides
+ *           having the advantage of making it easier to share
+ *           drivers.
+ *           /Jes
  */
 
 #include <linux/types.h>
@@ -70,7 +84,7 @@
  * the amiga IRQ handling routines.
  */
 
-__initfunc(void amiga_init_IRQ(void))
+void __init amiga_init_IRQ(void)
 {
 	int i;
 
@@ -81,7 +95,7 @@
 		} else {
 			ami_irq_list[i] = new_irq_node();
 			ami_irq_list[i]->handler = ami_badint;
-			ami_irq_list[i]->flags   = IRQ_FLG_STD;
+			ami_irq_list[i]->flags   = 0;
 			ami_irq_list[i]->dev_id  = NULL;
 			ami_irq_list[i]->devname = NULL;
 			ami_irq_list[i]->next    = NULL;
@@ -117,19 +131,18 @@
 
 	cur = *list;
 
-	if (node->flags & IRQ_FLG_FAST) {
-		node->flags &= ~IRQ_FLG_SLOW;
-		while (cur && cur->flags & IRQ_FLG_FAST) {
-			list = &cur->next;
-			cur = cur->next;
-		}
-	} else if (node->flags & IRQ_FLG_SLOW) {
-		while (cur) {
+	if (node->flags & SA_INTERRUPT) {
+		if (node->flags & SA_SHIRQ)
+			return;
+		/*
+		 * There should never be more than one
+		 */
+		while (cur && cur->flags & SA_INTERRUPT) {
 			list = &cur->next;
 			cur = cur->next;
 		}
 	} else {
-		while (cur && !(cur->flags & IRQ_FLG_SLOW)) {
+		while (cur) {
 			list = &cur->next;
 			cur = cur->next;
 		}
@@ -168,13 +181,15 @@
  *                     If the addition was successful, it returns 0.
  */
 
-int amiga_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
+int amiga_request_irq(unsigned int irq,
+		      void (*handler)(int, void *, struct pt_regs *),
                       unsigned long flags, const char *devname, void *dev_id)
 {
 	irq_node_t *node;
 
 	if (irq >= AMI_IRQS) {
-		printk ("%s: Unknown IRQ %d from %s\n", __FUNCTION__, irq, devname);
+		printk ("%s: Unknown IRQ %d from %s\n", __FUNCTION__,
+			irq, devname);
 		return -ENXIO;
 	}
 
@@ -190,6 +205,11 @@
 		return cia_request_irq(&ciaa_base, irq - IRQ_AMIGA_CIAA,
 		                       handler, flags, devname, dev_id);
 
+	/*
+	 * IRQ_AMIGA_PORTS & IRQ_AMIGA_EXTER defaults to shared,
+	 * we could add a check here for the SA_SHIRQ flag but all drivers
+	 * should be aware of sharing anyway.
+	 */
 	if (ami_servers[irq]) {
 		if (!(node = new_irq_node()))
 			return -ENOMEM;
@@ -200,18 +220,6 @@
 		node->next    = NULL;
 		amiga_insert_irq(&ami_irq_list[irq], node);
 	} else {
-		if (!(ami_irq_list[irq]->flags & IRQ_FLG_STD)) {
-			if (ami_irq_list[irq]->flags & IRQ_FLG_LOCK) {
-				printk("%s: IRQ %d from %s is not replaceable\n",
-				       __FUNCTION__, irq, ami_irq_list[irq]->devname);
-				return -EBUSY;
-			}
-			if (!(flags & IRQ_FLG_REPLACE)) {
-				printk("%s: %s can't replace IRQ %d from %s\n",
-				       __FUNCTION__, devname, irq, ami_irq_list[irq]->devname);
-				return -EBUSY;
-			}
-		}
 		ami_irq_list[irq]->handler = handler;
 		ami_irq_list[irq]->flags   = flags;
 		ami_irq_list[irq]->dev_id  = dev_id;
@@ -255,7 +263,7 @@
 			printk("%s: removing probably wrong IRQ %d from %s\n",
 			       __FUNCTION__, irq, ami_irq_list[irq]->devname);
 		ami_irq_list[irq]->handler = ami_badint;
-		ami_irq_list[irq]->flags   = IRQ_FLG_STD;
+		ami_irq_list[irq]->flags   = 0;
 		ami_irq_list[irq]->dev_id  = NULL;
 		ami_irq_list[irq]->devname = NULL;
 		custom.intena = ami_intena_vals[irq];
@@ -345,37 +353,58 @@
 void amiga_do_irq_list(int irq, struct pt_regs *fp, struct irq_server *server)
 {
 	irq_node_t *node, *slow_nodes;
-	unsigned short flags;
+	unsigned short flags, intena;
 
 	kstat.irqs[0][SYS_IRQS + irq]++;
 	if (server->count++)
 		server->reentrance = 1;
-	/* serve first fast and normal handlers */
-	for (node = ami_irq_list[irq];
-	     node && (!(node->flags & IRQ_FLG_SLOW));
-	     node = node->next)
-		node->handler(irq, node->dev_id, fp);
-	custom.intreq = ami_intena_vals[irq];
+
+	intena = ami_intena_vals[irq];
+	custom.intreq = intena;
+
+	/* serve first fast handlers - there can only be one of these */
+	node = ami_irq_list[irq];
+
+	/*
+	 * Timer interrupts show up like this
+	 */
 	if (!node) {
 		server->count--;
 		return;
 	}
+
+	if (node && (node->flags & SA_INTERRUPT)) {
+		save_flags(flags);
+		cli();
+		node->handler(irq, node->dev_id, fp);
+		restore_flags(flags);
+
+		server->count--;
+		return;
+	}
+
+	/*
+	 * Disable the interrupt source in question and reenable all
+	 * other interrupts. No interrupt handler should ever touch
+	 * the intena flags directly!
+	 */
+	custom.intena = intena;
 	save_flags(flags);
-	restore_flags((flags & ~0x0700) | (fp->sr & 0x0700));
-	/* if slow handlers exists, serve them now */
+	sti();
+
 	slow_nodes = node;
 	for (;;) {
 		for (; node; node = node->next)
 			node->handler(irq, node->dev_id, fp);
-		/* if reentrance occurred, serve slow handlers again */
-		custom.intena = ami_intena_vals[irq];
+
 		if (!server->reentrance) {
 			server->count--;
-			custom.intena = IF_SETCLR | ami_intena_vals[irq];
+			restore_flags(flags);
+			custom.intena = IF_SETCLR | intena;
 			return;
 		}
+
 		server->reentrance = 0;
-		custom.intena = IF_SETCLR | ami_intena_vals[irq];
 		node = slow_nodes;
 	}
 }
@@ -493,24 +522,13 @@
 	for (i = 0; i < AMI_STD_IRQS; i++) {
 		if (!(node = ami_irq_list[i]))
 			continue;
-		if (node->flags & IRQ_FLG_STD)
-			continue;
 		len += sprintf(buf+len, "ami  %2d: %10u ", i,
 		               kstat.irqs[0][SYS_IRQS + i]);
 		do {
-			if (ami_servers[i]) {
-				if (node->flags & IRQ_FLG_FAST)
-					len += sprintf(buf+len, "F ");
-				else if (node->flags & IRQ_FLG_SLOW)
-					len += sprintf(buf+len, "S ");
-				else
-					len += sprintf(buf+len, "  ");
-			} else {
-				if (node->flags & IRQ_FLG_LOCK)
-					len += sprintf(buf+len, "L ");
-				else
-					len += sprintf(buf+len, "  ");
-			}
+			if (node->flags & SA_INTERRUPT)
+				len += sprintf(buf+len, "F ");
+			else
+				len += sprintf(buf+len, "  ");
 			len += sprintf(buf+len, "%s\n", node->devname);
 			if ((node = node->next))
 				len += sprintf(buf+len, "                    ");
diff -u --recursive --new-file v2.3.13/linux/arch/m68k/amiga/cia.c linux/arch/m68k/amiga/cia.c
--- v2.3.13/linux/arch/m68k/amiga/cia.c	Thu Feb 12 16:30:12 1998
+++ linux/arch/m68k/amiga/cia.c	Sun Aug 15 11:47:29 1999
@@ -94,20 +94,6 @@
 {
 	u_char mask;
 
-	if (!(base->irq_list[irq].flags & IRQ_FLG_STD)) {
-		if (base->irq_list[irq].flags & IRQ_FLG_LOCK) {
-			printk("%s: IRQ %i from %s is not replaceable\n",
-			       __FUNCTION__, base->cia_irq + irq,
-			       base->irq_list[irq].devname);
-			return -EBUSY;
-		}
-		if (!(flags & IRQ_FLG_REPLACE)) {
-			printk("%s: %s can't replace IRQ %i from %s\n", __FUNCTION__,
-			       devname, base->cia_irq + irq,
-			       base->irq_list[irq].devname);
-			return -EBUSY;
-		}
-	}
 	base->irq_list[irq].handler = handler;
 	base->irq_list[irq].flags   = flags;
 	base->irq_list[irq].dev_id  = dev_id;
@@ -128,7 +114,7 @@
 		       base->irq_list[irq].devname);
 
 	base->irq_list[irq].handler = NULL;
-	base->irq_list[irq].flags   = IRQ_FLG_STD;
+	base->irq_list[irq].flags   = 0;
 
 	cia_able_irq(base, 1 << irq);
 }
@@ -153,14 +139,14 @@
 	amiga_do_irq_list(base->server_irq, fp, &base->server);
 }
 
-__initfunc(void cia_init_IRQ(struct ciabase *base))
+void __init cia_init_IRQ(struct ciabase *base)
 {
 	int i;
 
 	/* init isr handlers */
 	for (i = 0; i < CIA_IRQS; i++) {
 		base->irq_list[i].handler = NULL;
-		base->irq_list[i].flags   = IRQ_FLG_STD;
+		base->irq_list[i].flags   = 0;
 	}
 
 	/* clear any pending interrupt and turn off all interrupts */
@@ -168,7 +154,7 @@
 	cia_able_irq(base, CIA_ICR_ALL);
 
 	/* install CIA handler */
-	request_irq(base->handler_irq, cia_handler, IRQ_FLG_LOCK, base->name, base);
+	request_irq(base->handler_irq, cia_handler, 0, base->name, base);
 
 	custom.intena = IF_SETCLR | base->int_mask;
 }
@@ -179,15 +165,10 @@
 
 	j = base->cia_irq;
 	for (i = 0; i < CIA_IRQS; i++) {
-		if (!(base->irq_list[i].flags & IRQ_FLG_STD)) {
-			len += sprintf(buf+len, "cia  %2d: %10d ", j + i,
-			               kstat.irqs[0][SYS_IRQS + j + i]);
-			if (base->irq_list[i].flags & IRQ_FLG_LOCK)
-				len += sprintf(buf+len, "L ");
-			else
-				len += sprintf(buf+len, "  ");
-			len += sprintf(buf+len, "%s\n", base->irq_list[i].devname);
-		}
+		len += sprintf(buf+len, "cia  %2d: %10d ", j + i,
+			       kstat.irqs[0][SYS_IRQS + j + i]);
+			len += sprintf(buf+len, "  ");
+		len += sprintf(buf+len, "%s\n", base->irq_list[i].devname);
 	}
 	return len;
 }
diff -u --recursive --new-file v2.3.13/linux/arch/m68k/amiga/config.c linux/arch/m68k/amiga/config.c
--- v2.3.13/linux/arch/m68k/amiga/config.c	Tue Jan 19 10:58:26 1999
+++ linux/arch/m68k/amiga/config.c	Sun Aug 15 11:47:29 1999
@@ -173,7 +173,7 @@
      *  Identify builtin hardware
      */
 
-__initfunc(static void amiga_identify(void))
+static void __init amiga_identify(void)
 {
   /* Fill in some default values, if necessary */
   if (amiga_eclock == 0)
@@ -334,7 +334,7 @@
      *  Setup the Amiga configuration info
      */
 
-__initfunc(void config_amiga(void))
+void __init config_amiga(void)
 {
   amiga_debug_init();
   amiga_identify();
@@ -446,8 +446,8 @@
 
 static unsigned short jiffy_ticks;
 
-__initfunc(static void amiga_sched_init(void (*timer_routine)(int, void *,
-					struct pt_regs *)))
+static void __init amiga_sched_init(void (*timer_routine)(int, void *,
+							  struct pt_regs *))
 {
 	jiffy_ticks = (amiga_eclock+HZ/2)/HZ;
 
@@ -460,8 +460,7 @@
 	 * Please don't change this to use ciaa, as it interferes with the
 	 * SCSI code. We'll have to take a look at this later
 	 */
-	request_irq(IRQ_AMIGA_CIAB_TA, timer_routine, IRQ_FLG_LOCK,
-		    "timer", NULL);
+	request_irq(IRQ_AMIGA_CIAB_TA, timer_routine, 0, "timer", NULL);
 	/* start timer */
 	ciab.cra |= 0x11;
 }
@@ -880,7 +879,7 @@
 }
 #endif
 
-__initfunc(static void amiga_debug_init(void))
+static void __init amiga_debug_init(void)
 {
 	if (!strcmp( m68k_debug_device, "ser" )) {
 		/* no initialization required (?) */
diff -u --recursive --new-file v2.3.13/linux/arch/m68k/config.in linux/arch/m68k/config.in
--- v2.3.13/linux/arch/m68k/config.in	Mon Aug  9 14:59:19 1999
+++ linux/arch/m68k/config.in	Sun Aug 15 11:47:29 1999
@@ -58,6 +58,13 @@
 bool '68030 support' CONFIG_M68030
 bool '68040 support' CONFIG_M68040
 bool '68060 support' CONFIG_M68060
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+  bool 'Math emulation support' CONFIG_M68KFPU_EMU
+  if [ "$CONFIG_M68KFPU_EMU" = "y" ]; then
+    bool 'Math emulation extra precision' CONFIG_M68KFPU_EMU_EXTRAPREC
+    bool 'Math emulation only kernel' CONFIG_M68KFPU_EMU_ONLY
+  fi
+fi
 bool 'Advanced configuration options' CONFIG_ADVANCED
 if [ "$CONFIG_ADVANCED" = "y" ]; then
   bool 'Use read-modify-write instructions' CONFIG_RMW_INSNS
diff -u --recursive --new-file v2.3.13/linux/arch/m68k/kernel/entry.S linux/arch/m68k/kernel/entry.S
--- v2.3.13/linux/arch/m68k/kernel/entry.S	Mon Aug  9 14:59:19 1999
+++ linux/arch/m68k/kernel/entry.S	Sun Aug 15 11:47:29 1999
@@ -164,6 +164,36 @@
 	addql	#4,%sp
 	jra	5b
 
+
+#if 0
+#if CONFIG_AMIGA
+SYMBOL_NAME_LABEL(ami_inthandler)
+	addql	#1,SYMBOL_NAME(local_irq_count)
+	SAVE_ALL_INT
+	GET_CURRENT(%d0)
+
+	bfextu	%sp@(PT_VECTOR){#4,#12},%d0
+	movel	%d0,%a0
+	addql	#1,%a0@(SYMBOL_NAME(kstat)+STAT_IRQ-VECOFF(VEC_SPUR))
+	movel	%a0@(SYMBOL_NAME(autoirq_list)-VECOFF(VEC_SPUR)),%a0
+
+| amiga vector int handler get the req mask instead of irq vector
+	lea	CUSTOMBASE,%a1
+	movew	%a1@(C_INTREQR),%d0
+	andw	%a1@(C_INTENAR),%d0
+
+| prepare stack (push frame pointer, dev_id & req mask)
+	pea	%sp@
+	movel	%a0@(IRQ_DEVID),%sp@-
+	movel	%d0,%sp@-
+	pea	%pc@(SYMBOL_NAME(ret_from_interrupt):w)
+	jbra	@(IRQ_HANDLER,%a0)@(0)
+
+ENTRY(nmi_handler)
+	rte
+#endif
+#endif
+
 /*
 ** This is the main interrupt handler, responsible for calling process_int()
 */
@@ -183,7 +213,7 @@
 	jbeq	1f
 	jbsr	SYMBOL_NAME(floppy_hardint)
 	jbra	3f
-1:		
+1:
 #endif		
 	jbsr	SYMBOL_NAME(process_int)|  process the IRQ
 3:     	addql	#8,%sp			|  pop parameters off stack
@@ -191,7 +221,7 @@
 SYMBOL_NAME_LABEL(ret_from_interrupt)
 	subql	#1,SYMBOL_NAME(local_irq_count)
 	jeq	1f
-2:	
+2:
 	RESTORE_ALL
 1:
 #if 1
@@ -295,6 +325,11 @@
 	movel	%sp,%a0@(TASK_THREAD+THREAD_KSP)
 
 	/* save floating point context */
+#ifndef CONFIG_M68KFPU_EMU_ONLY
+#ifdef CONFIG_M68KFPU_EMU
+	tstl	SYMBOL_NAME(m68k_fputype)
+	jeq	3f
+#endif
 	fsave	%a0@(TASK_THREAD+THREAD_FPSTATE)
 
 #if defined(CONFIG_M68060)
@@ -316,6 +351,7 @@
 2:	fmovemx	%fp0-%fp7,%a0@(TASK_THREAD+THREAD_FPREG)
 	fmoveml	%fpcr/%fpsr/%fpiar,%a0@(TASK_THREAD+THREAD_FPCNTL)
 3:
+#endif	/* CONFIG_M68KFPU_EMU_ONLY */
 	/* Return previous task in %d1 */
 	movel	%curptr,%d1
 
@@ -323,7 +359,11 @@
 	movel	%a1,%curptr
 
 	/* restore floating point context */
-
+#ifndef CONFIG_M68KFPU_EMU_ONLY
+#ifdef CONFIG_M68KFPU_EMU
+	tstl	SYMBOL_NAME(m68k_fputype)
+	jeq	4f
+#endif
 #if defined(CONFIG_M68060)
 #if !defined(CPU_M68060_ONLY)
 	btst	#3,SYMBOL_NAME(m68k_cputype)+3
@@ -343,6 +383,8 @@
 2:	fmovemx	%a1@(TASK_THREAD+THREAD_FPREG),%fp0-%fp7
 	fmoveml	%a1@(TASK_THREAD+THREAD_FPCNTL),%fpcr/%fpsr/%fpiar
 3:	frestore %a1@(TASK_THREAD+THREAD_FPSTATE)
+4:
+#endif	/* CONFIG_M68KFPU_EMU_ONLY */
 
 	/* restore the kernel stack pointer */
 	movel	%a1@(TASK_THREAD+THREAD_KSP),%sp
diff -u --recursive --new-file v2.3.13/linux/arch/m68k/kernel/head.S linux/arch/m68k/kernel/head.S
--- v2.3.13/linux/arch/m68k/kernel/head.S	Tue May 11 09:57:14 1999
+++ linux/arch/m68k/kernel/head.S	Sun Aug 15 11:47:29 1999
@@ -503,10 +503,18 @@
 
 .macro	puts		string
 #if defined(CONSOLE) || defined(SERIAL_DEBUG)
+/* The __INITDATA stuff is a no-op when ftrace or kgdb are turned on */
+#if defined(CONFIG_FTRACE) || defined(CONFIG_KGDB)
+	bra 1f
+#endif
 	__INITDATA
 .Lstr\@:
 	.string	"\string"
 	__FINIT
+#if defined(CONFIG_FTRACE) || defined(CONFIG_KGDB)
+	.align 2
+1:
+#endif
 	pea	%pc@(.Lstr\@)
 	func_call	puts
 	addql	#4,%sp
diff -u --recursive --new-file v2.3.13/linux/arch/m68k/kernel/ints.c linux/arch/m68k/kernel/ints.c
--- v2.3.13/linux/arch/m68k/kernel/ints.c	Wed May 12 08:50:00 1999
+++ linux/arch/m68k/kernel/ints.c	Sun Aug 15 11:47:29 1999
@@ -86,14 +86,14 @@
  * the IRQ handling routines.
  */
 
-__initfunc(void init_IRQ(void))
+void __init init_IRQ(void)
 {
 	int i;
 
 	for (i = 0; i < SYS_IRQS; i++) {
 		if (mach_default_handler)
 			irq_list[i].handler = (*mach_default_handler)[i];
-		irq_list[i].flags   = IRQ_FLG_STD;
+		irq_list[i].flags   = 0;
 		irq_list[i].dev_id  = NULL;
 		irq_list[i].devname = default_names[i];
 	}
@@ -144,6 +144,7 @@
 		return -ENXIO;
 	}
 
+#if 0
 	if (!(irq_list[irq].flags & IRQ_FLG_STD)) {
 		if (irq_list[irq].flags & IRQ_FLG_LOCK) {
 			printk("%s: IRQ %d from %s is not replaceable\n",
@@ -156,6 +157,8 @@
 			return -EBUSY;
 		}
 	}
+#endif
+
 	irq_list[irq].handler = handler;
 	irq_list[irq].flags   = flags;
 	irq_list[irq].dev_id  = dev_id;
@@ -175,7 +178,7 @@
 		       __FUNCTION__, irq, irq_list[irq].devname);
 
 	irq_list[irq].handler = (*mach_default_handler)[irq];
-	irq_list[irq].flags   = IRQ_FLG_STD;
+	irq_list[irq].flags   = 0;
 	irq_list[irq].dev_id  = NULL;
 	irq_list[irq].devname = default_names[irq];
 }
@@ -250,9 +253,6 @@
 		for (i = 0; i < SYS_IRQS; i++) {
 			len += sprintf(buf+len, "auto %2d: %10u ", i,
 			               i ? kstat.irqs[0][i] : num_spurious);
-			if (irq_list[i].flags & IRQ_FLG_LOCK)
-				len += sprintf(buf+len, "L ");
-			else
 				len += sprintf(buf+len, "  ");
 			len += sprintf(buf+len, "%s\n", irq_list[i].devname);
 		}
diff -u --recursive --new-file v2.3.13/linux/arch/m68k/kernel/m68k_defs.h linux/arch/m68k/kernel/m68k_defs.h
--- v2.3.13/linux/arch/m68k/kernel/m68k_defs.h	Tue May 11 09:57:14 1999
+++ linux/arch/m68k/kernel/m68k_defs.h	Sun Aug 15 11:47:29 1999
@@ -7,19 +7,29 @@
 #define TASK_FLAGS 4
 #define TASK_SIGPENDING 8
 #define TASK_NEEDRESCHED 20
-#define TASK_TSS 470
-#define TASK_MM 622
-#define TSS_KSP 0
-#define TSS_USP 4
-#define TSS_SR 8
-#define TSS_FS 10
-#define TSS_CRP 12
-#define TSS_ESP0 20
-#define TSS_FPREG 24
-#define TSS_FPCNTL 120
-#define TSS_FPSTATE 132
+#define TASK_THREAD 482
+#define TASK_MM 634
+#define TASK_ACTIVE_MM 638
+#define THREAD_KSP 0
+#define THREAD_USP 4
+#define THREAD_SR 8
+#define THREAD_FS 10
+#define THREAD_CRP 12
+#define THREAD_ESP0 20
+#define THREAD_FPREG 24
+#define THREAD_FPCNTL 120
+#define THREAD_FPSTATE 132
 #define PT_D0 32
 #define PT_ORIG_D0 36
+#define PT_D1 0
+#define PT_D2 4
+#define PT_D3 8
+#define PT_D4 12
+#define PT_D5 16
+#define PT_A0 20
+#define PT_A1 24
+#define PT_A2 28
+#define PT_PC 46
 #define PT_SR 44
 #define PT_VECTOR 50
 #define IRQ_HANDLER 0
@@ -35,6 +45,10 @@
 #define FBCON_FONT_DESC_HEIGHT 12
 #define FBCON_FONT_DESC_DATA 16
 #define FBCON_FONT_DESC_PREF 20
+#define SIGSEGV 11
+#define SEGV_MAPERR 1
+#define SIGTRAP 5
+#define TRAP_TRACE 2
 #define CUSTOMBASE -2132807680
 #define C_INTENAR 28
 #define C_INTREQR 30
diff -u --recursive --new-file v2.3.13/linux/arch/m68k/kernel/process.c linux/arch/m68k/kernel/process.c
--- v2.3.13/linux/arch/m68k/kernel/process.c	Mon Aug  9 14:59:19 1999
+++ linux/arch/m68k/kernel/process.c	Sun Aug 15 11:47:29 1999
@@ -58,7 +58,7 @@
 {
 	while(1) {
 		if (!current->need_resched)
-#ifdef MACH_ATARI_ONLY
+#if defined(MACH_ATARI_ONLY) && !defined(CONFIG_HADES)
 			/* block out HSYNC on the atari (falcon) */
 			__asm__("stop #0x2200" : : : "cc");
 #else
@@ -161,9 +161,10 @@
 	unsigned long zero = 0;
 	set_fs(USER_DS);
 	current->thread.fs = __USER_DS;
-	asm volatile (".chip 68k/68881\n\t"
-		      "frestore %0@\n\t"
-		      ".chip 68k" : : "a" (&zero));
+	if (!FPU_IS_EMU)
+		asm volatile (".chip 68k/68881\n\t"
+			      "frestore %0@\n\t"
+			      ".chip 68k" : : "a" (&zero));
 }
 
 /*
@@ -224,16 +225,18 @@
 	 */
 	p->thread.fs = get_fs().seg;
 
-	/* Copy the current fpu state */
-	asm volatile ("fsave %0" : : "m" (p->thread.fpstate[0]) : "memory");
-
-	if (!CPU_IS_060 ? p->thread.fpstate[0] : p->thread.fpstate[2])
-	  asm volatile ("fmovemx %/fp0-%/fp7,%0\n\t"
-			"fmoveml %/fpiar/%/fpcr/%/fpsr,%1"
-			: : "m" (p->thread.fp[0]), "m" (p->thread.fpcntl[0])
-			: "memory");
-	/* Restore the state in case the fpu was busy */
-	asm volatile ("frestore %0" : : "m" (p->thread.fpstate[0]));
+	if (!FPU_IS_EMU) {
+		/* Copy the current fpu state */
+		asm volatile ("fsave %0" : : "m" (p->thread.fpstate[0]) : "memory");
+
+		if (!CPU_IS_060 ? p->thread.fpstate[0] : p->thread.fpstate[2])
+		  asm volatile ("fmovemx %/fp0-%/fp7,%0\n\t"
+				"fmoveml %/fpiar/%/fpcr/%/fpsr,%1"
+				: : "m" (p->thread.fp[0]), "m" (p->thread.fpcntl[0])
+				: "memory");
+		/* Restore the state in case the fpu was busy */
+		asm volatile ("frestore %0" : : "m" (p->thread.fpstate[0]));
+	}
 
 	return 0;
 }
@@ -244,18 +247,32 @@
 {
 	char fpustate[216];
 
-  /* First dump the fpu context to avoid protocol violation.  */
-  asm volatile ("fsave %0" :: "m" (fpustate[0]) : "memory");
-  if (!CPU_IS_060 ? !fpustate[0] : !fpustate[2])
-     return 0;
+	if (FPU_IS_EMU) {
+		int i;
+
+		memcpy(fpu->fpcntl, current->thread.fpcntl, 12);
+		memcpy(fpu->fpregs, current->thread.fp, 96);
+		/* Convert internal fpu reg representation
+		 * into long double format
+		 */
+		for (i = 0; i < 24; i += 3)
+			fpu->fpregs[i] = ((fpu->fpregs[i] & 0xffff0000) << 15) |
+			                 ((fpu->fpregs[i] & 0x0000ffff) << 16);
+		return 1;
+	}
+
+	/* First dump the fpu context to avoid protocol violation.  */
+	asm volatile ("fsave %0" :: "m" (fpustate[0]) : "memory");
+	if (!CPU_IS_060 ? !fpustate[0] : !fpustate[2])
+		return 0;
 
-  asm volatile ("fmovem %/fpiar/%/fpcr/%/fpsr,%0"
+	asm volatile ("fmovem %/fpiar/%/fpcr/%/fpsr,%0"
 		:: "m" (fpu->fpcntl[0])
 		: "memory");
-  asm volatile ("fmovemx %/fp0-%/fp7,%0"
+	asm volatile ("fmovemx %/fp0-%/fp7,%0"
 		:: "m" (fpu->fpregs[0])
 		: "memory");
-  return 1;
+	return 1;
 }
 
 /*
diff -u --recursive --new-file v2.3.13/linux/arch/m68k/kernel/ptrace.c linux/arch/m68k/kernel/ptrace.c
--- v2.3.13/linux/arch/m68k/kernel/ptrace.c	Mon Aug  9 14:59:19 1999
+++ linux/arch/m68k/kernel/ptrace.c	Sun Aug 15 11:47:29 1999
@@ -18,6 +18,7 @@
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
+#include <linux/config.h>
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
@@ -384,10 +385,17 @@
 				tmp = get_reg(child, addr);
 				if (addr == PT_SR)
 					tmp >>= 16;
-			}
-			else if (addr >= 21 && addr < 49)
+			} else if (addr >= 21 && addr < 49) {
 				tmp = child->thread.fp[addr - 21];
-			else
+#ifdef CONFIG_M68KFPU_EMU
+				/* Convert internal fpu reg representation
+				 * into long double format
+				 */
+				if (FPU_IS_EMU && (addr < 45) && !(addr % 3))
+					tmp = ((tmp & 0xffff0000) << 15) |
+					      ((tmp & 0x0000ffff) << 16);
+#endif
+			} else
 				goto out;
 			ret = put_user(tmp,(unsigned long *) data);
 			goto out;
@@ -423,6 +431,16 @@
 			}
 			if (addr >= 21 && addr < 48)
 			{
+#ifdef CONFIG_M68KFPU_EMU
+				/* Convert long double format
+				 * into internal fpu reg representation
+				 */
+				if (FPU_IS_EMU && (addr < 45) && !(addr % 3)) {
+					data = (unsigned long)data << 15;
+					data = (data & 0xffff0000) |
+					       ((data & 0x0000ffff) >> 1);
+				}
+#endif
 				child->thread.fp[addr - 21] = data;
 				ret = 0;
 			}
diff -u --recursive --new-file v2.3.13/linux/arch/m68k/kernel/signal.c linux/arch/m68k/kernel/signal.c
--- v2.3.13/linux/arch/m68k/kernel/signal.c	Mon Aug  9 14:59:19 1999
+++ linux/arch/m68k/kernel/signal.c	Sun Aug 15 11:47:29 1999
@@ -14,6 +14,10 @@
  * 68060 fixes by Jesper Skov
  *
  * 1997-12-01  Modified for POSIX.1b signals by Andreas Schwab
+ *
+ * mathemu support by Roman Zippel
+ *  (Note: fpstate in the signal context is completly ignored for the emulator
+ *         and the internal floating point format is put on stack)
  */
 
 /*
@@ -190,6 +194,13 @@
 {
 	int err = 1;
 
+	if (FPU_IS_EMU) {
+	    /* restore registers */
+	    memcpy(current->thread.fpcntl, sc->sc_fpcntl, 12);
+	    memcpy(current->thread.fp, sc->sc_fpregs, 24);
+	    return 0;
+	}
+
 	if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {
 	    /* Verify the frame format.  */
 	    if (!CPU_IS_060 && (sc->sc_fpstate[0] != fpu_version))
@@ -242,6 +253,18 @@
 	fpregset_t fpregs;
 	int err = 1;
 
+	if (FPU_IS_EMU) {
+		/* restore fpu control register */
+		if (__copy_from_user(current->thread.fpcntl,
+				&uc->uc_mcontext.fpregs.f_pcr, 12))
+			goto out;
+		/* restore all other fpu register */
+		if (__copy_from_user(current->thread.fp,
+				uc->uc_mcontext.fpregs.f_fpregs, 96))
+			goto out;
+		return 0;
+	}
+
 	if (__get_user(*(long *)fpstate, (long *)&uc->uc_fpstate))
 		goto out;
 	if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
@@ -539,6 +562,13 @@
 
 static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs)
 {
+	if (FPU_IS_EMU) {
+		/* save registers */
+		memcpy(sc->sc_fpcntl, current->thread.fpcntl, 12);
+		memcpy(sc->sc_fpregs, current->thread.fp, 24);
+		return;
+	}
+
 	__asm__ volatile (".chip 68k/68881\n\t"
 			  "fsave %0\n\t"
 			  ".chip 68k"
@@ -569,6 +599,16 @@
 	unsigned char fpstate[FPCONTEXT_SIZE];
 	int context_size = CPU_IS_060 ? 8 : 0;
 	int err = 0;
+
+	if (FPU_IS_EMU) {
+		/* save fpu control register */
+		err |= copy_to_user(&uc->uc_mcontext.fpregs.f_pcr,
+				current->thread.fpcntl, 12);
+		/* save all other fpu register */
+		err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs,
+				current->thread.fp, 96);
+		return err;
+	}
 
 	__asm__ volatile (".chip 68k/68881\n\t"
 			  "fsave %0\n\t"
diff -u --recursive --new-file v2.3.13/linux/arch/m68k/kernel/traps.c linux/arch/m68k/kernel/traps.c
--- v2.3.13/linux/arch/m68k/kernel/traps.c	Mon Aug  9 14:59:19 1999
+++ linux/arch/m68k/kernel/traps.c	Sun Aug 15 11:47:29 1999
@@ -47,6 +47,7 @@
 asmlinkage void trap(void);
 asmlinkage void inthandler(void);
 asmlinkage void nmihandler(void);
+asmlinkage void fpu_emu(void);
 
 e_vector vectors[256] = {
 	0, 0, buserr, trap, trap, trap, trap, trap,
@@ -65,12 +66,12 @@
     __ALIGN_STR "\n"
     SYMBOL_NAME_STR(nmihandler) ": rte");
 
-__initfunc(void base_trap_init(void))
+void __init base_trap_init(void)
 {
 	/* setup the exception vector table */
 	__asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors));
 
-	if (CPU_IS_040) {
+	if (CPU_IS_040 && !FPU_IS_EMU) {
 		/* set up FPSP entry points */
 		asmlinkage void dz_vec(void) asm ("dz");
 		asmlinkage void inex_vec(void) asm ("inex");
@@ -93,6 +94,12 @@
 		vectors[VEC_FPUNSUP] = unsupp_vec;
 	}
 	if (CPU_IS_060) {
+		/* set up ISP entry points */
+		asmlinkage void unimp_vec(void) asm ("_060_isp_unimp");
+
+		vectors[VEC_UNIMPII] = unimp_vec;
+	}
+	if (CPU_IS_060 && !FPU_IS_EMU) {
 		/* set up IFPSP entry points */
 		asmlinkage void snan_vec(void) asm ("_060_fpsp_snan");
 		asmlinkage void operr_vec(void) asm ("_060_fpsp_operr");
@@ -104,8 +111,6 @@
 		asmlinkage void unsupp_vec(void) asm ("_060_fpsp_unsupp");
 		asmlinkage void effadd_vec(void) asm ("_060_fpsp_effadd");
 
-		asmlinkage void unimp_vec(void) asm ("_060_isp_unimp");
-
 		vectors[VEC_FPNAN] = snan_vec;
 		vectors[VEC_FPOE] = operr_vec;
 		vectors[VEC_FPOVER] = ovfl_vec;
@@ -115,14 +120,10 @@
 		vectors[VEC_LINE11] = fline_vec;
 		vectors[VEC_FPUNSUP] = unsupp_vec;
 		vectors[VEC_UNIMPEA] = effadd_vec;
-
-		/* set up ISP entry points */
-
-		vectors[VEC_UNIMPII] = unimp_vec;
 	}
 }
 
-__initfunc(void trap_init (void))
+void __init trap_init (void)
 {
 	int i;
 
@@ -133,18 +134,17 @@
 	for (i = 64; i < 256; i++)
 		vectors[i] = inthandler;
 
+#ifdef CONFIG_M68KFPU_EMU
+	if (FPU_IS_EMU)
+		vectors[VEC_LINE11] = fpu_emu;
+#endif
+
         /* if running on an amiga, make the NMI interrupt do nothing */
 	if (MACH_IS_AMIGA) {
 		vectors[VEC_INT7] = nmihandler;
 	}
 }
 
-void set_evector(int vecnum, void (*handler)(void))
-{
-	if (vecnum >= 0 && vecnum <= 256)
-		vectors[vecnum] = handler;
-}
-
 
 static inline void console_verbose(void)
 {
@@ -152,6 +152,7 @@
 	console_loglevel = 15;
 }
 
+
 static char *vec_names[] = {
 	"RESET SP", "RESET PC", "BUS ERROR", "ADDRESS ERROR",
 	"ILLEGAL INSTRUCTION", "ZERO DIVIDE", "CHK", "TRAPcc",
@@ -180,7 +181,6 @@
 	};
 
 
-
 void die_if_kernel(char *,struct pt_regs *,int);
 asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
                              unsigned long error_code);
@@ -507,44 +507,6 @@
 	    else
 		    asm volatile ("ploadr %1,%0@" : /* no outputs */
 				  : "a" (addr), "d" (ssw));
-
-#if 0
-	    /* If this was a data fault due to an invalid page and a
-	       prefetch is pending on the same page, simulate it (but
-	       only if the page is now valid).  Otherwise we'll get an
-	       weird insn access.  */
-	    if ((ssw & RB) && (mmusr & MMU_I))
-	      {
-		unsigned long iaddr;
-
-		if ((fp->ptregs.format) == 0xB)
-		  iaddr = fp->un.fmtb.baddr;
-		else
-		  iaddr = fp->ptregs.pc + 4;
-		if (((addr ^ iaddr) & PAGE_MASK) == 0)
-		  {
-		    /* We only need to check the ATC as the entry has
-		       already been set up above.  */
-		    asm volatile ("ptestr #1,%1@,#0\n\t"
-				  "pmove %/psr,%0@"
-				  : : "a" (&temp), "a" (iaddr));
-		    mmusr = temp;
-#ifdef DEBUG
-		    printk ("prefetch iaddr=%#lx ssw=%#x mmusr=%#x\n",
-			    iaddr, ssw, mmusr);
-#endif
-		    if (!(mmusr & MMU_I))
-		      {
-			unsigned short insn;
-			asm volatile ("movesw %1@,%0"
-				      : "=r" (insn)
-				      : "a" (iaddr));
-			fp->un.fmtb.isb = insn;
-			fp->un.fmtb.ssw &= ~RB;
-		      }
-		  }
-	      }
-#endif
 	  }
 
 	/* Now handle the instruction fault. */
@@ -598,43 +560,6 @@
 		die_if_kernel("Oops",&fp->ptregs,mmusr);
 		force_sig(SIGSEGV, current);
 		return;
-	} else {
-#if 0 /* stale ATC entry??  Ignore it */
-
-#ifdef DEBUG
-		static volatile long tlong;
-#endif
-
-		printk ("weird insn access at %#lx from pc %#lx (ssw is %#x)\n",
-			addr, fp->ptregs.pc, ssw);
-		asm volatile ("ptestr #1,%1@,#0\n\t"
-			      "pmove %/psr,%0@"
-			      : /* no outputs */
-			      : "a" (&temp), "a" (addr));
-		mmusr = temp;
-		      
-		printk ("level 0 mmusr is %#x\n", mmusr);
-#ifdef DEBUG
-		if (m68k_cputype & CPU_68030) {
-			asm volatile ("pmove %/tt0,%0@"
-				      : /* no outputs */
-				      : "a" (&tlong));
-			printk ("tt0 is %#lx, ", tlong);
-			asm volatile ("pmove %/tt1,%0@"
-				      : /* no outputs */
-				      : "a" (&tlong));
-			printk ("tt1 is %#lx\n", tlong);
-		}
-
-#endif
-
-#if DEBUG
-		printk("Unknown SIGSEGV - 3\n");
-#endif
-		die_if_kernel("Oops",&fp->ptregs,mmusr);
-		force_sig(SIGSEGV, current);
-		return;
-#endif
 	}
 
 create_atc_entry:
@@ -990,3 +915,16 @@
 {
 	do_exit(SIGSEGV);
 }
+
+#ifdef CONFIG_M68KFPU_EMU
+asmlinkage void fpemu_signal(int signal, int code, void *addr)
+{
+	siginfo_t info;
+
+	info.si_signo = signal;
+	info.si_errno = 0;
+	info.si_code = code;
+	info.si_addr = addr;
+	force_sig_info(signal, &info, current);
+}
+#endif
diff -u --recursive --new-file v2.3.13/linux/arch/m68k/math-emu/Makefile linux/arch/m68k/math-emu/Makefile
--- v2.3.13/linux/arch/m68k/math-emu/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/math-emu/Makefile	Sun Aug 15 11:47:29 1999
@@ -0,0 +1,19 @@
+#
+# Makefile for the linux kernel.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+.S.o:
+	$(CC) $(EXTRA_CFLAGS) -D__ASSEMBLY__ -traditional -c $< -o $*.o
+
+#EXTRA_CFLAGS=-DFPU_EMU_DEBUG
+
+O_TARGET := mathemu.o
+O_OBJS := fp_entry.o fp_scan.o fp_util.o fp_move.o fp_movem.o \
+	  fp_cond.o fp_arith.o fp_log.o fp_trig.o
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.13/linux/arch/m68k/math-emu/fp_arith.c linux/arch/m68k/math-emu/fp_arith.c
--- v2.3.13/linux/arch/m68k/math-emu/fp_arith.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/math-emu/fp_arith.c	Sun Aug 15 11:47:29 1999
@@ -0,0 +1,700 @@
+/*
+
+   fp_arith.c: floating-point math routines for the Linux-m68k
+   floating point emulator.
+
+   Copyright (c) 1998-1999 David Huggins-Daines.
+
+   Somewhat based on the AlphaLinux floating point emulator, by David
+   Mosberger-Tang.
+
+   You may copy, modify, and redistribute this file under the terms of
+   the GNU General Public License, version 2, or any later version, at
+   your convenience.
+ */
+
+#include "fp_emu.h"
+#include "multi_arith.h"
+#include "fp_arith.h"
+
+const struct fp_ext fp_QNaN =
+{
+	0, 0, 0x7fff, { ~0 }
+};
+
+const struct fp_ext fp_Inf =
+{
+	0, 0, 0x7fff, { 0 }
+};
+
+/* let's start with the easy ones */
+
+struct fp_ext *
+fp_fabs(struct fp_ext *dest, struct fp_ext *src)
+{
+	dprint(PINSTR, "fabs\n");
+
+	fp_monadic_check(dest, src);
+
+	dest->sign = 0;
+
+	return dest;
+}
+
+struct fp_ext *
+fp_fneg(struct fp_ext *dest, struct fp_ext *src)
+{
+	dprint(PINSTR, "fneg\n");
+
+	fp_monadic_check(dest, src);
+
+	dest->sign = !dest->sign;
+
+	return dest;
+}
+
+/* Now, the slightly harder ones */
+
+/* fp_fadd: Implements the kernel of the FADD, FSADD, FDADD, FSUB,
+   FDSUB, and FCMP instructions. */
+
+struct fp_ext *
+fp_fadd(struct fp_ext *dest, struct fp_ext *src)
+{
+	int diff;
+
+	dprint(PINSTR, "fadd\n");
+
+	fp_dyadic_check(dest, src);
+
+	if (IS_INF(dest)) {
+		/* infinity - infinity == NaN */
+		if (IS_INF(src) && (src->sign != dest->sign))
+			fp_set_nan(dest);
+		return dest;
+	}
+	if (IS_INF(src)) {
+		fp_copy_ext(dest, src);
+		return dest;
+	}
+
+	if (IS_ZERO(dest)) {
+		if (IS_ZERO(src)) {
+			if (src->sign != dest->sign) {
+				if (FPDATA->rnd == FPCR_ROUND_RM)
+					dest->sign = 1;
+				else
+					dest->sign = 0;
+			}
+		} else
+			fp_copy_ext(dest, src);
+		return dest;
+	}
+
+	dest->lowmant = src->lowmant = 0;
+
+	if ((diff = dest->exp - src->exp) > 0)
+		fp_denormalize(src, diff);
+	else if ((diff = -diff) > 0)
+		fp_denormalize(dest, diff);
+
+	if (dest->sign == src->sign) {
+		if (fp_addmant(dest, src))
+			if (!fp_addcarry(dest))
+				return dest;
+	} else {
+		if (dest->mant.m64 < src->mant.m64) {
+			fp_submant(dest, src, dest);
+			dest->sign = !dest->sign;
+		} else
+			fp_submant(dest, dest, src);
+	}
+
+	return dest;
+}
+
+/* fp_fsub: Implementes the kernel of the FSUB, FSSUB, and FDSUB
+   instructions.
+
+   Remember that the arguments are in assembler-syntax order! */
+
+struct fp_ext *
+fp_fsub(struct fp_ext *dest, struct fp_ext *src)
+{
+	dprint(PINSTR, "fsub ");
+
+	src->sign = !src->sign;
+	return fp_fadd(dest, src);
+}
+
+
+struct fp_ext *
+fp_fcmp(struct fp_ext *dest, struct fp_ext *src)
+{
+	dprint(PINSTR, "fcmp ");
+
+	FPDATA->temp[1] = *dest;
+	src->sign = !src->sign;
+	return fp_fadd(&FPDATA->temp[1], src);
+}
+
+struct fp_ext *
+fp_ftst(struct fp_ext *dest, struct fp_ext *src)
+{
+	dprint(PINSTR, "ftst\n");
+
+	(void)dest;
+
+	return src;
+}
+
+struct fp_ext *
+fp_fmul(struct fp_ext *dest, struct fp_ext *src)
+{
+	union fp_mant128 temp;
+	int exp;
+
+	dprint(PINSTR, "fmul\n");
+
+	fp_dyadic_check(dest, src);
+
+	/* calculate the correct sign now, as it's necessary for infinities */
+	dest->sign = src->sign ^ dest->sign;
+
+	/* Handle infinities */
+	if (IS_INF(dest)) {
+		if (IS_ZERO(src))
+			fp_set_nan(dest);
+		return dest;
+	}
+	if (IS_INF(src)) {
+		if (IS_ZERO(dest))
+			fp_set_nan(dest);
+		else
+			fp_copy_ext(dest, src);
+		return dest;
+	}
+
+	/* Of course, as we all know, zero * anything = zero.  You may
+	   not have known that it might be a positive or negative
+	   zero... */
+	if (IS_ZERO(dest) || IS_ZERO(src)) {
+		dest->exp = 0;
+		dest->mant.m64 = 0;
+		dest->lowmant = 0;
+
+		return dest;
+	}
+
+	exp = dest->exp + src->exp - 0x3ffe;
+
+	/* shift up the mantissa for denormalized numbers,
+	   so that the highest bit is set, this makes the
+	   shift of the result below easier */
+	if ((long)dest->mant.m32[0] >= 0)
+		exp -= fp_overnormalize(dest);
+	if ((long)src->mant.m32[0] >= 0)
+		exp -= fp_overnormalize(src);
+
+	/* now, do a 64-bit multiply with expansion */
+	fp_multiplymant(&temp, dest, src);
+
+	/* normalize it back to 64 bits and stuff it back into the
+	   destination struct */
+	if ((long)temp.m32[0] > 0) {
+		exp--;
+		fp_putmant128(dest, &temp, 1);
+	} else
+		fp_putmant128(dest, &temp, 0);
+
+	if (exp >= 0x7fff) {
+		fp_set_ovrflw(dest);
+		return dest;
+	}
+	dest->exp = exp;
+	if (exp < 0) {
+		fp_set_sr(FPSR_EXC_UNFL);
+		fp_denormalize(dest, -exp);
+	}
+
+	return dest;
+}
+
+/* fp_fdiv: Implements the "kernel" of the FDIV, FSDIV, FDDIV and
+   FSGLDIV instructions.
+
+   Note that the order of the operands is counter-intuitive: instead
+   of src / dest, the result is actually dest / src. */
+
+struct fp_ext *
+fp_fdiv(struct fp_ext *dest, struct fp_ext *src)
+{
+	union fp_mant128 temp;
+	int exp;
+
+	dprint(PINSTR, "fdiv\n");
+
+	fp_dyadic_check(dest, src);
+
+	/* calculate the correct sign now, as it's necessary for infinities */
+	dest->sign = src->sign ^ dest->sign;
+
+	/* Handle infinities */
+	if (IS_INF(dest)) {
+		/* infinity / infinity = NaN (quiet, as always) */
+		if (IS_INF(src))
+			fp_set_nan(dest);
+		/* infinity / anything else = infinity (with approprate sign) */
+		return dest;
+	}
+	if (IS_INF(src)) {
+		/* anything / infinity = zero (with appropriate sign) */
+		dest->exp = 0;
+		dest->mant.m64 = 0;
+		dest->lowmant = 0;
+
+		return dest;
+	}
+
+	/* zeroes */
+	if (IS_ZERO(dest)) {
+		/* zero / zero = NaN */
+		if (IS_ZERO(src))
+			fp_set_nan(dest);
+		/* zero / anything else = zero */
+		return dest;
+	}
+	if (IS_ZERO(src)) {
+		/* anything / zero = infinity (with appropriate sign) */
+		fp_set_sr(FPSR_EXC_DZ);
+		dest->exp = 0x7fff;
+		dest->mant.m64 = 0;
+
+		return dest;
+	}
+
+	exp = dest->exp - src->exp + 0x3fff;
+
+	/* shift up the mantissa for denormalized numbers,
+	   so that the highest bit is set, this makes lots
+	   of things below easier */
+	if ((long)dest->mant.m32[0] >= 0)
+		exp -= fp_overnormalize(dest);
+	if ((long)src->mant.m32[0] >= 0)
+		exp -= fp_overnormalize(src);
+
+	/* now, do the 64-bit divide */
+	fp_dividemant(&temp, dest, src);
+
+	/* normalize it back to 64 bits and stuff it back into the
+	   destination struct */
+	if (!temp.m32[0]) {
+		exp--;
+		fp_putmant128(dest, &temp, 32);
+	} else
+		fp_putmant128(dest, &temp, 31);
+
+	if (exp >= 0x7fff) {
+		fp_set_ovrflw(dest);
+		return dest;
+	}
+	dest->exp = exp;
+	if (exp < 0) {
+		fp_set_sr(FPSR_EXC_UNFL);
+		fp_denormalize(dest, -exp);
+	}
+
+	return dest;
+}
+
+struct fp_ext *
+fp_fsglmul(struct fp_ext *dest, struct fp_ext *src)
+{
+	int exp;
+
+	dprint(PINSTR, "fsglmul\n");
+
+	fp_dyadic_check(dest, src);
+
+	/* calculate the correct sign now, as it's necessary for infinities */
+	dest->sign = src->sign ^ dest->sign;
+
+	/* Handle infinities */
+	if (IS_INF(dest)) {
+		if (IS_ZERO(src))
+			fp_set_nan(dest);
+		return dest;
+	}
+	if (IS_INF(src)) {
+		if (IS_ZERO(dest))
+			fp_set_nan(dest);
+		else
+			fp_copy_ext(dest, src);
+		return dest;
+	}
+
+	/* Of course, as we all know, zero * anything = zero.  You may
+	   not have known that it might be a positive or negative
+	   zero... */
+	if (IS_ZERO(dest) || IS_ZERO(src)) {
+		dest->exp = 0;
+		dest->mant.m64 = 0;
+		dest->lowmant = 0;
+
+		return dest;
+	}
+
+	exp = dest->exp + src->exp - 0x3ffe;
+
+	/* do a 32-bit multiply */
+	fp_mul64(dest->mant.m32[0], dest->mant.m32[1],
+		 dest->mant.m32[0] & 0xffffff00,
+		 src->mant.m32[0] & 0xffffff00);
+
+	if (exp >= 0x7fff) {
+		fp_set_ovrflw(dest);
+		return dest;
+	}
+	dest->exp = exp;
+	if (exp < 0) {
+		fp_set_sr(FPSR_EXC_UNFL);
+		fp_denormalize(dest, -exp);
+	}
+
+	return dest;
+}
+
+struct fp_ext *
+fp_fsgldiv(struct fp_ext *dest, struct fp_ext *src)
+{
+	int exp;
+	unsigned long quot, rem;
+
+	dprint(PINSTR, "fsgldiv\n");
+
+	fp_dyadic_check(dest, src);
+
+	/* calculate the correct sign now, as it's necessary for infinities */
+	dest->sign = src->sign ^ dest->sign;
+
+	/* Handle infinities */
+	if (IS_INF(dest)) {
+		/* infinity / infinity = NaN (quiet, as always) */
+		if (IS_INF(src))
+			fp_set_nan(dest);
+		/* infinity / anything else = infinity (with approprate sign) */
+		return dest;
+	}
+	if (IS_INF(src)) {
+		/* anything / infinity = zero (with appropriate sign) */
+		dest->exp = 0;
+		dest->mant.m64 = 0;
+		dest->lowmant = 0;
+
+		return dest;
+	}
+
+	/* zeroes */
+	if (IS_ZERO(dest)) {
+		/* zero / zero = NaN */
+		if (IS_ZERO(src))
+			fp_set_nan(dest);
+		/* zero / anything else = zero */
+		return dest;
+	}
+	if (IS_ZERO(src)) {
+		/* anything / zero = infinity (with appropriate sign) */
+		fp_set_sr(FPSR_EXC_DZ);
+		dest->exp = 0x7fff;
+		dest->mant.m64 = 0;
+
+		return dest;
+	}
+
+	exp = dest->exp - src->exp + 0x3fff;
+
+	dest->mant.m32[0] &= 0xffffff00;
+	src->mant.m32[0] &= 0xffffff00;
+
+	/* do the 32-bit divide */
+	if (dest->mant.m32[0] >= src->mant.m32[0]) {
+		fp_sub64(dest->mant, src->mant);
+		fp_div64(quot, rem, dest->mant.m32[0], 0, src->mant.m32[0]);
+		dest->mant.m32[0] = 0x80000000 | (quot >> 1);
+		dest->mant.m32[1] = (quot & 1) | rem;	/* only for rounding */
+	} else {
+		fp_div64(quot, rem, dest->mant.m32[0], 0, src->mant.m32[0]);
+		dest->mant.m32[0] = quot;
+		dest->mant.m32[1] = rem;		/* only for rounding */
+		exp--;
+	}
+
+	if (exp >= 0x7fff) {
+		fp_set_ovrflw(dest);
+		return dest;
+	}
+	dest->exp = exp;
+	if (exp < 0) {
+		fp_set_sr(FPSR_EXC_UNFL);
+		fp_denormalize(dest, -exp);
+	}
+
+	return dest;
+}
+
+/* fp_roundint: Internal rounding function for use by several of these
+   emulated instructions.
+
+   This one rounds off the fractional part using the rounding mode
+   specified. */
+
+static void fp_roundint(struct fp_ext *dest, int mode)
+{
+	union fp_mant64 oldmant;
+	unsigned long mask;
+
+	if (!fp_normalize_ext(dest))
+		return;
+
+	/* infinities and zeroes */
+	if (IS_INF(dest) || IS_ZERO(dest)) 
+		return;
+
+	/* first truncate the lower bits */
+	oldmant = dest->mant;
+	switch (dest->exp) {
+	case 0 ... 0x3ffe:
+		dest->mant.m64 = 0;
+		break;
+	case 0x3fff ... 0x401e:
+		dest->mant.m32[0] &= 0xffffffffU << (0x401e - dest->exp);
+		dest->mant.m32[1] = 0;
+		if (oldmant.m64 == dest->mant.m64)
+			return;
+		break;
+	case 0x401f ... 0x403e:
+		dest->mant.m32[1] &= 0xffffffffU << (0x403e - dest->exp);
+		if (oldmant.m32[1] == dest->mant.m32[1])
+			return;
+		break;
+	default:
+		return;
+	}
+	fp_set_sr(FPSR_EXC_INEX2);
+
+	/* We might want to normalize upwards here... however, since
+	   we know that this is only called on the output of fp_fdiv,
+	   or with the input to fp_fint or fp_fintrz, and the inputs
+	   to all these functions are either normal or denormalized
+	   (no subnormals allowed!), there's really no need.
+
+	   In the case of fp_fdiv, observe that 0x80000000 / 0xffff =
+	   0xffff8000, and the same holds for 128-bit / 64-bit. (i.e. the
+	   smallest possible normal dividend and the largest possible normal
+	   divisor will still produce a normal quotient, therefore, (normal
+	   << 64) / normal is normal in all cases) */
+
+	switch (mode) {
+	case FPCR_ROUND_RN:
+		switch (dest->exp) {
+		case 0 ... 0x3ffd:
+			return;
+		case 0x3ffe:
+			/* As noted above, the input is always normal, so the
+			   guard bit (bit 63) is always set.  therefore, the
+			   only case in which we will NOT round to 1.0 is when
+			   the input is exactly 0.5. */
+			if (oldmant.m64 == (1ULL << 63))
+				return;
+			break;
+		case 0x3fff ... 0x401d:
+			mask = 1 << (0x401d - dest->exp);
+			if (!(oldmant.m32[0] & mask))
+				return;
+			if (oldmant.m32[0] & (mask << 1))
+				break;
+			if (!(oldmant.m32[0] << (dest->exp - 0x3ffd)) &&
+					!oldmant.m32[1])
+				return;
+			break;
+		case 0x401e:
+			if (!(oldmant.m32[1] >= 0))
+				return;
+			if (oldmant.m32[0] & 1)
+				break;
+			if (!(oldmant.m32[1] << 1))
+				return;
+			break;
+		case 0x401f ... 0x403d:
+			mask = 1 << (0x403d - dest->exp);
+			if (!(oldmant.m32[1] & mask))
+				return;
+			if (oldmant.m32[1] & (mask << 1))
+				break;
+			if (!(oldmant.m32[1] << (dest->exp - 0x401d)))
+				return;
+			break;
+		default:
+			return;
+		}
+		break;
+	case FPCR_ROUND_RZ:
+		return;
+	default:
+		if (dest->sign ^ (mode - FPCR_ROUND_RM))
+			break;
+		return;
+	}
+
+	switch (dest->exp) {
+	case 0 ... 0x3ffe:
+		dest->exp = 0x3fff;
+		dest->mant.m64 = 1ULL << 63;
+		break;
+	case 0x3fff ... 0x401e:
+		mask = 1 << (0x401e - dest->exp);
+		if (dest->mant.m32[0] += mask)
+			break;
+		dest->mant.m32[0] = 0x80000000;
+		dest->exp++;
+		break;
+	case 0x401f ... 0x403e:
+		mask = 1 << (0x403e - dest->exp);
+		if (dest->mant.m32[1] += mask)
+			break;
+		if (dest->mant.m32[0] += 1)
+                        break;
+		dest->mant.m32[0] = 0x80000000;
+                dest->exp++;
+		break;
+	}
+}
+
+/* modrem_kernel: Implementation of the FREM and FMOD instructions
+   (which are exactly the same, except for the rounding used on the
+   intermediate value) */
+
+static struct fp_ext *
+modrem_kernel(struct fp_ext *dest, struct fp_ext *src, int mode)
+{
+	struct fp_ext tmp;
+
+	fp_dyadic_check(dest, src);
+
+	/* Infinities and zeros */
+	if (IS_INF(dest) || IS_ZERO(src)) {
+		fp_set_nan(dest);
+		return dest;
+	}
+	if (IS_ZERO(dest) || IS_INF(src))
+		return dest;
+
+	/* FIXME: there is almost certainly a smarter way to do this */
+	fp_copy_ext(&tmp, dest);
+	fp_fdiv(&tmp, src);		/* NOTE: src might be modified */
+	fp_roundint(&tmp, mode);
+	fp_fmul(&tmp, src);
+	fp_fsub(dest, &tmp);
+
+	/* set the quotient byte */
+	fp_set_quotient((dest->mant.m64 & 0x7f) | (dest->sign << 7));
+	return dest;
+}
+
+/* fp_fmod: Implements the kernel of the FMOD instruction.
+
+   Again, the argument order is backwards.  The result, as defined in
+   the Motorola manuals, is:
+
+   fmod(src,dest) = (dest - (src * floor(dest / src))) */
+
+struct fp_ext *
+fp_fmod(struct fp_ext *dest, struct fp_ext *src)
+{
+	dprint(PINSTR, "fmod\n");
+	return modrem_kernel(dest, src, FPCR_ROUND_RZ);
+}
+
+/* fp_frem: Implements the kernel of the FREM instruction.
+
+   frem(src,dest) = (dest - (src * round(dest / src)))
+ */
+
+struct fp_ext *
+fp_frem(struct fp_ext *dest, struct fp_ext *src)
+{
+	dprint(PINSTR, "frem\n");
+	return modrem_kernel(dest, src, FPCR_ROUND_RN);
+}
+
+struct fp_ext *
+fp_fint(struct fp_ext *dest, struct fp_ext *src)
+{
+	dprint(PINSTR, "fint\n");
+
+	fp_copy_ext(dest, src);
+
+	fp_roundint(dest, FPDATA->rnd);
+
+	return dest;
+}
+
+struct fp_ext *
+fp_fintrz(struct fp_ext *dest, struct fp_ext *src)
+{
+	dprint(PINSTR, "fintrz\n");
+
+	fp_copy_ext(dest, src);
+
+	fp_roundint(dest, FPCR_ROUND_RZ);
+
+	return dest;
+}
+
+struct fp_ext *
+fp_fscale(struct fp_ext *dest, struct fp_ext *src)
+{
+	int scale, oldround;
+
+	dprint(PINSTR, "fscale\n");
+
+	fp_dyadic_check(dest, src);
+
+	/* Infinities */
+	if (IS_INF(src)) {
+		fp_set_nan(dest);
+		return dest;
+	}
+	if (IS_INF(dest))
+		return dest;
+
+	/* zeroes */
+	if (IS_ZERO(src) || IS_ZERO(dest))
+		return dest;
+
+	/* Source exponent out of range */
+	if (src->exp >= 0x400c) {
+		fp_set_ovrflw(dest);
+		return dest;
+	}
+
+	/* src must be rounded with round to zero. */
+	oldround = FPDATA->rnd;
+	FPDATA->rnd = FPCR_ROUND_RZ;
+	scale = fp_conv_ext2long(src);
+	FPDATA->rnd = oldround;
+
+	/* new exponent */
+	scale += dest->exp;
+
+	if (scale >= 0x7fff) {
+		fp_set_ovrflw(dest);
+	} else if (scale <= 0) {
+		fp_set_sr(FPSR_EXC_UNFL);
+		fp_denormalize(dest, -scale);
+	} else
+		dest->exp = scale;
+
+	return dest;
+}
+
diff -u --recursive --new-file v2.3.13/linux/arch/m68k/math-emu/fp_arith.h linux/arch/m68k/math-emu/fp_arith.h
--- v2.3.13/linux/arch/m68k/math-emu/fp_arith.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/math-emu/fp_arith.h	Sun Aug 15 11:47:29 1999
@@ -0,0 +1,52 @@
+/*
+
+   fp_arith.h: floating-point math routines for the Linux-m68k
+   floating point emulator.
+
+   Copyright (c) 1998 David Huggins-Daines.
+
+   Somewhat based on the AlphaLinux floating point emulator, by David
+   Mosberger-Tang.
+
+   You may copy, modify, and redistribute this file under the terms of
+   the GNU General Public License, version 2, or any later version, at
+   your convenience.
+
+ */
+
+#ifndef FP_ARITH_H
+#define FP_ARITH_H
+
+/* easy ones */
+struct fp_ext *
+fp_fabs(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *
+fp_fneg(struct fp_ext *dest, struct fp_ext *src);
+
+/* straightforward arithmetic */
+struct fp_ext *
+fp_fadd(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *
+fp_fsub(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *
+fp_fcmp(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *
+fp_ftst(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *
+fp_fmul(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *
+fp_fdiv(struct fp_ext *dest, struct fp_ext *src);
+
+/* ones that do rounding and integer conversions */
+struct fp_ext *
+fp_fmod(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *
+fp_frem(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *
+fp_fint(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *
+fp_fintrz(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *
+fp_fscale(struct fp_ext *dest, struct fp_ext *src);
+
+#endif	/* FP_ARITH__H */
diff -u --recursive --new-file v2.3.13/linux/arch/m68k/math-emu/fp_cond.S linux/arch/m68k/math-emu/fp_cond.S
--- v2.3.13/linux/arch/m68k/math-emu/fp_cond.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/math-emu/fp_cond.S	Sun Aug 15 11:47:29 1999
@@ -0,0 +1,334 @@
+/*
+ * fp_cond.S
+ *
+ * Copyright Roman Zippel, 1997.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, and the entire permission notice in its entirety,
+ *    including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions.  (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "fp_emu.h"
+#include "fp_decode.h"
+
+	.globl	fp_fscc, fp_fbccw, fp_fbccl
+
+#ifdef FPU_EMU_DEBUG
+fp_fnop:
+	printf	PDECODE,"fnop\n"
+	jra	fp_end
+#else
+#define fp_fnop fp_end
+#endif
+
+fp_fbccw:
+	tst.w	%d2
+	jeq	fp_fnop
+	printf	PDECODE,"fbccw "
+	fp_get_pc %a0
+	lea	(-2,%a0,%d2.w),%a0
+	jra	1f
+
+fp_fbccl:
+	printf	PDECODE,"fbccl "
+	fp_get_pc %a0
+	move.l	%d2,%d0
+	swap	%d0
+	fp_get_instr_word %d0,fp_err_ua1
+	lea	(-2,%a0,%d0.l),%a0
+1:	printf	PDECODE,"%x",1,%a0
+	move.l	%d2,%d0
+	swap	%d0
+	jsr	fp_compute_cond
+	tst.l	%d0
+	jeq	1f
+	fp_put_pc %a0,1
+1:	printf	PDECODE,"\n"
+	jra	fp_end
+
+fp_fdbcc:
+	printf	PDECODE,"fdbcc "
+	fp_get_pc %a1				| calculate new pc
+	fp_get_instr_word %d0,fp_err_ua1
+	add.w	%d0,%a1
+	fp_decode_addr_reg
+	printf	PDECODE,"d%d,%x\n",2,%d0,%a1
+	swap	%d1				| test condition in %d1
+	tst.w	%d1
+	jne	2f
+	move.l	%d0,%d1
+	jsr	fp_get_data_reg
+	subq.w	#1,%d0
+	jcs	1f
+	fp_put_pc %a1,1
+1:	jsr	fp_put_data_reg
+2:	jra	fp_end
+
+| set flags for decode macros for fs<cc>
+do_fscc=1
+do_no_pc_mode=1
+
+fp_fscc:
+	printf	PDECODE,"fscc "
+	move.l	%d2,%d0
+	jsr	fp_compute_cond
+	move.w	%d0,%d1
+	swap	%d1
+
+	| decode addressing mode
+	fp_decode_addr_mode
+
+	.long 	fp_data, fp_fdbcc
+	.long 	fp_indirect, fp_postinc
+	.long 	fp_predecr, fp_disp16
+	.long 	fp_extmode0, fp_extmode1
+
+	| addressing mode: data register direct
+fp_data:
+	fp_mode_data_direct
+	move.w	%d0,%d1			| save register nr
+	jsr	fp_get_data_reg
+	swap	%d1
+	move.b	%d1,%d0
+	swap	%d1
+	jsr	fp_put_data_reg
+	printf	PDECODE,"\n"
+	jra	fp_end
+
+fp_indirect:
+	fp_mode_addr_indirect
+	jra	fp_do_scc
+
+fp_postinc:
+	fp_mode_addr_indirect_postinc
+	jra	fp_do_scc
+
+fp_predecr:
+	fp_mode_addr_indirect_predec
+	jra	fp_do_scc
+
+fp_disp16:
+	fp_mode_addr_indirect_disp16
+	jra	fp_do_scc
+
+fp_extmode0:
+	fp_mode_addr_indirect_extmode0
+	jra	fp_do_scc
+
+fp_extmode1:
+	bfextu	%d2{#13,#3},%d0
+	jmp	([0f:w,%pc,%d0*4])
+
+	.align	4
+0:
+	.long	fp_absolute_short, fp_absolute_long
+	.long	fp_ill, fp_ill		| NOTE: jump here to ftrap.x
+	.long	fp_ill, fp_ill
+	.long	fp_ill, fp_ill
+
+fp_absolute_short:
+	fp_mode_abs_short
+	jra	fp_do_scc
+
+fp_absolute_long:
+	fp_mode_abs_long
+|	jra	fp_do_scc
+
+fp_do_scc:
+	swap	%d1
+	putuser.b %d1,(%a0),fp_err_ua1,%a0
+	printf	PDECODE,"\n"
+	jra	fp_end
+
+
+#define tst_NAN	btst #24,%d1
+#define tst_Z	btst #26,%d1
+#define tst_N	btst #27,%d1
+
+fp_compute_cond:
+	move.l	(FPD_FPSR,FPDATA),%d1
+	btst	#4,%d0
+	jeq	1f
+	tst_NAN
+	jeq	1f
+	bset	#15,%d1
+	bset	#7,%d1
+	move.l	%d1,(FPD_FPSR,FPDATA)
+1:	and.w	#0xf,%d0
+	jmp	([0f:w,%pc,%d0.w*4])
+
+	.align	4
+0:
+	.long	fp_f  , fp_eq , fp_ogt, fp_oge
+	.long	fp_olt, fp_ole, fp_ogl, fp_or
+	.long	fp_un , fp_ueq, fp_ugt, fp_uge
+	.long	fp_ult, fp_ule, fp_ne , fp_t
+
+fp_f:
+	moveq	#0,%d0
+	rts
+
+fp_eq:
+	moveq	#0,%d0
+	tst_Z
+	jeq	1f
+	moveq	#-1,%d0
+1:	rts
+
+fp_ogt:
+	moveq	#0,%d0
+	tst_NAN
+	jne	1f
+	tst_Z
+	jne	1f
+	tst_N
+	jne	1f
+	moveq	#-1,%d0
+1:	rts
+
+fp_oge:
+	moveq	#-1,%d0
+	tst_Z
+	jne	2f
+	tst_NAN
+	jne	1f
+	tst_N
+	jeq	2f
+1:	moveq	#0,%d0
+2:	rts
+
+fp_olt:
+	moveq	#0,%d0
+	tst_NAN
+	jne	1f
+	tst_Z
+	jne	1f
+	tst_N
+	jeq	1f
+	moveq	#-1,%d0
+1:	rts
+
+fp_ole:
+	moveq	#-1,%d0
+	tst_Z
+	jne	2f
+	tst_NAN
+	jne	1f
+	tst_N
+	jne	2f
+1:	moveq	#0,%d0
+2:	rts
+
+fp_ogl:
+	moveq	#0,%d0
+	tst_NAN
+	jne	1f
+	tst_Z
+	jne	1f
+	moveq	#-1,%d0
+1:	rts
+
+fp_or:
+	moveq	#0,%d0
+	tst_NAN
+	jne	1f
+	moveq	#-1,%d0
+1:	rts
+
+fp_un:
+	moveq	#0,%d0
+	tst_NAN
+	jeq	1f
+	moveq	#-1,%d0
+	rts
+
+fp_ueq:
+	moveq	#-1,%d0
+	tst_NAN
+	jne	1f
+	tst_Z
+	jne	1f
+	moveq	#0,%d0
+1:	rts
+
+fp_ugt:
+	moveq	#-1,%d0
+	tst_NAN
+	jne	2f
+	tst_N
+	jne	1f
+	tst_Z
+	jeq	2f
+1:	moveq	#0,%d0
+2:	rts
+
+fp_uge:
+	moveq	#-1,%d0
+	tst_NAN
+	jne	1f
+	tst_Z
+	jne	1f
+	tst_N
+	jeq	1f
+	moveq	#0,%d0
+1:	rts
+
+fp_ult:
+	moveq	#-1,%d0
+	tst_NAN
+	jne	2f
+	tst_Z
+	jne	1f
+	tst_N
+	jne	2f
+1:	moveq	#0,%d0
+2:	rts
+
+fp_ule:
+	moveq	#-1,%d0
+	tst_NAN
+	jne	1f
+	tst_Z
+	jne	1f
+	tst_N
+	jne	1f
+	moveq	#0,%d0
+1:	rts
+
+fp_ne:
+	moveq	#0,%d0
+	tst_Z
+	jne	1f
+	moveq	#-1,%d0
+1:	rts
+
+fp_t:
+	moveq	#-1,%d0
+	rts
diff -u --recursive --new-file v2.3.13/linux/arch/m68k/math-emu/fp_decode.h linux/arch/m68k/math-emu/fp_decode.h
--- v2.3.13/linux/arch/m68k/math-emu/fp_decode.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/math-emu/fp_decode.h	Sun Aug 15 11:47:29 1999
@@ -0,0 +1,417 @@
+/*
+ * fp_decode.h
+ *
+ * Copyright Roman Zippel, 1997.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, and the entire permission notice in its entirety,
+ *    including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions.  (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _FP_DECODE_H
+#define _FP_DECODE_H
+
+/* These macros do the dirty work of the instr decoding, several variables
+ * can be defined in the source file to modify the work of these macros,
+ * currently the following variables are used:
+ * ...
+ * The register usage:
+ * d0 - will contain source operand for data direct mode,
+ *	otherwise scratch register
+ * d1 - upper 16bit are reserved for caller
+ *	lower 16bit may contain further arguments,
+ *	is destroyed during decoding
+ * d2 - contains first two instruction words,
+ *	first word will be used for extension word
+ * a0 - will point to source/dest operand for any indirect mode
+ *	otherwise scratch register
+ * a1 - scratch register
+ * a2 - base addr to the task structure
+ *
+ * the current implementation doesn't check for every disallowed
+ * addressing mode (e.g. pc relative modes as destination), as long
+ * as it only means a new addressing mode, which should not appear
+ * in a program and that doesn't crash the emulation, I think it's
+ * not a problem to allow these modes.
+ */
+
+do_fmovem=0
+do_fmovem_cr=0
+do_no_pc_mode=0
+do_fscc=0
+
+| first decoding of the instr type
+| this seperates the conditional instr
+.macro	fp_decode_cond_instr_type
+	bfextu	%d2{#8,#2},%d0
+	jmp	([0f:w,%pc,%d0*4])
+
+	.align	4
+0:
+|	.long	"f<op>","fscc/fdbcc"
+|	.long	"fbccw","fbccl"
+.endm
+
+| second decoding of the instr type
+| this seperates most move instr
+.macro	fp_decode_move_instr_type
+	bfextu	%d2{#16,#3},%d0
+	jmp	([0f:w,%pc,%d0*4])
+
+	.align	4
+0:
+|	.long	"f<op> fpx,fpx","invalid instr"
+|	.long	"f<op> <ea>,fpx","fmove fpx,<ea>"
+|	.long	"fmovem <ea>,fpcr","fmovem <ea>,fpx"
+|	.long	"fmovem fpcr,<ea>","fmovem fpx,<ea>"
+.endm
+
+| extract the source specifier, specifies
+| either source fp register or data format
+.macro	fp_decode_sourcespec
+	bfextu	%d2{#19,#3},%d0
+.endm
+
+| decode destination format for fmove reg,ea
+.macro	fp_decode_dest_format
+	bfextu	%d2{#19,#3},%d0
+.endm
+
+| decode source register for fmove reg,ea
+.macro	fp_decode_src_reg
+	bfextu	%d2{#22,#3},%d0
+.endm
+
+| extract the addressing mode
+| it depends on the instr which of the modes is valid
+.macro	fp_decode_addr_mode
+	bfextu	%d2{#10,#3},%d0
+	jmp	([0f:w,%pc,%d0*4])
+
+	.align	4
+0:
+|	.long	"data register direct","addr register direct"
+|	.long	"addr register indirect"
+|	.long	"addr register indirect postincrement"
+|	.long	"addr register indirect predecrement"
+|	.long	"addr register + index16"
+|	.long	"extension mode1","extension mode2"
+.endm
+
+| extract the register for the addressing mode
+.macro	fp_decode_addr_reg
+	bfextu	%d2{#13,#3},%d0
+.endm
+
+| decode the 8bit diplacement from the brief extension word
+.macro	fp_decode_disp8
+	move.b	%d2,%d0
+	ext.w	%d0
+.endm
+
+| decode the index of the brief/full extension word
+.macro	fp_decode_index
+	bfextu	%d2{#17,#3},%d0		| get the register nr
+	btst	#15,%d2			| test for data/addr register
+	jne	1\@f
+	printf	PDECODE,"d%d",1,%d0
+	jsr	fp_get_data_reg
+	jra	2\@f
+1\@:	printf	PDECODE,"a%d",1,%d0
+	jsr	fp_get_addr_reg
+	move.l	%a0,%d0
+2\@:
+debug	lea	"'l'.w,%a0"
+	btst	#11,%d2			| 16/32 bit size?
+	jne	3\@f
+debug	lea	"'w'.w,%a0"
+	ext.l	%d0
+3\@:	printf	PDECODE,":%c",1,%a0
+	move.w	%d2,%d1			| scale factor
+	rol.w	#7,%d1
+	and.w	#3,%d1
+debug	move.l	"%d1,-(%sp)"
+debug	ext.l	"%d1"
+	printf	PDECODE,":%d",1,%d1
+debug	move.l	"(%sp)+,%d1"
+	lsl.l	%d1,%d0
+.endm
+
+| decode the base displacement size
+.macro	fp_decode_basedisp
+	bfextu	%d2{#26,#2},%d0
+	jmp	([0f:w,%pc,%d0*4])
+
+	.align	4
+0:
+|	.long	"reserved","null displacement"
+|	.long	"word displacement","long displacement"
+.endm
+
+.macro	fp_decode_outerdisp
+	bfextu	%d2{#30,#2},%d0
+	jmp	([0f:w,%pc,%d0*4])
+
+	.align	4
+0:
+|	.long	"no memory indirect action/reserved","null outer displacement"
+|	.long	"word outer displacement","long outer displacement"
+.endm
+
+| get the extension word and test for brief or full extension type
+.macro	fp_get_test_extword label
+	fp_get_instr_word %d2,fp_err_ua1
+	btst	#8,%d2
+	jne	\label
+.endm
+
+
+| test if %pc is the base register for the indirect addr mode
+.macro	fp_test_basereg_d16	label
+	btst	#20,%d2
+	jeq	\label
+.endm
+
+| test if %pc is the base register for one of the extended modes
+.macro	fp_test_basereg_ext	label
+	btst	#19,%d2
+	jeq	\label
+.endm
+
+.macro	fp_test_suppr_index label
+	btst	#6,%d2
+	jne	\label
+.endm
+
+
+| addressing mode: data register direct
+.macro	fp_mode_data_direct
+	fp_decode_addr_reg
+	printf	PDECODE,"d%d",1,%d0
+.endm
+
+| addressing mode: address register indirect
+.macro	fp_mode_addr_indirect
+	fp_decode_addr_reg
+	printf	PDECODE,"(a%d)",1,%d0
+	jsr	fp_get_addr_reg
+.endm
+
+| adjust stack for byte moves from/to stack
+.macro	fp_test_sp_byte_move
+	.if	!do_fmovem
+	.if	do_fscc
+	move.w	#6,%d1
+	.endif
+	cmp.w	#7,%d0
+	jne	1\@f
+	.if	!do_fscc
+	cmp.w	#6,%d1
+	jne	1\@f
+	.endif
+	move.w	#4,%d1
+1\@:
+	.endif
+.endm
+
+| addressing mode: address register indirect with postincrement
+.macro	fp_mode_addr_indirect_postinc
+	fp_decode_addr_reg
+	printf	PDECODE,"(a%d)+",1,%d0
+	fp_test_sp_byte_move
+	jsr	fp_get_addr_reg
+	move.l	%a0,%a1			| save addr
+	.if	do_fmovem
+	lea	(%a0,%d1.w*4),%a0
+	.if	!do_fmovem_cr
+	lea	(%a0,%d1.w*8),%a0
+	.endif
+	.else
+	add.w	(fp_datasize,%d1.w*2),%a0
+	.endif
+	jsr	fp_put_addr_reg
+	move.l	%a1,%a0
+.endm
+
+| addressing mode: address register indirect with predecrement
+.macro	fp_mode_addr_indirect_predec
+	fp_decode_addr_reg
+	printf	PDECODE,"-(a%d)",1,%d0
+	fp_test_sp_byte_move
+	jsr	fp_get_addr_reg
+	.if	do_fmovem
+	.if	!do_fmovem_cr
+	lea	(-12,%a0),%a1		| setup to addr of 1st reg to move
+	neg.w	%d1
+	lea	(%a0,%d1.w*4),%a0
+	add.w	%d1,%d1
+	lea	(%a0,%d1.w*4),%a0
+	jsr	fp_put_addr_reg
+	move.l	%a1,%a0
+	.else
+	neg.w	%d1
+	lea	(%a0,%d1.w*4),%a0
+	jsr	fp_put_addr_reg
+	.endif
+	.else
+	sub.w	(fp_datasize,%d1.w*2),%a0
+	jsr	fp_put_addr_reg
+	.endif
+.endm
+
+| addressing mode: address register/programm counter indirect
+|		   with 16bit displacement
+.macro	fp_mode_addr_indirect_disp16
+	.if	!do_no_pc_mode
+	fp_test_basereg_d16 1f
+	printf	PDECODE,"pc"
+	fp_get_pc %a0
+	jra	2f
+	.endif
+1:	fp_decode_addr_reg
+	printf	PDECODE,"a%d",1,%d0
+	jsr	fp_get_addr_reg
+2:	fp_get_instr_word %a1,fp_err_ua1
+	printf	PDECODE,"@(%x)",1,%a1
+	add.l	%a1,%a0
+.endm
+
+| perform preindex (if I/IS == 0xx and xx != 00)
+.macro	fp_do_preindex
+	moveq	#3,%d0
+	and.w	%d2,%d0
+	jeq	1f
+	btst	#2,%d2
+	jne	1f
+	printf	PDECODE,")@("
+	getuser.l (%a1),%a1,fp_err_ua1,%a1
+debug	jra	"2f"
+1:	printf	PDECODE,","
+2:
+.endm
+
+| perform postindex (if I/IS == 1xx)
+.macro	fp_do_postindex
+	btst	#2,%d2
+	jeq	1f
+	printf	PDECODE,")@("
+	getuser.l (%a1),%a1,fp_err_ua1,%a1
+debug	jra	"2f"
+1:	printf	PDECODE,","
+2:
+.endm
+
+| all other indirect addressing modes will finally end up here
+.macro	fp_mode_addr_indirect_extmode0
+	.if	!do_no_pc_mode
+	fp_test_basereg_ext 1f
+	printf	PDECODE,"pc"
+	fp_get_pc %a0
+	jra	2f
+	.endif
+1:	fp_decode_addr_reg
+	printf	PDECODE,"a%d",1,%d0
+	jsr	fp_get_addr_reg
+2:	move.l	%a0,%a1
+	swap	%d2
+	fp_get_test_extword 3f
+	| addressing mode: address register/programm counter indirect
+	|		   with index and 8bit displacement
+	fp_decode_disp8
+debug	ext.l	"%d0"
+	printf	PDECODE,"@(%x,",1,%d0
+	add.w	%d0,%a1
+	fp_decode_index
+	add.l	%d0,%a1
+	printf	PDECODE,")"
+	jra	9f
+3:	| addressing mode: address register/programm counter memory indirect
+	|		   with base and/or outer displacement
+	btst	#7,%d2			| base register suppressed?
+	jeq	1f
+	printf	PDECODE,"!"
+	sub.l	%a1,%a1
+1:	printf	PDECODE,"@("
+	fp_decode_basedisp
+
+	.long	fp_ill,1f
+	.long	2f,3f
+
+#ifdef FPU_EMU_DEBUG
+1:	printf	PDECODE,"0"		| null base displacement
+	jra	1f
+#endif
+2:	fp_get_instr_word %a0,fp_err_ua1 | 16bit base displacement
+	printf	PDECODE,"%x:w",1,%a0
+	jra	4f
+3:	fp_get_instr_long %a0,fp_err_ua1 | 32bit base displacement
+	printf	PDECODE,"%x:l",1,%a0
+4:	add.l	%a0,%a1
+1:
+	fp_do_postindex
+	fp_test_suppr_index 1f
+	fp_decode_index
+	add.l	%d0,%a1
+1:	fp_do_preindex
+
+	fp_decode_outerdisp
+
+	.long	5f,1f
+	.long	2f,3f
+
+#ifdef FPU_EMU_DEBUG
+1:	printf	PDECODE,"0"		| null outer displacement
+	jra	1f
+#endif
+2:	fp_get_instr_word %a0,fp_err_ua1 | 16bit outer displacement
+	printf	PDECODE,"%x:w",1,%a0
+	jra	4f
+3:	fp_get_instr_long %a0,fp_err_ua1 | 32bit outer displacement
+	printf	PDECODE,"%x:l",1,%a0
+4:	add.l	%a0,%a1
+1:
+5:	printf	PDECODE,")"
+9:	move.l	%a1,%a0
+	swap	%d2
+.endm
+
+| get the absolute short address from user space
+.macro	fp_mode_abs_short
+	fp_get_instr_word %a0,fp_err_ua1
+	printf	PDECODE,"%x.w",1,%a0
+.endm
+
+| get the absolute long address from user space
+.macro	fp_mode_abs_long
+	fp_get_instr_long %a0,fp_err_ua1
+	printf	PDECODE,"%x.l",1,%a0
+.endm
+
+#endif /* _FP_DECODE_H */
diff -u --recursive --new-file v2.3.13/linux/arch/m68k/math-emu/fp_emu.h linux/arch/m68k/math-emu/fp_emu.h
--- v2.3.13/linux/arch/m68k/math-emu/fp_emu.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/math-emu/fp_emu.h	Sun Aug 15 11:47:29 1999
@@ -0,0 +1,137 @@
+/*
+ * fp_emu.h
+ *
+ * Copyright Roman Zippel, 1997.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, and the entire permission notice in its entirety,
+ *    including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions.  (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _FP_EMU_H
+#define _FP_EMU_H
+
+#ifndef __ASSEMBLY__
+
+#include <asm/math-emu.h>
+
+#define IS_INF(a) ((a)->exp == 0x7fff)
+#define IS_ZERO(a) ((a)->mant.m64 == 0)
+
+
+#define fp_set_sr(bit) ({					\
+	FPDATA->fpsr |= 1 << (bit);				\
+})
+
+#define fp_set_quotient(quotient) ({				\
+	FPDATA->fpsr &= 0xff00ffff;				\
+	FPDATA->fpsr |= ((quotient) & 0xff) << 16;		\
+})
+
+/* linkage for several useful functions */
+
+/* Normalize the extended struct, return 0 for a NaN */
+#define fp_normalize_ext(fpreg) ({				\
+	register struct fp_ext *reg asm ("a0") = fpreg;		\
+	register int res asm ("d0");				\
+								\
+	asm volatile ("jsr fp_conv_ext2ext"			\
+			: "=d" (res) : "a" (reg)		\
+			: "a1", "d1", "d2", "memory");		\
+	res;							\
+})
+
+#define fp_copy_ext(dest, src) ({				\
+	*dest = *src;						\
+})
+
+#define fp_monadic_check(dest, src) ({				\
+	fp_copy_ext(dest, src);					\
+	if (!fp_normalize_ext(dest))				\
+		return dest;					\
+})
+
+#define fp_dyadic_check(dest, src) ({				\
+	if (!fp_normalize_ext(dest))				\
+		return dest;					\
+	if (!fp_normalize_ext(src)) {				\
+		fp_copy_ext(dest, src);				\
+		return dest;					\
+	}							\
+})
+
+extern const struct fp_ext fp_QNaN;
+extern const struct fp_ext fp_Inf;
+
+#define fp_set_nan(dest) ({					\
+	fp_set_sr(FPSR_EXC_OPERR);				\
+	*dest = fp_QNaN;					\
+})
+
+/* TODO check rounding mode? */
+#define fp_set_ovrflw(dest) ({					\
+	fp_set_sr(FPSR_EXC_OVFL);				\
+	dest->exp = 0x7fff;					\
+	dest->mant.m64 = 0;					\
+})
+
+#define fp_conv_ext2long(src) ({				\
+	register struct fp_ext *__src asm ("a0") = src;		\
+	register int __res asm ("d0");				\
+								\
+	asm volatile ("jsr fp_conv_ext2long"			\
+			: "=d" (__res) : "a" (__src)		\
+			: "a1", "d1", "d2", "memory");		\
+	__res;							\
+})
+
+#else /* __ASSEMBLY__ */
+
+#include "../kernel/m68k_defs.h"
+#include <asm/math-emu.h>
+
+/*
+ * set, reset or clear a bit in the fp status register
+ */
+.macro	fp_set_sr	bit
+	bset	#(\bit&7),(FPD_FPSR+3-(\bit/8),FPDATA)
+.endm
+
+.macro	fp_clr_sr	bit
+	bclr	#(\bit&7),(FPD_FPSR+3-(\bit/8),FPDATA)
+.endm
+
+.macro	fp_tst_sr	bit
+	btst	#(\bit&7),(FPD_FPSR+3-(\bit/8),FPDATA)
+.endm
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _FP_EMU_H */
diff -u --recursive --new-file v2.3.13/linux/arch/m68k/math-emu/fp_entry.S linux/arch/m68k/math-emu/fp_entry.S
--- v2.3.13/linux/arch/m68k/math-emu/fp_entry.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/math-emu/fp_entry.S	Tue Aug 17 10:39:02 1999
@@ -0,0 +1,325 @@
+/*
+ * fp_emu.S
+ *
+ * Copyright Roman Zippel, 1997.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, and the entire permission notice in its entirety,
+ *    including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions.  (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/entry.h>
+
+#include "fp_emu.h"
+
+	.globl	SYMBOL_NAME(fpu_emu)
+	.globl	fp_debugprint
+	.globl	fp_err_ua1,fp_err_ua2
+
+	.text
+SYMBOL_NAME_LABEL(fpu_emu)
+	SAVE_ALL_INT
+	GET_CURRENT(%d0)
+
+#if defined(CPU_M68020_OR_M68030) && defined(CPU_M68040_OR_M68060)
+        tst.l	SYMBOL_NAME(m68k_is040or060)
+        jeq	1f
+#endif
+#if defined(CPU_M68040_OR_M68060)
+	move.l	(FPS_PC2,%sp),(FPS_PC,%sp)
+#endif
+1:
+	| emulate the instruction
+	jsr	fp_scan
+
+#if defined(CONFIG_M68060)
+#if !defined(CPU_M68060_ONLY)
+	btst	#3,SYMBOL_NAME(m68k_cputype)+3
+	jeq	1f
+#endif
+	btst	#7,(FPS_SR,%sp)
+	jne	fp_sendtrace060
+#endif
+1:
+	| emulation successful?
+	tst.l	%d0
+	jeq	SYMBOL_NAME(ret_from_exception)
+
+	| send some signal to program here
+
+	jra	SYMBOL_NAME(ret_from_exception)
+
+	| we jump here after an access error while trying to access
+	| user space, we correct stackpointer and send a SIGSEGV to
+	| the user process
+fp_err_ua2:
+	addq.l	#4,%sp
+fp_err_ua1:
+	addq.l	#4,%sp
+	move.l	%a0,-(%sp)
+	pea	SEGV_MAPERR
+	pea	SIGSEGV
+	jsr	SYMBOL_NAME(fpemu_signal)
+	add.w	#12,%sp
+	jra	SYMBOL_NAME(ret_from_exception)
+
+#if defined(CONFIG_M68060)
+	| send a trace signal if we are debugged
+	| it does not really belong here, but...
+fp_sendtrace060:
+	move.l	(FPS_PC,%sp),-(%sp)
+	pea	TRAP_TRACE
+	pea	SIGTRAP
+	jsr	SYMBOL_NAME(fpemu_signal)
+	add.w	#12,%sp
+	jra	SYMBOL_NAME(ret_from_exception)
+#endif
+
+	.globl	fp_get_data_reg, fp_put_data_reg
+	.globl	fp_get_addr_reg, fp_put_addr_reg
+
+	| Entry points to get/put a register. Some of them can be get/put
+	| directly, others are on the stack, as we read/write the stack
+	| directly here, these function may only be called from within
+	| instruction decoding, otherwise the stack pointer is incorrect
+	| and the stack gets corrupted.
+fp_get_data_reg:
+	jmp	([0f:w,%pc,%d0.w*4])
+
+	.align	4
+0:
+	.long	fp_get_d0, fp_get_d1
+	.long	fp_get_d2, fp_get_d3
+	.long	fp_get_d4, fp_get_d5
+	.long	fp_get_d6, fp_get_d7
+
+fp_get_d0:
+	move.l	(PT_D0+8,%sp),%d0
+	printf	PREGISTER,"{d0->%08x}",1,%d0
+	rts
+
+fp_get_d1:
+	move.l	(PT_D1+8,%sp),%d0
+	printf	PREGISTER,"{d1->%08x}",1,%d0
+	rts
+
+fp_get_d2:
+	move.l	(PT_D2+8,%sp),%d0
+	printf	PREGISTER,"{d2->%08x}",1,%d0
+	rts
+
+fp_get_d3:
+	move.l	%d3,%d0
+	printf	PREGISTER,"{d3->%08x}",1,%d0
+	rts
+
+fp_get_d4:
+	move.l	%d4,%d0
+	printf	PREGISTER,"{d4->%08x}",1,%d0
+	rts
+
+fp_get_d5:
+	move.l	%d5,%d0
+	printf	PREGISTER,"{d5->%08x}",1,%d0
+	rts
+
+fp_get_d6:
+	move.l	%d6,%d0
+	printf	PREGISTER,"{d6->%08x}",1,%d0
+	rts
+
+fp_get_d7:
+	move.l	%d7,%d0
+	printf	PREGISTER,"{d7->%08x}",1,%d0
+	rts
+
+fp_put_data_reg:
+	jmp	([0f:w,%pc,%d1.w*4])
+
+	.align	4
+0:
+	.long	fp_put_d0, fp_put_d1
+	.long	fp_put_d2, fp_put_d3
+	.long	fp_put_d4, fp_put_d5
+	.long	fp_put_d6, fp_put_d7
+
+fp_put_d0:
+	printf	PREGISTER,"{d0<-%08x}",1,%d0
+	move.l	%d0,(PT_D0+8,%sp)
+	rts
+
+fp_put_d1:
+	printf	PREGISTER,"{d1<-%08x}",1,%d0
+	move.l	%d0,(PT_D1+8,%sp)
+	rts
+
+fp_put_d2:
+	printf	PREGISTER,"{d2<-%08x}",1,%d0
+	move.l	%d0,(PT_D2+8,%sp)
+	rts
+
+fp_put_d3:
+	printf	PREGISTER,"{d3<-%08x}",1,%d0
+|	move.l	%d0,%d3
+	move.l	%d0,(PT_D3+8,%sp)
+	rts
+
+fp_put_d4:
+	printf	PREGISTER,"{d4<-%08x}",1,%d0
+|	move.l	%d0,%d4
+	move.l	%d0,(PT_D4+8,%sp)
+	rts
+
+fp_put_d5:
+	printf	PREGISTER,"{d5<-%08x}",1,%d0
+|	move.l	%d0,%d5
+	move.l	%d0,(PT_D5+8,%sp)
+	rts
+
+fp_put_d6:
+	printf	PREGISTER,"{d6<-%08x}",1,%d0
+	move.l	%d0,%d6
+	rts
+
+fp_put_d7:
+	printf	PREGISTER,"{d7<-%08x}",1,%d0
+	move.l	%d0,%d7
+	rts
+
+fp_get_addr_reg:
+	jmp	([0f:w,%pc,%d0.w*4])
+
+	.align	4
+0:
+	.long	fp_get_a0, fp_get_a1
+	.long	fp_get_a2, fp_get_a3
+	.long	fp_get_a4, fp_get_a5
+	.long	fp_get_a6, fp_get_a7
+
+fp_get_a0:
+	move.l	(PT_A0+8,%sp),%a0
+	printf	PREGISTER,"{a0->%08x}",1,%a0
+	rts
+
+fp_get_a1:
+	move.l	(PT_A1+8,%sp),%a0
+	printf	PREGISTER,"{a1->%08x}",1,%a0
+	rts
+
+fp_get_a2:
+	move.l	(PT_A2+8,%sp),%a0
+	printf	PREGISTER,"{a2->%08x}",1,%a0
+	rts
+
+fp_get_a3:
+	move.l	%a3,%a0
+	printf	PREGISTER,"{a3->%08x}",1,%a0
+	rts
+
+fp_get_a4:
+	move.l	%a4,%a0
+	printf	PREGISTER,"{a4->%08x}",1,%a0
+	rts
+
+fp_get_a5:
+	move.l	%a5,%a0
+	printf	PREGISTER,"{a5->%08x}",1,%a0
+	rts
+
+fp_get_a6:
+	move.l	%a6,%a0
+	printf	PREGISTER,"{a6->%08x}",1,%a0
+	rts
+
+fp_get_a7:
+	move.l	%usp,%a0
+	printf	PREGISTER,"{a7->%08x}",1,%a0
+	rts
+
+fp_put_addr_reg:
+	jmp	([0f:w,%pc,%d0.w*4])
+
+	.align	4
+0:
+	.long	fp_put_a0, fp_put_a1
+	.long	fp_put_a2, fp_put_a3
+	.long	fp_put_a4, fp_put_a5
+	.long	fp_put_a6, fp_put_a7
+
+fp_put_a0:
+	printf	PREGISTER,"{a0<-%08x}",1,%a0
+	move.l	%a0,(PT_A0+8,%sp)
+	rts
+
+fp_put_a1:
+	printf	PREGISTER,"{a1<-%08x}",1,%a0
+	move.l	%a0,(PT_A1+8,%sp)
+	rts
+
+fp_put_a2:
+	printf	PREGISTER,"{a2<-%08x}",1,%a0
+	move.l	%a0,(PT_A2+8,%sp)
+	rts
+
+fp_put_a3:
+	printf	PREGISTER,"{a3<-%08x}",1,%a0
+	move.l	%a0,%a3
+	rts
+
+fp_put_a4:
+	printf	PREGISTER,"{a4<-%08x}",1,%a0
+	move.l	%a0,%a4
+	rts
+
+fp_put_a5:
+	printf	PREGISTER,"{a5<-%08x}",1,%a0
+	move.l	%a0,%a5
+	rts
+
+fp_put_a6:
+	printf	PREGISTER,"{a6<-%08x}",1,%a0
+	move.l	%a0,%a6
+	rts
+
+fp_put_a7:
+	printf	PREGISTER,"{a7<-%08x}",1,%a0
+	move.l	%a0,%usp
+	rts
+
+	.data
+	.align	4
+
+fp_debugprint:
+|	.long	PMDECODE
+	.long	PMINSTR+PMDECODE+PMCONV+PMNORM
+|	.long	PMCONV+PMNORM+PMINSTR
+|	.long	0
diff -u --recursive --new-file v2.3.13/linux/arch/m68k/math-emu/fp_log.c linux/arch/m68k/math-emu/fp_log.c
--- v2.3.13/linux/arch/m68k/math-emu/fp_log.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/math-emu/fp_log.c	Sun Aug 15 11:47:29 1999
@@ -0,0 +1,142 @@
+/*
+
+  fp_trig.c: floating-point math routines for the Linux-m68k
+  floating point emulator.
+
+  Copyright (c) 1998-1999 David Huggins-Daines / Roman Zippel.
+
+  I hereby give permission, free of charge, to copy, modify, and
+  redistribute this software, in source or binary form, provided that
+  the above copyright notice and the following disclaimer are included
+  in all such copies.
+
+  THIS SOFTWARE IS PROVIDED "AS IS", WITH ABSOLUTELY NO WARRANTY, REAL
+  OR IMPLIED.
+
+*/
+
+#include "fp_emu.h"
+
+struct fp_ext *
+fp_fsqrt(struct fp_ext *dest, struct fp_ext *src)
+{
+	uprint("fsqrt\n");
+
+	fp_monadic_check(dest, src);
+
+	if (IS_ZERO(dest))
+		return dest;
+
+	if (dest->sign) {
+		fp_set_nan(dest);
+		return dest;
+	}
+	if (IS_INF(dest))
+		return dest;
+
+	return dest;
+}
+
+struct fp_ext *
+fp_fetoxm1(struct fp_ext *dest, struct fp_ext *src)
+{
+	uprint("fetoxm1\n");
+
+	fp_monadic_check(dest, src);
+
+	if (IS_ZERO(dest))
+		return dest;
+
+	return dest;
+}
+
+struct fp_ext *
+fp_fetox(struct fp_ext *dest, struct fp_ext *src)
+{
+	uprint("fetox\n");
+
+	fp_monadic_check(dest, src);
+
+	return dest;
+}
+
+struct fp_ext *
+fp_ftwotox(struct fp_ext *dest, struct fp_ext *src)
+{
+	uprint("ftwotox\n");
+
+	fp_monadic_check(dest, src);
+
+	return dest;
+}
+
+struct fp_ext *
+fp_ftentox(struct fp_ext *dest, struct fp_ext *src)
+{
+	uprint("ftentox\n");
+
+	fp_monadic_check(dest, src);
+
+	return dest;
+}
+
+struct fp_ext *
+fp_flogn(struct fp_ext *dest, struct fp_ext *src)
+{
+	uprint("flogn\n");
+
+	fp_monadic_check(dest, src);
+
+	return dest;
+}
+
+struct fp_ext *
+fp_flognp1(struct fp_ext *dest, struct fp_ext *src)
+{
+	uprint("flognp1\n");
+
+	fp_monadic_check(dest, src);
+
+	return dest;
+}
+
+struct fp_ext *
+fp_flog10(struct fp_ext *dest, struct fp_ext *src)
+{
+	uprint("flog10\n");
+
+	fp_monadic_check(dest, src);
+
+	return dest;
+}
+
+struct fp_ext *
+fp_flog2(struct fp_ext *dest, struct fp_ext *src)
+{
+	uprint("flog2\n");
+
+	fp_monadic_check(dest, src);
+
+	return dest;
+}
+
+struct fp_ext *
+fp_fgetexp(struct fp_ext *dest, struct fp_ext *src)
+{
+	uprint("fgetexp\n");
+
+	fp_monadic_check(dest, src);
+
+	return dest;
+}
+
+struct fp_ext *
+fp_fgetman(struct fp_ext *dest, struct fp_ext *src)
+{
+	uprint("fgetman\n");
+
+	fp_monadic_check(dest, src);
+
+	return dest;
+}
+
diff -u --recursive --new-file v2.3.13/linux/arch/m68k/math-emu/fp_move.S linux/arch/m68k/math-emu/fp_move.S
--- v2.3.13/linux/arch/m68k/math-emu/fp_move.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/math-emu/fp_move.S	Sun Aug 15 11:47:29 1999
@@ -0,0 +1,244 @@
+/*
+ * fp_move.S
+ *
+ * Copyright Roman Zippel, 1997.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, and the entire permission notice in its entirety,
+ *    including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions.  (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "fp_emu.h"
+#include "fp_decode.h"
+
+do_no_pc_mode=1
+
+	.globl	fp_fmove_fp2mem
+
+fp_fmove_fp2mem:
+	clr.b	(2+FPD_FPSR,FPDATA)
+	fp_decode_dest_format
+	move.w	%d0,%d1			| store data size twice in %d1
+	swap	%d1			| one can be trashed below
+	move.w	%d0,%d1
+#ifdef FPU_EMU_DEBUG
+	lea	0f,%a0
+	clr.l	%d0
+	move.b	(%a0,%d1.w),%d0
+	printf	PDECODE,"fmove.%c ",1,%d0
+	fp_decode_src_reg
+	printf	PDECODE,"fp%d,",1,%d0
+
+	.data
+0:	.byte	'l','s','x','p','w','d','b','p'
+	.previous
+#endif
+
+	| encode addressing mode for dest
+	fp_decode_addr_mode
+
+	.long	fp_data, fp_ill
+	.long	fp_indirect, fp_postinc
+	.long	fp_predecr, fp_disp16
+	.long	fp_extmode0, fp_extmode1
+
+	| addressing mode: data register direct
+fp_data:
+	fp_mode_data_direct
+	move.w	%d0,%d1
+	fp_decode_src_reg
+	fp_get_fp_reg
+	lea	(FPD_TEMPFP1,FPDATA),%a1
+	move.l	(%a0)+,(%a1)+
+	move.l	(%a0)+,(%a1)+
+	move.l	(%a0),(%a1)
+	lea	(-8,%a1),%a0
+	swap	%d1
+	move.l	%d1,%d2
+	printf	PDECODE,"\n"
+	jmp	([0f:w,%pc,%d1.w*4])
+
+	.align	4
+0:
+	.long	fp_data_long, fp_data_single
+	.long	fp_ill, fp_ill
+	.long	fp_data_word, fp_ill
+	.long	fp_data_byte, fp_ill
+
+fp_data_byte:
+	jsr	fp_normalize_ext
+	jsr	fp_conv_ext2byte
+	move.l	%d0,%d1
+	swap	%d2
+	move.w	%d2,%d0
+	jsr	fp_get_data_reg
+	move.b	%d1,%d0
+	move.w	%d2,%d1
+	jsr	fp_put_data_reg
+	jra	fp_final
+
+fp_data_word:
+	jsr	fp_normalize_ext
+	jsr	fp_conv_ext2short
+	move.l	%d0,%d1
+	swap	%d2
+	move.w	%d2,%d0
+	jsr	fp_get_data_reg
+	move.w	%d1,%d0
+	move.l	%d2,%d1
+	jsr	fp_put_data_reg
+	jra	fp_final
+
+fp_data_long:
+	jsr	fp_normalize_ext
+	jsr	fp_conv_ext2long
+	swap	%d2
+	move.w	%d2,%d1
+	jsr	fp_put_data_reg
+	jra	fp_final
+
+fp_data_single:
+	jsr	fp_normalize_ext
+	jsr	fp_conv_ext2single
+	swap	%d2
+	move.w	%d2,%d1
+	jsr	fp_put_data_reg
+	jra	fp_final
+
+	| addressing mode: address register indirect
+fp_indirect:
+	fp_mode_addr_indirect
+	jra	fp_putdest
+
+	| addressing mode: address register indirect with postincrement
+fp_postinc:
+	fp_mode_addr_indirect_postinc
+	jra	fp_putdest
+
+	| addressing mode: address register indirect with predecrement
+fp_predecr:
+	fp_mode_addr_indirect_predec
+	jra	fp_putdest
+
+	| addressing mode: address register indirect with 16bit displacement
+fp_disp16:
+	fp_mode_addr_indirect_disp16
+	jra     fp_putdest
+
+fp_extmode0:
+	fp_mode_addr_indirect_extmode0
+	jra	fp_putdest
+
+fp_extmode1:
+	fp_decode_addr_reg
+	jmp	([0f:w,%pc,%d0*4])
+
+	.align	4
+0:
+	.long	fp_abs_short, fp_abs_long
+	.long	fp_ill, fp_ill
+	.long	fp_ill, fp_ill
+	.long	fp_ill, fp_ill
+
+fp_abs_short:
+	fp_mode_abs_short
+	jra	fp_putdest
+
+fp_abs_long:
+	fp_mode_abs_long
+	jra	fp_putdest
+
+fp_putdest:
+	move.l	%a0,%a1
+	fp_decode_src_reg
+	move.l	%d1,%d2			| save size
+	fp_get_fp_reg
+	printf	PDECODE,"\n"
+	addq.l	#8,%a0
+	move.l	(%a0),-(%sp)
+	move.l	-(%a0),-(%sp)
+	move.l	-(%a0),-(%sp)
+	move.l	%sp,%a0
+	jsr	fp_normalize_ext
+
+	swap	%d2
+	jmp	([0f:w,%pc,%d2.w*4])
+
+	.align	4
+0:
+	.long	fp_format_long, fp_format_single
+	.long	fp_format_extended, fp_format_packed
+	.long	fp_format_word, fp_format_double
+	.long	fp_format_byte, fp_format_packed
+
+fp_format_long:
+	jsr	fp_conv_ext2long
+	putuser.l %d0,(%a1),fp_err_ua1,%a1
+	jra	fp_finish_move
+
+fp_format_single:
+	jsr	fp_conv_ext2single
+	putuser.l %d0,(%a1),fp_err_ua1,%a1
+	jra	fp_finish_move
+
+fp_format_extended:
+	move.l	(%a0)+,%d0
+	lsl.w	#1,%d0
+	lsl.l	#7,%d0
+	lsl.l	#8,%d0
+	putuser.l %d0,(%a1)+,fp_err_ua1,%a1
+	move.l	(%a0)+,%d0
+	putuser.l %d0,(%a1)+,fp_err_ua1,%a1
+	move.l	(%a0),%d0
+	putuser.l %d0,(%a1),fp_err_ua1,%a1
+	jra	fp_finish_move
+
+fp_format_packed:
+	/* not supported yet */
+	lea	(12,%sp),%sp
+	jra	fp_ill
+
+fp_format_word:
+	jsr	fp_conv_ext2short
+	putuser.w %d0,(%a1),fp_err_ua1,%a1
+	jra	fp_finish_move
+
+fp_format_double:
+	jsr	fp_conv_ext2double
+	jra	fp_finish_move
+
+fp_format_byte:
+	jsr	fp_conv_ext2byte
+	putuser.b %d0,(%a1),fp_err_ua1,%a1
+|	jra	fp_finish_move
+
+fp_finish_move:
+	lea	(12,%sp),%sp
+	jra	fp_final
diff -u --recursive --new-file v2.3.13/linux/arch/m68k/math-emu/fp_movem.S linux/arch/m68k/math-emu/fp_movem.S
--- v2.3.13/linux/arch/m68k/math-emu/fp_movem.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/math-emu/fp_movem.S	Sun Aug 15 11:47:29 1999
@@ -0,0 +1,368 @@
+/*
+ * fp_movem.S
+ *
+ * Copyright Roman Zippel, 1997.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, and the entire permission notice in its entirety,
+ *    including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions.  (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "fp_emu.h"
+#include "fp_decode.h"
+
+| set flags for decode macros for fmovem
+do_fmovem=1
+
+	.globl	fp_fmovem_fp, fp_fmovem_cr
+
+| %d1 contains the mask and count of the register list
+| for other register usage see fp_decode.h
+
+fp_fmovem_fp:
+	printf	PDECODE,"fmovem.x "
+	| get register list and count them
+	btst	#11,%d2
+	jne	1f
+	bfextu	%d2{#24,#8},%d0		| static register list
+	jra	2f
+1:	bfextu	%d2{#25,#3},%d0		| dynamic register list
+	jsr	fp_get_data_reg
+2:	move.l	%d0,%d1
+	swap	%d1
+	jra	2f
+1:	addq.w	#1,%d1			| count the # of registers in
+2:	lsr.b	#1,%d0			| register list and keep it in %d1
+	jcs	1b
+	jne	2b
+	printf	PDECODE,"#%08x",1,%d1
+#ifdef FPU_EMU_DEBUG
+	btst	#12,%d2
+	jne	1f
+	printf	PDECODE,"-"		| decremental move
+	jra	2f
+1:	printf	PDECODE,"+"		| incremental move
+2:	btst	#13,%d2
+	jeq	1f
+	printf	PDECODE,"->"		| fpu -> cpu
+	jra	2f
+1:	printf	PDECODE,"<-"		| fpu <- cpu
+2:
+#endif
+
+	| decode address mode
+	fp_decode_addr_mode
+
+	.long	fp_ill, fp_ill
+	.long	fpr_indirect, fpr_postinc
+	.long	fpr_predecr, fpr_disp16
+	.long	fpr_extmode0, fpr_extmode1
+
+	| addressing mode: address register indirect
+fpr_indirect:
+	fp_mode_addr_indirect
+	jra	fpr_do_movem
+
+	| addressing mode: address register indirect with postincrement
+fpr_postinc:
+	fp_mode_addr_indirect_postinc
+	jra	fpr_do_movem
+
+fpr_predecr:
+	fp_mode_addr_indirect_predec
+	jra	fpr_do_movem
+
+	| addressing mode: address register/programm counter indirect
+	|		   with 16bit displacement
+fpr_disp16:
+	fp_mode_addr_indirect_disp16
+	jra	fpr_do_movem
+
+fpr_extmode0:
+	fp_mode_addr_indirect_extmode0
+	jra	fpr_do_movem
+
+fpr_extmode1:
+	fp_decode_addr_reg
+	jmp	([0f:w,%pc,%d0*4])
+
+	.align	4
+0:
+	.long	fpr_absolute_short, fpr_absolute_long
+	.long	fpr_disp16, fpr_extmode0
+	.long	fp_ill, fp_ill
+	.long	fp_ill, fp_ill
+
+fpr_absolute_short:
+	fp_mode_abs_short
+	jra	fpr_do_movem
+
+fpr_absolute_long:
+	fp_mode_abs_long
+|	jra	fpr_do_movem
+
+fpr_do_movem:
+	swap	%d1			| get fpu register list
+	lea	(FPD_FPREG,FPDATA),%a1
+	moveq	#12,%d0
+	btst	#12,%d2
+	jne	1f
+	lea	(-12,%a1,%d0*8),%a1
+	neg.l	%d0
+1:	btst	#13,%d2
+	jne	4f
+	| move register from memory into fpu
+	jra	3f
+1:	printf	PMOVEM,"(%p>%p)",2,%a0,%a1
+	getuser.l (%a0)+,%d2,fp_err_ua1,%a0
+	lsr.l	#8,%d2
+	lsr.l	#7,%d2
+	lsr.w	#1,%d2
+	move.l	%d2,(%a1)+
+	getuser.l (%a0)+,%d2,fp_err_ua1,%a0
+	move.l	%d2,(%a1)+
+	getuser.l (%a0),%d2,fp_err_ua1,%a0
+	move.l	%d2,(%a1)
+	subq.l	#8,%a0
+	subq.l	#8,%a1
+	add.l	%d0,%a0
+2:	add.l	%d0,%a1
+3:	lsl.b	#1,%d1
+	jcs	1b
+	jne	2b
+	jra	5f
+	| move register from fpu into memory
+1:	printf	PMOVEM,"(%p>%p)",2,%a1,%a0
+	move.l	(%a1)+,%d2
+	lsl.w	#1,%d2
+	lsl.l	#7,%d2
+	lsl.l	#8,%d2
+	putuser.l %d2,(%a0)+,fp_err_ua1,%a0
+	move.l	(%a1)+,%d2
+	putuser.l %d2,(%a0)+,fp_err_ua1,%a0
+	move.l	(%a1),%d2
+	putuser.l %d2,(%a0),fp_err_ua1,%a0
+	subq.l	#8,%a1
+	subq.l	#8,%a0
+	add.l	%d0,%a0
+2:	add.l	%d0,%a1
+4:	lsl.b	#1,%d1
+	jcs	1b
+	jne	2b
+5:
+	printf	PDECODE,"\n"
+#if 0
+	lea	(FPD_FPREG,FPDATA),%a0
+	printf	PMOVEM,"fp:"
+	printx	PMOVEM,%a0@(0)
+	printx	PMOVEM,%a0@(12)
+	printf	PMOVEM,"\n   "
+	printx	PMOVEM,%a0@(24)
+	printx	PMOVEM,%a0@(36)
+	printf	PMOVEM,"\n   "
+	printx	PMOVEM,%a0@(48)
+	printx	PMOVEM,%a0@(60)
+	printf	PMOVEM,"\n   "
+	printx	PMOVEM,%a0@(72)
+	printx	PMOVEM,%a0@(84)
+	printf	PMOVEM,"\n"
+#endif
+	jra	fp_end
+
+| set flags for decode macros for fmovem control register
+do_fmovem=1
+do_fmovem_cr=1
+
+fp_fmovem_cr:
+	printf	PDECODE,"fmovem.cr "
+	| get register list and count them
+	bfextu	%d2{#19,#3},%d0
+	move.l	%d0,%d1
+	swap	%d1
+	jra	2f
+1:	addq.w	#1,%d1
+2:	lsr.l	#1,%d0
+	jcs	1b
+	jne	2b
+	printf	PDECODE,"#%08x",1,%d1
+#ifdef FPU_EMU_DEBUG
+	btst	#13,%d2
+	jeq	1f
+	printf	PDECODE,"->"		| fpu -> cpu
+	jra	2f
+1:	printf	PDECODE,"<-"		| fpu <- cpu
+2:
+#endif
+
+	| decode address mode
+	fp_decode_addr_mode
+
+	.long	fpc_data, fpc_addr
+	.long	fpc_indirect, fpc_postinc
+	.long	fpc_predecr, fpc_disp16
+	.long	fpc_extmode0, fpc_extmode1
+
+fpc_data:
+	fp_mode_data_direct
+	move.w	%d0,%d1
+	bfffo	%d2{#19,#3},%d0
+	sub.w	#19,%d0
+	lea	(FPD_FPCR,FPDATA,%d0.w*4),%a1
+	btst	#13,%d2
+	jne	1f
+	move.w	%d1,%d0
+	jsr	fp_get_data_reg
+	move.l	%d0,(%a1)
+	jra	fpc_movem_fin
+1:	move.l	(%a1),%d0
+	jsr	fp_put_data_reg
+	jra	fpc_movem_fin
+
+fpc_addr:
+	fp_decode_addr_reg
+	printf	PDECODE,"a%d",1,%d0
+	btst	#13,%d2
+	jne	1f
+	jsr	fp_get_addr_reg
+	move.l	%a0,(FPD_FPIAR,FPDATA)
+	jra	fpc_movem_fin
+1:	move.l	(FPD_FPIAR,FPDATA),%a0
+	jsr	fp_put_addr_reg
+	jra	fpc_movem_fin
+
+fpc_indirect:
+	fp_mode_addr_indirect
+	jra	fpc_do_movem
+
+fpc_postinc:
+	fp_mode_addr_indirect_postinc
+	jra	fpc_do_movem
+
+fpc_predecr:
+	fp_mode_addr_indirect_predec
+	jra	fpc_do_movem
+
+fpc_disp16:
+	fp_mode_addr_indirect_disp16
+	jra	fpc_do_movem
+
+fpc_extmode0:
+	fp_mode_addr_indirect_extmode0
+	jra	fpc_do_movem
+
+fpc_extmode1:
+	fp_decode_addr_reg
+	jmp	([0f:w,%pc,%d0*4])
+
+	.align	4
+0:
+	.long	fpc_absolute_short, fpc_absolute_long
+	.long	fpc_disp16, fpc_extmode0
+	.long	fpc_immediate, fp_ill
+	.long	fp_ill, fp_ill
+
+fpc_absolute_short:
+	fp_mode_abs_short
+	jra	fpc_do_movem
+
+fpc_absolute_long:
+	fp_mode_abs_long
+	jra	fpc_do_movem
+
+fpc_immediate:
+	fp_get_pc %a0
+	lea	(%a0,%d1.w*4),%a1
+	fp_put_pc %a1
+	printf	PDECODE,"#imm"
+|	jra	fpc_do_movem
+#if 0
+	swap	%d1
+	lsl.l	#5,%d1
+	lea	(FPD_FPCR,FPDATA),%a0
+	jra	3f
+1:	move.l	%d0,(%a0)
+2:	addq.l	#4,%a0
+3:	lsl.b	#1,%d1
+	jcs	1b
+	jne	2b
+	jra	fpc_movem_fin
+#endif
+
+fpc_do_movem:
+	swap	%d1			| get fpu register list
+	lsl.l	#5,%d1
+	lea	(FPD_FPCR,FPDATA),%a1
+1:	btst	#13,%d2
+	jne	4f
+
+	| move register from memory into fpu
+	jra	3f
+1:	printf	PMOVEM,"(%p>%p)",2,%a0,%a1
+	getuser.l (%a0)+,%d0,fp_err_ua1,%a0
+	move.l	%d0,(%a1)
+2:	addq.l	#4,%a1
+3:	lsl.b	#1,%d1
+	jcs	1b
+	jne	2b
+	jra	fpc_movem_fin
+
+	| move register from fpu into memory
+1:	printf	PMOVEM,"(%p>%p)",2,%a1,%a0
+	move.l	(%a1),%d0
+	putuser.l %d0,(%a0)+,fp_err_ua1,%a0
+2:	addq.l	#4,%a1
+4:	lsl.b	#1,%d1
+	jcs	1b
+	jne	2b
+
+fpc_movem_fin:
+	and.l	#0x0000fff0,(FPD_FPCR,FPDATA)
+	and.l	#0x0ffffff8,(FPD_FPSR,FPDATA)
+	move.l	(FPD_FPCR,FPDATA),%d0
+	lsr.l	#4,%d0
+	moveq	#3,%d1
+	and.l	%d0,%d1
+	move.w	%d1,(FPD_RND,FPDATA)
+	lsr.l	#2,%d0
+	moveq	#3,%d1
+	and.l	%d0,%d1
+	move.w	%d1,(FPD_PREC,FPDATA)
+	printf	PDECODE,"\n"
+#if 0
+	printf	PMOVEM,"fpcr : %08x\n",1,FPDATA@(FPD_FPCR)
+	printf	PMOVEM,"fpsr : %08x\n",1,FPDATA@(FPD_FPSR)
+	printf	PMOVEM,"fpiar: %08x\n",1,FPDATA@(FPD_FPIAR)
+	clr.l	%d0
+	move.w	(FPD_PREC,FPDATA),%d0
+	printf	PMOVEM,"prec : %04x\n",1,%d0
+	move.w	(FPD_RND,FPDATA),%d0
+	printf	PMOVEM,"rnd  : %04x\n",1,%d0
+#endif
+	jra	fp_end
diff -u --recursive --new-file v2.3.13/linux/arch/m68k/math-emu/fp_scan.S linux/arch/m68k/math-emu/fp_scan.S
--- v2.3.13/linux/arch/m68k/math-emu/fp_scan.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/math-emu/fp_scan.S	Sun Aug 15 11:47:29 1999
@@ -0,0 +1,478 @@
+/*
+ * fp_scan.S
+ *
+ * Copyright Roman Zippel, 1997.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, and the entire permission notice in its entirety,
+ *    including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions.  (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "fp_emu.h"
+#include "fp_decode.h"
+
+	.globl	fp_scan, fp_datasize
+
+	.data
+
+| %d2 - first two instr words
+| %d1 - operand size
+
+/* operand formats are:
+
+	Long = 0,		i.e. fmove.l
+	Single,			i.e. fmove.s
+	Extended,		i.e. fmove.x
+	Packed-BCD,		i.e. fmove.p
+	Word,			i.e. fmove.w
+	Double,			i.e. fmove.d
+*/
+
+	.text
+
+| On entry:
+| FPDATA - base of emulated FPU registers
+
+fp_scan:
+| normal fpu instruction? (this excludes fsave/frestore)
+	fp_get_pc %a0
+	printf	PDECODE,"%08x: ",1,%a0
+	getuser.b (%a0),%d0,fp_err_ua1,%a0
+#if 1
+	cmp.b	#0xf2,%d0		| cpid = 1
+#else
+	cmp.b	#0xfc,%d0		| cpid = 6
+#endif
+	jne	fp_nonstd
+| first two instruction words are kept in %d2
+	getuser.l (%a0)+,%d2,fp_err_ua1,%a0
+	fp_put_pc %a0
+fp_decode_cond:				| seperate conditional instr
+	fp_decode_cond_instr_type
+
+	.long	fp_decode_move, fp_fscc
+	.long	fp_fbccw, fp_fbccl
+
+fp_decode_move:				| seperate move instr
+	fp_decode_move_instr_type
+
+	.long	fp_fgen_fp, fp_ill
+	.long	fp_fgen_ea, fp_fmove_fp2mem
+	.long	fp_fmovem_cr, fp_fmovem_cr
+	.long	fp_fmovem_fp, fp_fmovem_fp
+
+| now all arithmetic instr and a few move instr are left
+fp_fgen_fp:				| source is a fpu register
+	clr.b	(FPD_FPSR+2,FPDATA)	| clear the exception byte
+	fp_decode_sourcespec
+	printf	PDECODE,"f<op>.x fp%d",1,%d0
+	fp_get_fp_reg
+	lea	(FPD_TEMPFP1,FPDATA),%a1 | copy src into a temp location
+	move.l	(%a0)+,(%a1)+
+	move.l	(%a0)+,(%a1)+
+	move.l	(%a0),(%a1)
+	lea	(-8,%a1),%a0
+	jra	fp_getdest
+
+fp_fgen_ea:				| source is <ea>
+	clr.b	(FPD_FPSR+2,FPDATA)	| clear the exception byte
+	| sort out fmovecr, keep data size in %d1
+	fp_decode_sourcespec
+	cmp.w	#7,%d0
+	jeq	fp_fmovecr
+	move.w	%d0,%d1			| store data size twice in %d1
+	swap	%d1			| one can be trashed below
+	move.w	%d0,%d1
+#ifdef FPU_EMU_DEBUG
+	lea	0f,%a0
+	clr.l	%d0
+	move.b	(%a0,%d1.w),%d0
+	printf	PDECODE,"f<op>.%c ",1,%d0
+
+	.data
+0:	.byte	'l','s','x','p','w','d','b',0
+	.previous
+#endif
+
+/*
+	fp_getsource, fp_getdest
+
+	basically, we end up with a pointer to the source operand in
+	%a1, and a pointer to the destination operand in %a0.  both
+	are, of course, 96-bit extended floating point numbers.
+*/
+
+fp_getsource:
+	| decode addressing mode for source
+	fp_decode_addr_mode
+
+	.long 	fp_data, fp_ill
+	.long 	fp_indirect, fp_postinc
+	.long 	fp_predecr, fp_disp16
+	.long 	fp_extmode0, fp_extmode1
+
+	| addressing mode: data register direct
+fp_data:
+	fp_mode_data_direct
+	jsr	fp_get_data_reg
+	lea	(FPD_TEMPFP1,FPDATA),%a0
+	jmp	([0f:w,%pc,%d1.w*4])
+
+	.align	4
+0:
+	.long	fp_data_long, fp_data_single
+	.long	fp_ill, fp_ill
+	.long	fp_data_word, fp_ill
+	.long	fp_data_byte, fp_ill
+
+	| data types that fit in an integer data register
+fp_data_byte:
+	extb.l	%d0
+	jra	fp_data_long
+
+fp_data_word:
+	ext.l	%d0
+
+fp_data_long:
+	jsr	fp_conv_long2ext
+	jra	fp_getdest
+
+fp_data_single:
+	jsr	fp_conv_single2ext
+	jra	fp_getdest
+
+	| addressing mode: address register indirect
+fp_indirect:
+	fp_mode_addr_indirect
+	jra	fp_fetchsource
+
+	| addressing mode: address register indirect with postincrement
+fp_postinc:
+	fp_mode_addr_indirect_postinc
+	jra	fp_fetchsource
+
+	| addressing mode: address register indirect with predecrement
+fp_predecr:
+	fp_mode_addr_indirect_predec
+	jra	fp_fetchsource
+
+	| addressing mode: address register/programm counter indirect
+	|		   with 16bit displacement
+fp_disp16:
+	fp_mode_addr_indirect_disp16
+	jra	fp_fetchsource
+
+	| all other indirect addressing modes will finally end up here
+fp_extmode0:
+	fp_mode_addr_indirect_extmode0
+	jra	fp_fetchsource
+
+| all pc relative addressing modes and immediate/absolute modes end up here
+| the first ones are sent to fp_extmode0 or fp_disp16
+| and only the latter are handled here
+fp_extmode1:
+	fp_decode_addr_reg
+	jmp	([0f:w,%pc,%d0*4])
+
+	.align	4
+0:
+	.long	fp_abs_short, fp_abs_long
+	.long	fp_disp16, fp_extmode0
+	.long	fp_immediate, fp_ill
+	.long	fp_ill, fp_ill
+
+	| addressing mode: absolute short
+fp_abs_short:
+	fp_mode_abs_short
+	jra	fp_fetchsource
+
+	| addressing mode: absolute long
+fp_abs_long:
+	fp_mode_abs_long
+	jra	fp_fetchsource
+
+	| addressing mode: immediate data
+fp_immediate:
+	printf	PDECODE,"#"
+	fp_get_pc %a0
+	move.w	(fp_datasize,%d1.w*2),%d0
+	addq.w	#1,%d0
+	and.w	#-2,%d0
+#ifdef FPU_EMU_DEBUG
+	movem.l	%d0/%d1,-(%sp)
+	movel	%a0,%a1
+	clr.l	%d1
+	jra	2f
+1:	getuser.b (%a1)+,%d1,fp_err_ua1,%a1
+	printf	PDECODE,"%02x",1,%d1
+2:	dbra	%d0,1b
+	movem.l	(%sp)+,%d0/%d1
+#endif
+	lea	(%a0,%d0.w),%a1
+	fp_put_pc %a1
+|	jra	fp_fetchsource
+
+fp_fetchsource:
+	move.l	%a0,%a1
+	swap	%d1
+	lea	(FPD_TEMPFP1,FPDATA),%a0
+	jmp	([0f:w,%pc,%d1.w*4])
+
+	.align	4
+0:	.long	fp_long, fp_single
+	.long	fp_ext, fp_pack
+	.long	fp_word, fp_double
+	.long	fp_byte, fp_ill
+
+fp_long:
+	getuser.l (%a1),%d0,fp_err_ua1,%a1
+	jsr	fp_conv_long2ext
+	jra	fp_getdest
+
+fp_single:
+	getuser.l (%a1),%d0,fp_err_ua1,%a1
+	jsr	fp_conv_single2ext
+	jra	fp_getdest
+
+fp_ext:
+	getuser.l (%a1)+,%d0,fp_err_ua1,%a1
+	lsr.l	#8,%d0
+	lsr.l	#7,%d0
+	lsr.w	#1,%d0
+	move.l	%d0,(%a0)+
+	getuser.l (%a1)+,%d0,fp_err_ua1,%a1
+	move.l	%d0,(%a0)+
+	getuser.l (%a1),%d0,fp_err_ua1,%a1
+	move.l	%d0,(%a0)
+	subq.l	#8,%a0
+	jra	fp_getdest
+
+fp_pack:
+	/* not supported yet */
+	jra	fp_ill
+
+fp_word:
+	getuser.w (%a1),%d0,fp_err_ua1,%a1
+	ext.l	%d0
+	jsr	fp_conv_long2ext
+	jra	fp_getdest
+
+fp_double:
+	jsr	fp_conv_double2ext
+	jra	fp_getdest
+
+fp_byte:
+	getuser.b (%a1),%d0,fp_err_ua1,%a1
+	extb.l	%d0
+	jsr	fp_conv_long2ext
+|	jra	fp_getdest
+
+fp_getdest:
+	move.l	%a0,%a1
+	bfextu	%d2{#22,#3},%d0
+	printf	PDECODE,",fp%d\n",1,%d0
+	fp_get_fp_reg
+	movem.l	%a0/%a1,-(%sp)
+	pea	fp_finalrounding
+	bfextu	%d2{#25,#7},%d0
+	jmp	([0f:w,%pc,%d0*4])
+
+	.align	4
+0:
+	.long	fp_fmove_mem2fp, fp_fint, fp_fsinh, fp_fintrz
+	.long	fp_fsqrt, fp_ill, fp_flognp1, fp_ill
+	.long	fp_fetoxm1, fp_ftanh, fp_fatan, fp_ill
+	.long	fp_fasin, fp_fatanh, fp_fsin, fp_ftan
+	.long	fp_fetox, fp_ftwotox, fp_ftentox, fp_ill
+	.long	fp_flogn, fp_flog10, fp_flog2, fp_ill
+	.long	fp_fabs, fp_fcosh, fp_fneg, fp_ill
+	.long	fp_facos, fp_fcos, fp_fgetexp, fp_fgetman
+	.long	fp_fdiv, fp_fmod, fp_fadd, fp_fmul
+	.long	fpa_fsgldiv, fp_frem, fp_fscale, fpa_fsglmul
+	.long	fp_fsub, fp_ill, fp_ill, fp_ill
+	.long	fp_ill, fp_ill, fp_ill, fp_ill
+	.long	fp_fsincos0, fp_fsincos1, fp_fsincos2, fp_fsincos3
+	.long	fp_fsincos4, fp_fsincos5, fp_fsincos6, fp_fsincos7
+	.long	fp_fcmp, fp_ill, fp_ftst, fp_ill
+	.long	fp_ill, fp_ill, fp_ill, fp_ill
+	.long	fp_fsmove, fp_fssqrt, fp_ill, fp_ill
+	.long	fp_fdmove, fp_fdsqrt, fp_ill, fp_ill
+	.long	fp_ill, fp_ill, fp_ill, fp_ill
+	.long	fp_ill, fp_ill, fp_ill, fp_ill
+	.long	fp_ill, fp_ill, fp_ill, fp_ill
+	.long	fp_ill, fp_ill, fp_ill, fp_ill
+	.long	fp_fsabs, fp_ill, fp_fsneg, fp_ill
+	.long	fp_fdabs, fp_ill, fp_fdneg, fp_ill
+	.long	fp_fsdiv, fp_ill, fp_fsadd, fp_fsmul
+	.long	fp_fddiv, fp_ill, fp_fdadd, fp_fdmul
+	.long	fp_fssub, fp_ill, fp_ill, fp_ill
+	.long	fp_fdsub, fp_ill, fp_ill, fp_ill
+	.long	fp_ill, fp_ill, fp_ill, fp_ill
+	.long	fp_ill, fp_ill, fp_ill, fp_ill
+	.long	fp_ill, fp_ill, fp_ill, fp_ill
+	.long	fp_ill, fp_ill, fp_ill, fp_ill
+
+	| Instructions follow
+
+	| Move an (emulated) ROM constant
+fp_fmovecr:
+	bfextu	%d2{#27,#5},%d0
+	printf	PINSTR,"fp_fmovecr #%d",1,%d0
+	move.l	%d0,%d1
+	add.l	%d0,%d0
+	add.l	%d1,%d0
+	lea	(fp_constants,%d0*4),%a0
+	move.l	#0x801cc0ff,%d0
+	addq.l	#1,%d1
+	lsl.l	%d1,%d0
+	jcc	1f
+	fp_set_sr FPSR_EXC_INEX2			| INEX2 exception
+1:	moveq	#-128,%d0				| continue with fmove
+	and.l	%d0,%d2
+	jra	fp_getdest
+
+	.data
+	.align	4
+fp_constants:
+	.long	0x00004000,0xc90fdaa2,0x2168c235	| pi
+	.extend	0,0,0,0,0,0,0,0,0,0
+	.long	0x00003ffd,0x9a209a84,0xfbcff798	| log10(2)
+	.long	0x00004000,0xadf85458,0xa2bb4a9a	| e
+	.long	0x00003fff,0xb8aa3b29,0x5c17f0bc	| log2(e)
+	.long	0x00003ffd,0xde5bd8a9,0x37287195	| log10(e)
+	.long	0x00000000,0x00000000,0x00000000	| 0.0
+	.long	0x00003ffe,0xb17217f7,0xd1cf79ac	| 1n(2)
+	.long	0x00004000,0x935d8ddd,0xaaa8ac17	| 1n(10)
+	| read this as "1.0 * 2^0" - note the high bit in the mantissa
+	.long	0x00003fff,0x80000000,0x00000000	| 10^0
+	.long	0x00004002,0xa0000000,0x00000000	| 10^1
+	.long	0x00004005,0xc8000000,0x00000000	| 10^2
+	.long	0x0000400c,0x9c400000,0x00000000	| 10^4
+	.long	0x00004019,0xbebc2000,0x00000000	| 10^8
+	.long	0x00004034,0x8e1bc9bf,0x04000000	| 10^16
+	.long	0x00004069,0x9dc5ada8,0x2b70b59e	| 10^32
+	.long	0x000040d3,0xc2781f49,0xffcfa6d5	| 10^64
+	.long	0x000041a8,0x93ba47c9,0x80e98ce0	| 10^128
+	.long	0x00004351,0xaa7eebfb,0x9df9de8e	| 10^256
+	.long	0x000046a3,0xe319a0ae,0xa60e91c7	| 10^512
+	.long	0x00004d48,0xc9767586,0x81750c17	| 10^1024
+	.long	0x00005a92,0x9e8b3b5d,0xc53d5de5	| 10^2048
+	.long	0x00007525,0xc4605202,0x8a20979b	| 10^4096
+	.previous
+
+fp_fmove_mem2fp:
+	printf	PINSTR,"fmove %p,%p\n",2,%a0,%a1
+	move.l	(%a1)+,(%a0)+
+	move.l	(%a1)+,(%a0)+
+	move.l	(%a1),(%a0)
+	subq.l	#8,%a0
+	rts
+
+fpa_fsglmul:
+	move.l	#fp_finalrounding_single_fast,(%sp)
+	jra	fp_fsglmul
+
+fpa_fsgldiv:
+	move.l	#fp_finalrounding_single_fast,(%sp)
+	jra	fp_fsgldiv
+
+.macro	fp_dosingleprec instr
+	printf	PINSTR,"single "
+	move.l	#fp_finalrounding_single,(%sp)
+	jra	\instr
+.endm
+
+.macro	fp_dodoubleprec instr
+	printf	PINSTR,"double "
+	move.l	#fp_finalrounding_double,(%sp)
+	jra	\instr
+.endm
+
+fp_fsmove:
+	fp_dosingleprec fp_fmove_mem2fp
+
+fp_fssqrt:
+	fp_dosingleprec fp_fsqrt
+
+fp_fdmove:
+	fp_dodoubleprec fp_fmove_mem2fp
+
+fp_fdsqrt:
+	fp_dodoubleprec fp_fsqrt
+
+fp_fsabs:
+	fp_dosingleprec fp_fabs
+
+fp_fsneg:
+	fp_dosingleprec fp_fneg
+
+fp_fdabs:
+	fp_dodoubleprec fp_fabs
+
+fp_fdneg:
+	fp_dodoubleprec fp_fneg
+
+fp_fsdiv:
+	fp_dosingleprec fp_fdiv
+
+fp_fsadd:
+	fp_dosingleprec fp_fadd
+
+fp_fsmul:
+	fp_dosingleprec fp_fmul
+
+fp_fddiv:
+	fp_dodoubleprec fp_fdiv
+
+fp_fdadd:
+	fp_dodoubleprec fp_fadd
+
+fp_fdmul:
+	fp_dodoubleprec fp_fmul
+
+fp_fssub:
+	fp_dosingleprec fp_fsub
+
+fp_fdsub:
+	fp_dodoubleprec fp_fsub
+
+fp_nonstd:
+	fp_get_pc %a0
+	getuser.l (%a0),%d0,fp_err_ua1,%a0
+	printf	,"nonstd ((%08x)=%08x)\n",2,%a0,%d0
+	moveq	#-1,%d0
+	rts
+
+	.data
+	.align	4
+
+	| data sizes corresponding to the operand formats
+fp_datasize:
+	.word	4, 4, 12, 12, 2, 8, 1, 0
diff -u --recursive --new-file v2.3.13/linux/arch/m68k/math-emu/fp_trig.c linux/arch/m68k/math-emu/fp_trig.c
--- v2.3.13/linux/arch/m68k/math-emu/fp_trig.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/math-emu/fp_trig.c	Sun Aug 15 11:47:29 1999
@@ -0,0 +1,183 @@
+/*
+
+  fp_trig.c: floating-point math routines for the Linux-m68k
+  floating point emulator.
+
+  Copyright (c) 1998-1999 David Huggins-Daines / Roman Zippel.
+
+  I hereby give permission, free of charge, to copy, modify, and
+  redistribute this software, in source or binary form, provided that
+  the above copyright notice and the following disclaimer are included
+  in all such copies.
+
+  THIS SOFTWARE IS PROVIDED "AS IS", WITH ABSOLUTELY NO WARRANTY, REAL
+  OR IMPLIED.
+
+*/
+
+#include "fp_emu.h"
+#include "fp_trig.h"
+
+struct fp_ext *
+fp_fsin(struct fp_ext *dest, struct fp_ext *src)
+{
+	uprint("fsin\n");
+
+	fp_monadic_check(dest, src);
+
+	return dest;
+}
+
+struct fp_ext *
+fp_fcos(struct fp_ext *dest, struct fp_ext *src)
+{
+	uprint("fcos\n");
+
+	fp_monadic_check(dest, src);
+
+	return dest;
+}
+
+struct fp_ext *
+fp_ftan(struct fp_ext *dest, struct fp_ext *src)
+{
+	uprint("ftan\n");
+
+	fp_monadic_check(dest, src);
+
+	return dest;
+}
+
+struct fp_ext *
+fp_fasin(struct fp_ext *dest, struct fp_ext *src)
+{
+	uprint("fasin\n");
+
+	fp_monadic_check(dest, src);
+
+	return dest;
+}
+
+struct fp_ext *
+fp_facos(struct fp_ext *dest, struct fp_ext *src)
+{
+	uprint("facos\n");
+
+	fp_monadic_check(dest, src);
+
+	return dest;
+}
+
+struct fp_ext *
+fp_fatan(struct fp_ext *dest, struct fp_ext *src)
+{
+	uprint("fatan\n");
+
+	fp_monadic_check(dest, src);
+
+	return dest;
+}
+
+struct fp_ext *
+fp_fsinh(struct fp_ext *dest, struct fp_ext *src)
+{
+	uprint("fsinh\n");
+
+	fp_monadic_check(dest, src);
+
+	return dest;
+}
+
+struct fp_ext *
+fp_fcosh(struct fp_ext *dest, struct fp_ext *src)
+{
+	uprint("fcosh\n");
+
+	fp_monadic_check(dest, src);
+
+	return dest;
+}
+
+struct fp_ext *
+fp_ftanh(struct fp_ext *dest, struct fp_ext *src)
+{
+	uprint("ftanh\n");
+
+	fp_monadic_check(dest, src);
+
+	return dest;
+}
+
+struct fp_ext *
+fp_fatanh(struct fp_ext *dest, struct fp_ext *src)
+{
+	uprint("fatanh\n");
+
+	fp_monadic_check(dest, src);
+
+	return dest;
+}
+
+struct fp_ext *
+fp_fsincos0(struct fp_ext *dest, struct fp_ext *src)
+{
+	uprint("fsincos0\n");
+
+	return dest;
+}
+
+struct fp_ext *
+fp_fsincos1(struct fp_ext *dest, struct fp_ext *src)
+{
+	uprint("fsincos1\n");
+
+	return dest;
+}
+
+struct fp_ext *
+fp_fsincos2(struct fp_ext *dest, struct fp_ext *src)
+{
+	uprint("fsincos2\n");
+
+	return dest;
+}
+
+struct fp_ext *
+fp_fsincos3(struct fp_ext *dest, struct fp_ext *src)
+{
+	uprint("fsincos3\n");
+
+	return dest;
+}
+
+struct fp_ext *
+fp_fsincos4(struct fp_ext *dest, struct fp_ext *src)
+{
+	uprint("fsincos4\n");
+
+	return dest;
+}
+
+struct fp_ext *
+fp_fsincos5(struct fp_ext *dest, struct fp_ext *src)
+{
+	uprint("fsincos5\n");
+
+	return dest;
+}
+
+struct fp_ext *
+fp_fsincos6(struct fp_ext *dest, struct fp_ext *src)
+{
+	uprint("fsincos6\n");
+
+	return dest;
+}
+
+struct fp_ext *
+fp_fsincos7(struct fp_ext *dest, struct fp_ext *src)
+{
+	uprint("fsincos7\n");
+
+	return dest;
+}
diff -u --recursive --new-file v2.3.13/linux/arch/m68k/math-emu/fp_trig.h linux/arch/m68k/math-emu/fp_trig.h
--- v2.3.13/linux/arch/m68k/math-emu/fp_trig.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/math-emu/fp_trig.h	Sun Aug 15 11:47:29 1999
@@ -0,0 +1,32 @@
+/*
+
+  fp_trig.h: floating-point math routines for the Linux-m68k
+  floating point emulator.
+
+  Copyright (c) 1998 David Huggins-Daines.
+
+  I hereby give permission, free of charge, to copy, modify, and
+  redistribute this software, in source or binary form, provided that
+  the above copyright notice and the following disclaimer are included
+  in all such copies.
+
+  THIS SOFTWARE IS PROVIDED "AS IS", WITH ABSOLUTELY NO WARRANTY, REAL
+  OR IMPLIED.
+
+*/
+
+#ifndef FP_TRIG_H
+#define FP_TRIG_H
+
+#include "fp_emu.h"
+
+/* floating point trigonometric instructions:
+
+   the arguments to these are in the "internal" extended format, that
+   is, an "exploded" version of the 96-bit extended fp format used by
+   the 68881.
+
+   they return a status code, which should end up in %d0, if all goes
+   well.  */
+
+#endif /* FP_TRIG__H */
diff -u --recursive --new-file v2.3.13/linux/arch/m68k/math-emu/fp_util.S linux/arch/m68k/math-emu/fp_util.S
--- v2.3.13/linux/arch/m68k/math-emu/fp_util.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/math-emu/fp_util.S	Tue Aug 17 10:39:17 1999
@@ -0,0 +1,1456 @@
+/*
+ * fp_util.S
+ *
+ * Copyright Roman Zippel, 1997.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, and the entire permission notice in its entirety,
+ *    including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions.  (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/config.h>
+
+#include "fp_emu.h"
+
+/*
+ * Here are lots of conversion and normalization functions mainly
+ * used by fp_scan.S
+ * Note that these functions are optimized for "normal" numbers,
+ * these are handled first and exit as fast as possible, this is
+ * especially important for fp_normalize_ext/fp_conv_ext2ext, as
+ * it's called very often.
+ * The register usage is optimized for fp_scan.S and which register
+ * is currently at that time unused, be careful if you want change
+ * something here. %d0 and %d1 is always usable, sometimes %d2 (or
+ * only the lower half) most function have to return the %a0
+ * unmodified, so that the caller can immediatly reuse it.
+ */
+
+	.globl	fp_ill, fp_end
+
+	| exits from fp_scan:
+	| illegal instruction
+fp_ill:
+	printf	,"fp_illegal\n"
+	rts
+	| completed instruction
+fp_end:
+	tst.l	(TASK_MM-8,%a2)
+	jmi	1f
+	tst.l	(TASK_MM-4,%a2)
+	jmi	1f
+	tst.l	(TASK_MM,%a2)
+	jpl	2f
+1:	printf	,"oops:%p,%p,%p\n",3,%a2@(TASK_MM-8),%a2@(TASK_MM-4),%a2@(TASK_MM)
+2:	clr.l	%d0
+	rts
+
+	.globl	fp_conv_long2ext, fp_conv_single2ext
+	.globl	fp_conv_double2ext, fp_conv_ext2ext
+	.globl	fp_normalize_ext, fp_normalize_double
+	.globl	fp_normalize_single, fp_normalize_single_fast
+	.globl	fp_conv_ext2double, fp_conv_ext2single
+	.globl	fp_conv_ext2long, fp_conv_ext2short
+	.globl	fp_conv_ext2byte
+	.globl	fp_finalrounding_single, fp_finalrounding_single_fast
+	.globl	fp_finalrounding_double
+	.globl	fp_finalrounding, fp_finaltest, fp_final
+
+/*
+ * First several conversion functions from a source operand
+ * into the extended format. Note, that only fp_conv_ext2ext
+ * normalizes the number and is always called after the other
+ * conversion functions, which only move the information into
+ * fp_ext structure.
+ */
+
+	| fp_conv_long2ext:
+	|
+	| args:	%d0 = source (32-bit long)
+	|	%a0 = destination (ptr to struct fp_ext)
+
+fp_conv_long2ext:
+	printf	PCONV,"l2e: %p -> %p(",2,%d0,%a0
+	clr.l	%d1			| sign defaults to zero
+	tst.l	%d0
+	jeq	fp_l2e_zero		| is source zero?
+	jpl	1f			| positive?
+	moveq	#1,%d1
+	neg.l	%d0
+1:	swap	%d1
+	move.w	#0x3fff+31,%d1
+	move.l	%d1,(%a0)+		| set sign / exp
+	move.l	%d0,(%a0)+		| set mantissa
+	clr.l	(%a0)
+	subq.l	#8,%a0			| restore %a0
+	printx	PCONV,%a0@
+	printf	PCONV,")\n"
+	rts
+	| source is zero
+fp_l2e_zero:
+	clr.l	(%a0)+
+	clr.l	(%a0)+
+	clr.l	(%a0)
+	subq.l	#8,%a0
+	printx	PCONV,%a0@
+	printf	PCONV,")\n"
+	rts
+
+	| fp_conv_single2ext
+	| args:	%d0 = source (single-precision fp value)
+	|	%a0 = dest (struct fp_ext *)
+
+fp_conv_single2ext:
+	printf	PCONV,"s2e: %p -> %p(",2,%d0,%a0
+	move.l	%d0,%d1
+	lsl.l	#8,%d0			| shift mantissa
+	lsr.l	#8,%d1			| exponent / sign
+	lsr.l	#7,%d1
+	lsr.w	#8,%d1
+	jeq	fp_s2e_small		| zero / denormal?
+	cmp.w	#0xff,%d1		| NaN / Inf?
+	jeq	fp_s2e_large
+	bset	#31,%d0			| set explizit bit
+	add.w	#0x3fff-0x7f,%d1	| re-bias the exponent.
+9:	move.l	%d1,(%a0)+		| fp_ext.sign, fp_ext.exp
+	move.l	%d0,(%a0)+		| high lword of fp_ext.mant
+	clr.l	(%a0)			| low lword = 0
+	subq.l	#8,%a0
+	printx	PCONV,%a0@
+	printf	PCONV,")\n"
+	rts
+	| zeros and denormalized
+fp_s2e_small:
+	| exponent is zero, so explizit bit is already zero too
+	tst.l	%d0
+	jeq	9b
+	move.w	#0x4000-0x7f,%d1
+	jra	9b
+	| infinities and NAN
+fp_s2e_large:
+	bclr	#31,%d0			| clear explizit bit
+	move.w	#0x7fff,%d1
+	jra	9b
+
+fp_conv_double2ext:
+#ifdef FPU_EMU_DEBUG
+	getuser.l %a1@(0),%d0,fp_err_ua2,%a1
+	getuser.l %a1@(4),%d1,fp_err_ua2,%a1
+	printf	PCONV,"d2e: %p%p -> %p(",3,%d0,%d1,%a0
+#endif
+	getuser.l (%a1)+,%d0,fp_err_ua2,%a1
+	move.l	%d0,%d1
+	lsl.l	#8,%d0			| shift high mantissa
+	lsl.l	#3,%d0
+	lsr.l	#8,%d1			| exponent / sign
+	lsr.l	#7,%d1
+	lsr.w	#5,%d1
+	jeq	fp_d2e_small		| zero / denormal?
+	cmp.w	#0x7ff,%d1		| NaN / Inf?
+	jeq	fp_d2e_large
+	bset	#31,%d0			| set explizit bit
+	add.w	#0x3fff-0x3ff,%d1	| re-bias the exponent.
+9:	move.l	%d1,(%a0)+		| fp_ext.sign, fp_ext.exp
+	move.l	%d0,(%a0)+
+	getuser.l (%a1)+,%d0,fp_err_ua2,%a1
+	move.l	%d0,%d1
+	lsl.l	#8,%d0
+	lsl.l	#3,%d0
+	move.l	%d0,(%a0)
+	moveq	#21,%d0
+	lsr.l	%d0,%d1
+	or.l	%d1,-(%a0)
+	subq.l	#4,%a0
+	printx	PCONV,%a0@
+	printf	PCONV,")\n"
+	rts
+	| zeros and denormalized
+fp_d2e_small:
+	| exponent is zero, so explizit bit is already zero too
+	tst.l	%d0
+	jeq	9b
+	move.w	#0x4000-0x3ff,%d1
+	jra	9b
+	| infinities and NAN
+fp_d2e_large:
+	bclr	#31,%d0			| clear explizit bit
+	move.w	#0x7fff,%d1
+	jra	9b
+
+	| fp_conv_ext2ext:
+	| originally used to get longdouble from userspace, now it's
+	| called before arithmetic operations to make sure the number
+	| is normalized [maybe rename it?].
+	| args:	%a0 = dest (struct fp_ext *)
+	| returns 0 in %d0 for a NaN, otherwise 1
+
+fp_conv_ext2ext:
+	printf	PCONV,"e2e: %p(",1,%a0
+	printx	PCONV,%a0@
+	printf	PCONV,"), "
+	move.l	(%a0)+,%d0
+	cmp.w	#0x7fff,%d0		| Inf / NaN?
+	jeq	fp_e2e_large
+	move.l	(%a0),%d0
+	jpl	fp_e2e_small		| zero / denorm?
+	| The high bit is set, so normalization is irrelevant.
+fp_e2e_checkround:
+	subq.l	#4,%a0
+#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
+	move.b	(%a0),%d0
+	jne	fp_e2e_round
+#endif
+	printf	PCONV,"%p(",1,%a0
+	printx	PCONV,%a0@
+	printf	PCONV,")\n"
+	moveq	#1,%d0
+	rts
+#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
+fp_e2e_round:
+	fp_set_sr FPSR_EXC_INEX2
+	clr.b	(%a0)
+	move.w	(FPD_RND,FPDATA),%d2
+	jne	fp_e2e_roundother	| %d2 == 0, round to nearest
+	tst.b	%d0			| test guard bit
+	jpl	9f			| zero is closer
+	btst	#0,(11,%a0)		| test lsb bit
+	jne	fp_e2e_doroundup	| round to infinity
+	lsl.b	#1,%d0			| check low bits
+	jeq	9f			| round to zero
+fp_e2e_doroundup:
+	addq.l	#1,(8,%a0)
+	jcc	9f
+	addq.l	#1,(4,%a0)
+	jcc	9f
+	move.w	#0x8000,(4,%a0)
+	addq.w	#1,(2,%a0)
+9:	printf	PNORM,"%p(",1,%a0
+	printx	PNORM,%a0@
+	printf	PNORM,")\n"
+	rts
+fp_e2e_roundother:
+	subq.w	#2,%d2
+	jcs	9b			| %d2 < 2, round to zero
+	jhi	1f			| %d2 > 2, round to +infinity
+	tst.b	(1,%a0)			| to -inf
+	jne	fp_e2e_doroundup	| negative, round to infinity
+	jra	9b			| positive, round to zero
+1:	tst.b	(1,%a0)			| to +inf
+	jeq	fp_e2e_doroundup	| positive, round to infinity
+	jra	9b			| negative, round to zero
+#endif
+	| zeros and subnormals:
+	| try to normalize these anyway.
+fp_e2e_small:
+	jne	fp_e2e_small1		| high lword zero?
+	move.l	(4,%a0),%d0
+	jne	fp_e2e_small2
+#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
+	clr.l	%d0
+	move.b	(-4,%a0),%d0
+	jne	fp_e2e_small3
+#endif
+	| Genuine zero.
+	clr.w	-(%a0)
+	subq.l	#2,%a0
+	printf	PNORM,"%p(",1,%a0
+	printx	PNORM,%a0@
+	printf	PNORM,")\n"
+	moveq	#1,%d0
+	rts
+	| definitely subnormal, need to shift all 64 bits
+fp_e2e_small1:
+	bfffo	%d0{#0,#32},%d1
+	move.w	-(%a0),%d2
+	sub.w	%d1,%d2
+	jcc	1f
+	| Pathologically small, denormalize.
+	add.w	%d2,%d1
+	clr.w	%d2
+1:	move.w	%d2,(%a0)+
+	move.w	%d1,%d2
+	jeq	fp_e2e_checkround
+	| fancy 64-bit double-shift begins here
+	lsl.l	%d2,%d0
+	move.l	%d0,(%a0)+
+	move.l	(%a0),%d0
+	move.l	%d0,%d1
+	lsl.l	%d2,%d0
+	move.l	%d0,(%a0)
+	neg.w	%d2
+	and.w	#0x1f,%d2
+	lsr.l	%d2,%d1
+	or.l	%d1,-(%a0)
+#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
+fp_e2e_extra1:
+	clr.l	%d0
+	move.b	(-4,%a0),%d0
+	neg.w	%d2
+	add.w	#24,%d2
+	jcc	1f
+	clr.b	(-4,%a0)
+	lsl.l	%d2,%d0
+	or.l	%d0,(4,%a0)
+	jra	fp_e2e_checkround
+1:	addq.w	#8,%d2
+	lsl.l	%d2,%d0
+	move.b	%d0,(-4,%a0)
+	lsr.l	#8,%d0
+	or.l	%d0,(4,%a0)
+#endif
+	jra	fp_e2e_checkround
+	| pathologically small subnormal
+fp_e2e_small2:
+	bfffo	%d0{#0,#32},%d1
+	add.w	#32,%d1
+	move.w	-(%a0),%d2
+	sub.w	%d1,%d2
+	jcc	1f
+	| Beyond pathologically small, denormalize.
+	add.w	%d2,%d1
+	clr.w	%d2
+1:	move.w	%d2,(%a0)+
+	ext.l	%d1
+	jeq	fp_e2e_checkround
+	clr.l	(4,%a0)
+	sub.w	#32,%d2
+	jcs	1f
+	lsl.l	%d1,%d0			| lower lword needs only to be shifted
+	move.l	%d0,(%a0)		| into the higher lword
+#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
+	clr.l	%d0
+	move.b	(-4,%a0),%d0
+	clr.b	(-4,%a0)
+	neg.w	%d1
+	add.w	#32,%d1
+	bfins	%d0,(%a0){%d1,#8}
+#endif
+	jra	fp_e2e_checkround
+1:	neg.w	%d1			| lower lword is splitted between
+	bfins	%d0,(%a0){%d1,#32}	| higher and lower lword
+#ifndef CONFIG_M68KFPU_EMU_EXTRAPREC
+	jra	fp_e2e_checkround
+#else
+	move.w	%d1,%d2
+	jra	fp_e2e_extra1
+	| These are extremely small numbers, that will mostly end up as zero
+	| anyway, so this is only important for correct rounding.
+fp_e2e_small3:
+	bfffo	%d0{#24,#8},%d1
+	add.w	#40,%d1
+	move.w	-(%a0),%d2
+	sub.w	%d1,%d2
+	jcc	1f
+	| Pathologically small, denormalize.
+	add.w	%d2,%d1
+	clr.w	%d2
+1:	move.w	%d2,(%a0)+
+	ext.l	%d1
+	jeq	fp_e2e_checkround
+	cmp.w	#8,%d1
+	jcs	2f
+1:	clr.b	(-4,%a0)
+	sub.w	#64,%d1
+	jcs	1f
+	add.w	#24,%d1
+	lsl.l	%d1,%d0
+	move.l	%d0,(%a0)
+	jra	fp_e2e_checkround
+1:	neg.w	%d1
+	bfins	%d0,(%a0){%d1,#8}
+	jra	fp_e2e_checkround
+2:	lsl.l	%d1,%d0
+	move.b	%d0,(-4,%a0)
+	lsr.l	#8,%d0
+	move.b	%d0,(7,%a0)
+	jra	fp_e2e_checkround
+#endif
+1:	move.l	%d0,%d1			| lower lword is splitted between
+	lsl.l	%d2,%d0			| higher and lower lword
+	move.l	%d0,(%a0)
+	move.l	%d1,%d0
+	neg.w	%d2
+	add.w	#32,%d2
+	lsr.l	%d2,%d0
+	move.l	%d0,-(%a0)
+	jra	fp_e2e_checkround
+	| Infinities and NaNs
+fp_e2e_large:
+	move.l	(%a0)+,%d0
+	jne	3f
+1:	tst.l	(%a0)
+	jne	4f
+	moveq	#1,%d0
+2:	subq.l	#8,%a0
+	printf	PCONV,"%p(",1,%a0
+	printx	PCONV,%a0@
+	printf	PCONV,")\n"
+	rts
+	| we have maybe a NaN, shift off the highest bit
+3:	lsl.l	#1,%d0
+	jeq	1b
+	| we have a NaN, clear the return value
+4:	clrl	%d0
+	jra	2b
+
+
+/*
+ * Normalization functions.  Call these on the output of general
+ * FP operators, and before any conversion into the destination
+ * formats. fp_normalize_ext has always to be called first, the
+ * following conversion functions expect an already normalized
+ * number.
+ */
+
+	| fp_normalize_ext:
+	| normalize an extended in extended (unpacked) format, basically
+	| it does the same as fp_conv_ext2ext, additionally it also does
+	| the necessary postprocessing checks.
+	| args:	%a0 (struct fp_ext *)
+	| NOTE: it does _not_ modify %a0/%a1 and the upper word of %d2
+
+fp_normalize_ext:
+	printf	PNORM,"ne: %p(",1,%a0
+	printx	PNORM,%a0@
+	printf	PNORM,"), "
+	move.l	(%a0)+,%d0
+	cmp.w	#0x7fff,%d0		| Inf / NaN?
+	jeq	fp_ne_large
+	move.l	(%a0),%d0
+	jpl	fp_ne_small		| zero / denorm?
+	| The high bit is set, so normalization is irrelevant.
+fp_ne_checkround:
+	subq.l	#4,%a0
+#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
+	move.b	(%a0),%d0
+	jne	fp_ne_round
+#endif
+	printf	PNORM,"%p(",1,%a0
+	printx	PNORM,%a0@
+	printf	PNORM,")\n"
+	rts
+#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
+fp_ne_round:
+	fp_set_sr FPSR_EXC_INEX2
+	clr.b	(%a0)
+	move.w	(FPD_RND,FPDATA),%d2
+	jne	fp_ne_roundother	| %d2 == 0, round to nearest
+	tst.b	%d0			| test guard bit
+	jpl	9f			| zero is closer
+	btst	#0,(11,%a0)		| test lsb bit
+	jne	fp_ne_doroundup		| round to infinity
+	lsl.b	#1,%d0			| check low bits
+	jeq	9f			| round to zero
+fp_ne_doroundup:
+	addq.l	#1,(8,%a0)
+	jcc	9f
+	addq.l	#1,(4,%a0)
+	jcc	9f
+	addq.w	#1,(2,%a0)
+	move.w	#0x8000,(4,%a0)
+9:	printf	PNORM,"%p(",1,%a0
+	printx	PNORM,%a0@
+	printf	PNORM,")\n"
+	rts
+fp_ne_roundother:
+	subq.w	#2,%d2
+	jcs	9b			| %d2 < 2, round to zero
+	jhi	1f			| %d2 > 2, round to +infinity
+	tst.b	(1,%a0)			| to -inf
+	jne	fp_ne_doroundup		| negative, round to infinity
+	jra	9b			| positive, round to zero
+1:	tst.b	(1,%a0)			| to +inf
+	jeq	fp_ne_doroundup		| positive, round to infinity
+	jra	9b			| negative, round to zero
+#endif
+	| Zeros and subnormal numbers
+	| These are probably merely subnormal, rather than "denormalized"
+	|  numbers, so we will try to make them normal again.
+fp_ne_small:
+	jne	fp_ne_small1		| high lword zero?
+	move.l	(4,%a0),%d0
+	jne	fp_ne_small2
+#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
+	clr.l	%d0
+	move.b	(-4,%a0),%d0
+	jne	fp_ne_small3
+#endif
+	| Genuine zero.
+	clr.w	-(%a0)
+	subq.l	#2,%a0
+	printf	PNORM,"%p(",1,%a0
+	printx	PNORM,%a0@
+	printf	PNORM,")\n"
+	rts
+	| Subnormal.
+fp_ne_small1:
+	bfffo	%d0{#0,#32},%d1
+	move.w	-(%a0),%d2
+	sub.w	%d1,%d2
+	jcc	1f
+	| Pathologically small, denormalize.
+	add.w	%d2,%d1
+	clr.w	%d2
+	fp_set_sr FPSR_EXC_UNFL
+1:	move.w	%d2,(%a0)+
+	move.w	%d1,%d2
+	jeq	fp_ne_checkround
+	| This is exactly the same 64-bit double shift as seen above.
+	lsl.l	%d2,%d0
+	move.l	%d0,(%a0)+
+	move.l	(%a0),%d0
+	move.l	%d0,%d1
+	lsl.l	%d2,%d0
+	move.l	%d0,(%a0)
+	neg.w	%d2
+	and.w	#0x1f,%d2
+	lsr.l	%d2,%d1
+	or.l	%d1,-(%a0)
+#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
+fp_ne_extra1:
+	clr.l	%d0
+	move.b	(-4,%a0),%d0
+	neg.w	%d2
+	add.w	#24,%d2
+	jcc	1f
+	clr.b	(-4,%a0)
+	lsl.l	%d2,%d0
+	or.l	%d0,(4,%a0)
+	jra	fp_ne_checkround
+1:	addq.w	#8,%d2
+	lsl.l	%d2,%d0
+	move.b	%d0,(-4,%a0)
+	lsr.l	#8,%d0
+	or.l	%d0,(4,%a0)
+#endif
+	jra	fp_ne_checkround
+	| May or may not be subnormal, if so, only 32 bits to shift.
+fp_ne_small2:
+	bfffo	%d0{#0,#32},%d1
+	add.w	#32,%d1
+	move.w	-(%a0),%d2
+	sub.w	%d1,%d2
+	jcc	1f
+	| Beyond pathologically small, denormalize.
+	add.w	%d2,%d1
+	clr.w	%d2
+	fp_set_sr FPSR_EXC_UNFL
+1:	move.w	%d2,(%a0)+
+	ext.l	%d1
+	jeq	fp_ne_checkround
+	clr.l	(4,%a0)
+	sub.w	#32,%d1
+	jcs	1f
+	lsl.l	%d1,%d0			| lower lword needs only to be shifted
+	move.l	%d0,(%a0)		| into the higher lword
+#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
+	clr.l	%d0
+	move.b	(-4,%a0),%d0
+	clr.b	(-4,%a0)
+	neg.w	%d1
+	add.w	#32,%d1
+	bfins	%d0,(%a0){%d1,#8}
+#endif
+	jra	fp_ne_checkround
+1:	neg.w	%d1			| lower lword is splitted between
+	bfins	%d0,(%a0){%d1,#32}	| higher and lower lword
+#ifndef CONFIG_M68KFPU_EMU_EXTRAPREC
+	jra	fp_ne_checkround
+#else
+	move.w	%d1,%d2
+	jra	fp_ne_extra1
+	| These are extremely small numbers, that will mostly end up as zero
+	| anyway, so this is only important for correct rounding.
+fp_ne_small3:
+	bfffo	%d0{#24,#8},%d1
+	add.w	#40,%d1
+	move.w	-(%a0),%d2
+	sub.w	%d1,%d2
+	jcc	1f
+	| Pathologically small, denormalize.
+	add.w	%d2,%d1
+	clr.w	%d2
+1:	move.w	%d2,(%a0)+
+	ext.l	%d1
+	jeq	fp_ne_checkround
+	cmp.w	#8,%d1
+	jcs	2f
+1:	clr.b	(-4,%a0)
+	sub.w	#64,%d1
+	jcs	1f
+	add.w	#24,%d1
+	lsl.l	%d1,%d0
+	move.l	%d0,(%a0)
+	jra	fp_ne_checkround
+1:	neg.w	%d1
+	bfins	%d0,(%a0){%d1,#8}
+	jra	fp_ne_checkround
+2:	lsl.l	%d1,%d0
+	move.b	%d0,(-4,%a0)
+	lsr.l	#8,%d0
+	move.b	%d0,(7,%a0)
+	jra	fp_ne_checkround
+#endif
+	| Infinities and NaNs, again, same as above.
+fp_ne_large:
+	move.l	(%a0)+,%d0
+	jne	3f
+1:	tst.l	(%a0)
+	jne	4f
+2:	subq.l	#8,%a0
+	printf	PNORM,"%p(",1,%a0
+	printx	PNORM,%a0@
+	printf	PNORM,")\n"
+	rts
+	| we have maybe a NaN, shift off the highest bit
+3:	move.l	%d0,%d1
+	lsl.l	#1,%d1
+	jne	4f
+	clr.l	(-4,%a0)
+	jra	1b
+	| we have a NaN, test if it is signaling
+4:	bset	#30,%d0
+	jne	2b
+	fp_set_sr FPSR_EXC_SNAN
+	move.l	%d0,(-4,%a0)
+	jra	2b
+
+	| these next two do rounding as per the IEEE standard.
+	| values for the rounding modes appear to be:
+	| 0:	Round to nearest
+	| 1:	Round to zero
+	| 2:	Round to -Infinity
+	| 3:	Round to +Infinity
+	| both functions expect that fp_normalize was already
+	| called (and extended argument is already normalized
+	| as far as possible), these are used if there is different
+	| rounding precision is selected and before converting
+	| into single/double
+
+	| fp_normalize_double:
+	| normalize an extended with double (52-bit) precision
+	| args:	 %a0 (struct fp_ext *)
+
+fp_normalize_double:
+	printf	PNORM,"nd: %p(",1,%a0
+	printx	PNORM,%a0@
+	printf	PNORM,"), "
+	move.l	(%a0)+,%d2
+	tst.w	%d2
+	jeq	fp_nd_zero		| zero / denormalized
+	cmp.w	#0x7fff,%d2
+	jeq	fp_nd_huge		| NaN / infinitive.
+	sub.w	#0x4000-0x3ff,%d2	| will the exponent fit?
+	jcs	fp_nd_small		| too small.
+	cmp.w	#0x7fe,%d2
+	jcc	fp_nd_large		| too big.
+	addq.l	#4,%a0
+	move.l	(%a0),%d0		| low lword of mantissa
+	| now, round off the low 11 bits.
+fp_nd_round:
+	moveq	#21,%d1
+	lsl.l	%d1,%d0			| keep 11 low bits.
+	jne	fp_nd_checkround	| Are they non-zero?
+	| nothing to do here
+9:	subq.l	#8,%a0
+	printf	PNORM,"%p(",1,%a0
+	printx	PNORM,%a0@
+	printf	PNORM,")\n"
+	rts
+	| Be careful with the X bit! It contains the lsb
+	| from the shift above, it is needed for round to nearest.
+fp_nd_checkround:
+	fp_set_sr FPSR_EXC_INEX2	| INEX2 bit
+	and.w	#0xf800,(2,%a0)		| clear bits 0-10
+	move.w	(FPD_RND,FPDATA),%d2	| rounding mode
+	jne	2f			| %d2 == 0, round to nearest
+	tst.l	%d0			| test guard bit
+	jpl	9b			| zero is closer
+	| here we test the X bit by adding it to %d2
+	clr.w	%d2			| first set z bit, addx only clears it
+	addx.w	%d2,%d2			| test lsb bit
+	| IEEE754-specified "round to even" behaviour.  If the guard
+	| bit is set, then the number is odd, so rounding works like
+	| in grade-school arithmetic (i.e. 1.5 rounds to 2.0)
+	| Otherwise, an equal distance rounds towards zero, so as not
+	| to produce an odd number.  This is strange, but it is what
+	| the standard says.
+	jne	fp_nd_doroundup		| round to infinity
+	lsl.l	#1,%d0			| check low bits
+	jeq	9b			| round to zero
+fp_nd_doroundup:
+	| round (the mantissa, that is) towards infinity
+	add.l	#0x800,(%a0)
+	jcc	9b			| no overflow, good.
+	addq.l	#1,-(%a0)		| extend to high lword
+	jcc	1f			| no overflow, good.
+	| Yow! we have managed to overflow the mantissa.  Since this
+	| only happens when %d1 was 0xfffff800, it is now zero, so
+	| reset the high bit, and increment the exponent.
+	move.w	#0x8000,(%a0)
+	addq.w	#1,-(%a0)
+	cmp.w	#0x43ff,(%a0)+		| exponent now overflown?
+	jeq	fp_nd_large		| yes, so make it infinity.
+1:	subq.l	#4,%a0
+	printf	PNORM,"%p(",1,%a0
+	printx	PNORM,%a0@
+	printf	PNORM,")\n"
+	rts
+2:	subq.w	#2,%d2
+	jcs	9b			| %d2 < 2, round to zero
+	jhi	3f			| %d2 > 2, round to +infinity
+	| Round to +Inf or -Inf.  High word of %d2 contains the
+	| sign of the number, by the way.
+	swap	%d2			| to -inf
+	tst.b	%d2
+	jne	fp_nd_doroundup		| negative, round to infinity
+	jra	9b			| positive, round to zero
+3:	swap	%d2			| to +inf
+	tst.b	%d2
+	jeq	fp_nd_doroundup		| positive, round to infinity
+	jra	9b			| negative, round to zero
+	| Exponent underflow.  Try to make a denormal, and set it to
+	| the smallest possible fraction if this fails.
+fp_nd_small:
+	fp_set_sr FPSR_EXC_UNFL		| set UNFL bit
+	move.w	#0x3c01,(-2,%a0)	| 2**-1022
+	neg.w	%d2			| degree of underflow
+	cmp.w	#32,%d2			| single or double shift?
+	jcc	1f
+	| Again, another 64-bit double shift.
+	move.l	(%a0),%d0
+	move.l	%d0,%d1
+	lsr.l	%d2,%d0
+	move.l	%d0,(%a0)+
+	move.l	(%a0),%d0
+	lsr.l	%d2,%d0
+	neg.w	%d2
+	add.w	#32,%d2
+	lsl.l	%d2,%d1
+	or.l	%d1,%d0
+	move.l	(%a0),%d1
+	move.l	%d0,(%a0)
+	| Check to see if we shifted off any significant bits
+	lsl.l	%d2,%d1
+	jeq	fp_nd_round		| Nope, round.
+	bset	#0,%d0			| Yes, so set the "sticky bit".
+	jra	fp_nd_round		| Now, round.
+	| Another 64-bit single shift and store
+1:	sub.w	#32,%d2
+	cmp.w	#32,%d2			| Do we really need to shift?
+	jcc	2f			| No, the number is too small.
+	move.l	(%a0),%d0
+	clr.l	(%a0)+
+	move.l	%d0,%d1
+	lsr.l	%d2,%d0
+	neg.w	%d2
+	add.w	#32,%d2
+	| Again, check to see if we shifted off any significant bits.
+	tst.l	(%a0)
+	jeq	1f
+	bset	#0,%d0			| Sticky bit.
+1:	move.l	%d0,(%a0)
+	lsl.l	%d2,%d1
+	jeq	fp_nd_round
+	bset	#0,%d0
+	jra	fp_nd_round
+	| Sorry, the number is just too small.
+2:	clr.l	(%a0)+
+	clr.l	(%a0)
+	moveq	#1,%d0			| Smallest possible fraction,
+	jra	fp_nd_round		| round as desired.
+	| zero and denormalized
+fp_nd_zero:
+	tst.l	(%a0)+
+	jne	1f
+	tst.l	(%a0)
+	jne	1f
+	subq.l	#8,%a0
+	printf	PNORM,"%p(",1,%a0
+	printx	PNORM,%a0@
+	printf	PNORM,")\n"
+	rts				| zero.  nothing to do.
+	| These are not merely subnormal numbers, but true denormals,
+	| i.e. pathologically small (exponent is 2**-16383) numbers.
+	| It is clearly impossible for even a normal extended number
+	| with that exponent to fit into double precision, so just
+	| write these ones off as "too darn small".
+1:	fp_set_sr FPSR_EXC_UNFL		| Set UNFL bit
+	clr.l	(%a0)
+	clr.l	-(%a0)
+	move.w	#0x3c01,-(%a0)		| i.e. 2**-1022
+	addq.l	#6,%a0
+	moveq	#1,%d0
+	jra	fp_nd_round		| round.
+	| Exponent overflow.  Just call it infinity.
+fp_nd_large:
+	move.w	#0x7ff,%d0
+	and.w	(6,%a0),%d0
+	jeq	1f
+	fp_set_sr FPSR_EXC_INEX2
+1:	fp_set_sr FPSR_EXC_OVFL
+	move.w	(FPD_RND,FPDATA),%d2
+	jne	3f			| %d2 = 0 round to nearest
+1:	move.w	#0x7fff,(-2,%a0)
+	clr.l	(%a0)+
+	clr.l	(%a0)
+2:	subq.l	#8,%a0
+	printf	PNORM,"%p(",1,%a0
+	printx	PNORM,%a0@
+	printf	PNORM,")\n"
+	rts
+3:	subq.w	#2,%d2
+	jcs	5f			| %d2 < 2, round to zero
+	jhi	4f			| %d2 > 2, round to +infinity
+	tst.b	(-3,%a0)		| to -inf
+	jne	1b
+	jra	5f
+4:	tst.b	(-3,%a0)		| to +inf
+	jeq	1b
+5:	move.w	#0x43fe,(-2,%a0)
+	moveq	#-1,%d0
+	move.l	%d0,(%a0)+
+	move.w	#0xf800,%d0
+	move.l	%d0,(%a0)
+	jra	2b
+	| Infinities or NaNs
+fp_nd_huge:
+	subq.l	#4,%a0
+	printf	PNORM,"%p(",1,%a0
+	printx	PNORM,%a0@
+	printf	PNORM,")\n"
+	rts
+
+	| fp_normalize_single:
+	| normalize an extended with single (23-bit) precision
+	| args:	 %a0 (struct fp_ext *)
+
+fp_normalize_single:
+	printf	PNORM,"ns: %p(",1,%a0
+	printx	PNORM,%a0@
+	printf	PNORM,") "
+	addq.l	#2,%a0
+	move.w	(%a0)+,%d2
+	jeq	fp_ns_zero		| zero / denormalized
+	cmp.w	#0x7fff,%d2
+	jeq	fp_ns_huge		| NaN / infinitive.
+	sub.w	#0x4000-0x7f,%d2	| will the exponent fit?
+	jcs	fp_ns_small		| too small.
+	cmp.w	#0xfe,%d2
+	jcc	fp_ns_large		| too big.
+	move.l	(%a0)+,%d0		| get high lword of mantissa
+fp_ns_round:
+	tst.l	(%a0)			| check the low lword
+	jeq	1f
+	| Set a sticky bit if it is non-zero.  This should only
+	| affect the rounding in what would otherwise be equal-
+	| distance situations, which is what we want it to do.
+	bset	#0,%d0
+1:	clr.l	(%a0)			| zap it from memory.
+	| now, round off the low 8 bits of the hi lword.
+	tst.b	%d0			| 8 low bits.
+	jne	fp_ns_checkround	| Are they non-zero?
+	| nothing to do here
+	subq.l	#8,%a0
+	printf	PNORM,"%p(",1,%a0
+	printx	PNORM,%a0@
+	printf	PNORM,")\n"
+	rts
+fp_ns_checkround:
+	fp_set_sr FPSR_EXC_INEX2	| INEX2 bit
+	clr.b	-(%a0)			| clear low byte of high lword
+	subq.l	#3,%a0
+	move.w	(FPD_RND,FPDATA),%d2	| rounding mode
+	jne	2f			| %d2 == 0, round to nearest
+	tst.b	%d0			| test guard bit
+	jpl	9f			| zero is closer
+	btst	#8,%d0			| test lsb bit
+	| round to even behaviour, see above.
+	jne	fp_ns_doroundup		| round to infinity
+	lsl.b	#1,%d0			| check low bits
+	jeq	9f			| round to zero
+fp_ns_doroundup:
+	| round (the mantissa, that is) towards infinity
+	add.l	#0x100,(%a0)
+	jcc	9f			| no overflow, good.
+	| Overflow.  This means that the %d1 was 0xffffff00, so it
+	| is now zero.  We will set the mantissa to reflect this, and
+	| increment the exponent (checking for overflow there too)
+	move.w	#0x8000,(%a0)
+	addq.w	#1,-(%a0)
+	cmp.w	#0x407f,(%a0)+		| exponent now overflown?
+	jeq	fp_ns_large		| yes, so make it infinity.
+9:	subq.l	#4,%a0
+	printf	PNORM,"%p(",1,%a0
+	printx	PNORM,%a0@
+	printf	PNORM,")\n"
+	rts
+	| check nondefault rounding modes
+2:	subq.w	#2,%d2
+	jcs	9b			| %d2 < 2, round to zero
+	jhi	3f			| %d2 > 2, round to +infinity
+	tst.b	(-3,%a0)		| to -inf
+	jne	fp_ns_doroundup		| negative, round to infinity
+	jra	9b			| positive, round to zero
+3:	tst.b	(-3,%a0)		| to +inf
+	jeq	fp_ns_doroundup		| positive, round to infinity
+	jra	9b			| negative, round to zero
+	| Exponent underflow.  Try to make a denormal, and set it to
+	| the smallest possible fraction if this fails.
+fp_ns_small:
+	fp_set_sr FPSR_EXC_UNFL		| set UNFL bit
+	move.w	#0x3f81,(-2,%a0)	| 2**-126
+	neg.w	%d2			| degree of underflow
+	cmp.w	#32,%d2			| single or double shift?
+	jcc	2f
+	| a 32-bit shift.
+	move.l	(%a0),%d0
+	move.l	%d0,%d1
+	lsr.l	%d2,%d0
+	move.l	%d0,(%a0)+
+	| Check to see if we shifted off any significant bits.
+	neg.w	%d2
+	add.w	#32,%d2
+	lsl.l	%d2,%d1
+	jeq	1f
+	bset	#0,%d0			| Sticky bit.
+	| Check the lower lword
+1:	tst.l	(%a0)
+	jeq	fp_ns_round
+	clr	(%a0)
+	bset	#0,%d0			| Sticky bit.
+	jra	fp_ns_round
+	| Sorry, the number is just too small.
+2:	clr.l	(%a0)+
+	clr.l	(%a0)
+	moveq	#1,%d0			| Smallest possible fraction,
+	jra	fp_ns_round		| round as desired.
+	| Exponent overflow.  Just call it infinity.
+fp_ns_large:
+	tst.b	(3,%a0)
+	jeq	1f
+	fp_set_sr FPSR_EXC_INEX2
+1:	fp_set_sr FPSR_EXC_OVFL
+	move.w	(FPD_RND,FPDATA),%d2
+	jne	3f			| %d2 = 0 round to nearest
+1:	move.w	#0x7fff,(-2,%a0)
+	clr.l	(%a0)+
+	clr.l	(%a0)
+2:	subq.l	#8,%a0
+	printf	PNORM,"%p(",1,%a0
+	printx	PNORM,%a0@
+	printf	PNORM,")\n"
+	rts
+3:	subq.w	#2,%d2
+	jcs	5f			| %d2 < 2, round to zero
+	jhi	4f			| %d2 > 2, round to +infinity
+	tst.b	(-3,%a0)		| to -inf
+	jne	1b
+	jra	5f
+4:	tst.b	(-3,%a0)		| to +inf
+	jeq	1b
+5:	move.w	#0x407e,(-2,%a0)
+	move.l	#0xffffff00,(%a0)+
+	clr.l	(%a0)
+	jra	2b
+	| zero and denormalized
+fp_ns_zero:
+	tst.l	(%a0)+
+	jne	1f
+	tst.l	(%a0)
+	jne	1f
+	subq.l	#8,%a0
+	printf	PNORM,"%p(",1,%a0
+	printx	PNORM,%a0@
+	printf	PNORM,")\n"
+	rts				| zero.  nothing to do.
+	| These are not merely subnormal numbers, but true denormals,
+	| i.e. pathologically small (exponent is 2**-16383) numbers.
+	| It is clearly impossible for even a normal extended number
+	| with that exponent to fit into single precision, so just
+	| write these ones off as "too darn small".
+1:	fp_set_sr FPSR_EXC_UNFL		| Set UNFL bit
+	clr.l	(%a0)
+	clr.l	-(%a0)
+	move.w	#0x3f81,-(%a0)		| i.e. 2**-126
+	addq.l	#6,%a0
+	moveq	#1,%d0
+	jra	fp_ns_round		| round.
+	| Infinities or NaNs
+fp_ns_huge:
+	subq.l	#4,%a0
+	printf	PNORM,"%p(",1,%a0
+	printx	PNORM,%a0@
+	printf	PNORM,")\n"
+	rts
+
+	| fp_normalize_single_fast:
+	| normalize an extended with single (23-bit) precision
+	| this is only used by fsgldiv/fsgdlmul, where the
+	| operand is not completly normalized.
+	| args:	 %a0 (struct fp_ext *)
+
+fp_normalize_single_fast:
+	printf	PNORM,"nsf: %p(",1,%a0
+	printx	PNORM,%a0@
+	printf	PNORM,") "
+	addq.l	#2,%a0
+	move.w	(%a0)+,%d2
+	cmp.w	#0x7fff,%d2
+	jeq	fp_nsf_huge		| NaN / infinitive.
+	move.l	(%a0)+,%d0		| get high lword of mantissa
+fp_nsf_round:
+	tst.l	(%a0)			| check the low lword
+	jeq	1f
+	| Set a sticky bit if it is non-zero.  This should only
+	| affect the rounding in what would otherwise be equal-
+	| distance situations, which is what we want it to do.
+	bset	#0,%d0
+1:	clr.l	(%a0)			| zap it from memory.
+	| now, round off the low 8 bits of the hi lword.
+	tst.b	%d0			| 8 low bits.
+	jne	fp_nsf_checkround	| Are they non-zero?
+	| nothing to do here
+	subq.l	#8,%a0
+	printf	PNORM,"%p(",1,%a0
+	printx	PNORM,%a0@
+	printf	PNORM,")\n"
+	rts
+fp_nsf_checkround:
+	fp_set_sr FPSR_EXC_INEX2	| INEX2 bit
+	clr.b	-(%a0)			| clear low byte of high lword
+	subq.l	#3,%a0
+	move.w	(FPD_RND,FPDATA),%d2	| rounding mode
+	jne	2f			| %d2 == 0, round to nearest
+	tst.b	%d0			| test guard bit
+	jpl	9f			| zero is closer
+	btst	#8,%d0			| test lsb bit
+	| round to even behaviour, see above.
+	jne	fp_nsf_doroundup		| round to infinity
+	lsl.b	#1,%d0			| check low bits
+	jeq	9f			| round to zero
+fp_nsf_doroundup:
+	| round (the mantissa, that is) towards infinity
+	add.l	#0x100,(%a0)
+	jcc	9f			| no overflow, good.
+	| Overflow.  This means that the %d1 was 0xffffff00, so it
+	| is now zero.  We will set the mantissa to reflect this, and
+	| increment the exponent (checking for overflow there too)
+	move.w	#0x8000,(%a0)
+	addq.w	#1,-(%a0)
+	cmp.w	#0x407f,(%a0)+		| exponent now overflown?
+	jeq	fp_nsf_large		| yes, so make it infinity.
+9:	subq.l	#4,%a0
+	printf	PNORM,"%p(",1,%a0
+	printx	PNORM,%a0@
+	printf	PNORM,")\n"
+	rts
+	| check nondefault rounding modes
+2:	subq.w	#2,%d2
+	jcs	9b			| %d2 < 2, round to zero
+	jhi	3f			| %d2 > 2, round to +infinity
+	tst.b	(-3,%a0)		| to -inf
+	jne	fp_nsf_doroundup	| negative, round to infinity
+	jra	9b			| positive, round to zero
+3:	tst.b	(-3,%a0)		| to +inf
+	jeq	fp_nsf_doroundup		| positive, round to infinity
+	jra	9b			| negative, round to zero
+	| Exponent overflow.  Just call it infinity.
+fp_nsf_large:
+	tst.b	(3,%a0)
+	jeq	1f
+	fp_set_sr FPSR_EXC_INEX2
+1:	fp_set_sr FPSR_EXC_OVFL
+	move.w	(FPD_RND,FPDATA),%d2
+	jne	3f			| %d2 = 0 round to nearest
+1:	move.w	#0x7fff,(-2,%a0)
+	clr.l	(%a0)+
+	clr.l	(%a0)
+2:	subq.l	#8,%a0
+	printf	PNORM,"%p(",1,%a0
+	printx	PNORM,%a0@
+	printf	PNORM,")\n"
+	rts
+3:	subq.w	#2,%d2
+	jcs	5f			| %d2 < 2, round to zero
+	jhi	4f			| %d2 > 2, round to +infinity
+	tst.b	(-3,%a0)		| to -inf
+	jne	1b
+	jra	5f
+4:	tst.b	(-3,%a0)		| to +inf
+	jeq	1b
+5:	move.w	#0x407e,(-2,%a0)
+	move.l	#0xffffff00,(%a0)+
+	clr.l	(%a0)
+	jra	2b
+	| Infinities or NaNs
+fp_nsf_huge:
+	subq.l	#4,%a0
+	printf	PNORM,"%p(",1,%a0
+	printx	PNORM,%a0@
+	printf	PNORM,")\n"
+	rts
+
+	| conv_ext2int (macro):
+	| Generates a subroutine that converts an extended value to an
+	| integer of a given size, again, with the appropriate type of
+	| rounding.
+
+	| Macro arguments:
+	| s:	size, as given in an assembly instruction.
+	| b:	number of bits in that size.
+
+	| Subroutine arguments:
+	| %a0:	source (struct fp_ext *)
+
+	| Returns the integer in %d0 (like it should)
+
+.macro conv_ext2int s,b
+	.set	inf,(1<<(\b-1))-1	| i.e. MAXINT
+	printf	PCONV,"e2i%d: %p(",2,#\b,%a0
+	printx	PCONV,%a0@
+	printf	PCONV,") "
+	addq.l	#2,%a0
+	move.w	(%a0)+,%d2		| exponent
+	jeq	fp_e2i_zero\b		| zero / denorm (== 0, here)
+	cmp.w	#0x7fff,%d2
+	jeq	fp_e2i_huge\b		| Inf / NaN
+	sub.w	#0x3ffe,%d2
+	jcs	fp_e2i_small\b
+	cmp.w	#\b,%d2
+	jhi	fp_e2i_large\b
+	move.l	(%a0),%d0
+	move.l	%d0,%d1
+	lsl.l	%d2,%d1
+	jne	fp_e2i_round\b
+	tst.l	(4,%a0)
+	jne	fp_e2i_round\b
+	neg.w	%d2
+	add.w	#32,%d2
+	lsr.l	%d2,%d0
+9:	tst.w	(-4,%a0)
+	jne	1f
+	tst.\s	%d0
+	jmi	fp_e2i_large\b
+	printf	PCONV,"-> %p\n",1,%d0
+	rts
+1:	neg.\s	%d0
+	jeq	1f
+	jpl	fp_e2i_large\b
+1:	printf	PCONV,"-> %p\n",1,%d0
+	rts
+fp_e2i_round\b:
+	fp_set_sr FPSR_EXC_INEX2	| INEX2 bit
+	neg.w	%d2
+	add.w	#32,%d2
+	.if	\b>16
+	jeq	5f
+	.endif
+	lsr.l	%d2,%d0
+	move.w	(FPD_RND,FPDATA),%d2	| rounding mode
+	jne	2f			| %d2 == 0, round to nearest
+	tst.l	%d1			| test guard bit
+	jpl	9b			| zero is closer
+	btst	%d2,%d0			| test lsb bit (%d2 still 0)
+	jne	fp_e2i_doroundup\b
+	lsl.l	#1,%d1			| check low bits
+	jne	fp_e2i_doroundup\b
+	tst.l	(4,%a0)
+	jeq	9b
+fp_e2i_doroundup\b:
+	addq.l	#1,%d0
+	jra	9b
+	| check nondefault rounding modes
+2:	subq.w	#2,%d2
+	jcs	9b			| %d2 < 2, round to zero
+	jhi	3f			| %d2 > 2, round to +infinity
+	tst.w	(-4,%a0)		| to -inf
+	jne	fp_e2i_doroundup\b	| negative, round to infinity
+	jra	9b			| positive, round to zero
+3:	tst.w	(-4,%a0)		| to +inf
+	jeq	fp_e2i_doroundup\b	| positive, round to infinity
+	jra	9b	| negative, round to zero
+	| we are only want -2**127 get correctly rounded here,
+	| since the guard bit is in the lower lword.
+	| everything else ends up anyway as overflow.
+	.if	\b>16
+5:	move.w	(FPD_RND,FPDATA),%d2	| rounding mode
+	jne	2b			| %d2 == 0, round to nearest
+	move.l	(4,%a0),%d1		| test guard bit
+	jpl	9b			| zero is closer
+	lsl.l	#1,%d1			| check low bits
+	jne	fp_e2i_doroundup\b
+	jra	9b
+	.endif
+fp_e2i_zero\b:
+	clr.l	%d0
+	tst.l	(%a0)+
+	jne	1f
+	tst.l	(%a0)
+	jeq	3f
+1:	subq.l	#4,%a0
+	fp_clr_sr FPSR_EXC_UNFL		| fp_normalize_ext has set this bit
+fp_e2i_small\b:
+	fp_set_sr FPSR_EXC_INEX2
+	clr.l	%d0
+	move.w	(FPD_RND,FPDATA),%d2	| rounding mode
+	subq.w	#2,%d2
+	jcs	3f			| %d2 < 2, round to nearest/zero
+	jhi	2f			| %d2 > 2, round to +infinity
+	tst.w	(-4,%a0)		| to -inf
+	jeq	3f
+	subq.\s	#1,%d0
+	jra	3f
+2:	tst.w	(-4,%a0)		| to +inf
+	jne	3f
+	addq.\s	#1,%d0
+3:	printf	PCONV,"-> %p\n",1,%d0
+	rts
+fp_e2i_large\b:
+	fp_set_sr FPSR_EXC_OPERR
+	move.\s	#inf,%d0
+	tst.w	(-4,%a0)
+	jeq	1f
+	addq.\s	#1,%d0
+1:	printf	PCONV,"-> %p\n",1,%d0
+	rts
+fp_e2i_huge\b:
+	move.\s	(%a0),%d0
+	tst.l	(%a0)
+	jne	1f
+	tst.l	(%a0)
+	jeq	fp_e2i_large\b
+	| fp_normalize_ext has set this bit already
+	| and made the number nonsignaling
+1:	fp_tst_sr FPSR_EXC_SNAN
+	jne	1f
+	fp_set_sr FPSR_EXC_OPERR
+1:	printf	PCONV,"-> %p\n",1,%d0
+	rts
+.endm
+
+fp_conv_ext2long:
+	conv_ext2int l,32
+
+fp_conv_ext2short:
+	conv_ext2int w,16
+
+fp_conv_ext2byte:
+	conv_ext2int b,8
+
+fp_conv_ext2double:
+	jsr	fp_normalize_double
+	printf	PCONV,"e2d: %p(",1,%a0
+	printx	PCONV,%a0@
+	printf	PCONV,"), "
+	move.l	(%a0)+,%d2
+	cmp.w	#0x7fff,%d2
+	jne	1f
+	move.w	#0x7ff,%d2
+	move.l	(%a0)+,%d0
+	jra	2f
+1:	sub.w	#0x3fff-0x3ff,%d2
+	move.l	(%a0)+,%d0
+	jmi	2f
+	clr.w	%d2
+2:	lsl.w	#5,%d2
+	lsl.l	#7,%d2
+	lsl.l	#8,%d2
+	move.l	%d0,%d1
+	lsl.l	#1,%d0
+	lsr.l	#4,%d0
+	lsr.l	#8,%d0
+	or.l	%d2,%d0
+	putuser.l %d0,(%a1)+,fp_err_ua2,%a1
+	moveq	#21,%d0
+	lsl.l	%d0,%d1
+	move.l	(%a0),%d0
+	lsr.l	#4,%d0
+	lsr.l	#7,%d0
+	or.l	%d1,%d0
+	putuser.l %d0,(%a1),fp_err_ua2,%a1
+#ifdef FPU_EMU_DEBUG
+	getuser.l %a1@(-4),%d0,fp_err_ua2,%a1
+	getuser.l %a1@(0),%d1,fp_err_ua2,%a1
+	printf	PCONV,"%p(%08x%08x)\n",3,%a1,%d0,%d1
+#endif
+	rts
+
+fp_conv_ext2single:
+	jsr	fp_normalize_single
+	printf	PCONV,"e2s: %p(",1,%a0
+	printx	PCONV,%a0@
+	printf	PCONV,"), "
+	move.l	(%a0)+,%d1
+	cmp.w	#0x7fff,%d1
+	jne	1f
+	move.w	#0xff,%d1
+	move.l	(%a0)+,%d0
+	jra	2f
+1:	sub.w	#0x3fff-0x7f,%d1
+	move.l	(%a0)+,%d0
+	jmi	2f
+	clr.w	%d1
+2:	lsl.w	#8,%d1
+	lsl.l	#7,%d1
+	lsl.l	#8,%d1
+	bclr	#31,%d0
+	lsr.l	#8,%d0
+	or.l	%d1,%d0
+	printf	PCONV,"%08x\n",1,%d0
+	rts
+
+	| special return addresses for instr that
+	| encode the rounding precision in the opcode
+	| (e.g. fsmove,fdmove)
+
+fp_finalrounding_single:
+	addq.l	#8,%sp
+	jsr	fp_normalize_ext
+	jsr	fp_normalize_single
+	jra	fp_finaltest
+
+fp_finalrounding_single_fast:
+	addq.l	#8,%sp 
+	jsr	fp_normalize_ext
+	jsr	fp_normalize_single_fast
+	jra	fp_finaltest
+
+fp_finalrounding_double:
+	addq.l	#8,%sp
+	jsr	fp_normalize_ext
+	jsr	fp_normalize_double
+	jra	fp_finaltest
+
+	| fp_finaltest:
+	| set the emulated status register based on the outcome of an
+	| emulated instruction.
+
+fp_finalrounding:
+	addq.l	#8,%sp
+|	printf	,"f: %p\n",1,%a0
+	jsr	fp_normalize_ext
+	move.w	(FPD_PREC,FPDATA),%d0
+	subq.w	#1,%d0
+	jcs	fp_finaltest
+	jne	1f
+	jsr	fp_normalize_single
+	jra	2f
+1:	jsr	fp_normalize_double
+2:|	printf	,"f: %p\n",1,%a0
+fp_finaltest:
+	| First, we do some of the obvious tests for the exception
+	| status byte and condition code bytes of fp_sr here, so that
+	| they do not have to be handled individually by every
+	| emulated instruction.
+	clr.l	%d0
+	addq.l	#1,%a0
+	tst.b	(%a0)+			| sign
+	jeq	1f
+	bset	#FPSR_CC_NEG-24,%d0	| N bit
+1:	cmp.w	#0x7fff,(%a0)+		| exponent
+	jeq	2f
+	| test for zero
+	moveq	#FPSR_CC_Z-24,%d1
+	tst.l	(%a0)+
+	jne	9f
+	tst.l	(%a0)
+	jne	9f
+	jra	8f
+	| infinitiv and NAN
+2:	moveq	#FPSR_CC_NAN-24,%d1
+	move.l	(%a0)+,%d2
+	lsl.l	#1,%d2			| ignore high bit
+	jne	8f
+	tst.l	(%a0)
+	jne	8f
+	moveq	#FPSR_CC_INF-24,%d1
+8:	bset	%d1,%d0
+9:	move.b	%d0,(FPD_FPSR+0,FPDATA)	| set condition test result
+	| move instructions enter here
+	| Here, we test things in the exception status byte, and set
+	| other things in the accrued exception byte accordingly.
+	| Emulated instructions can set various things in the former,
+	| as defined in fp_emu.h.
+fp_final:
+	move.l	(FPD_FPSR,FPDATA),%d0
+#if 0
+	btst	#FPSR_EXC_SNAN,%d0	| EXC_SNAN
+	jne	1f
+	btst	#FPSR_EXC_OPERR,%d0	| EXC_OPERR
+	jeq	2f
+1:	bset	#FPSR_AEXC_IOP,%d0	| set IOP bit
+2:	btst	#FPSR_EXC_OVFL,%d0	| EXC_OVFL
+	jeq	1f
+	bset	#FPSR_AEXC_OVFL,%d0	| set OVFL bit
+1:	btst	#FPSR_EXC_UNFL,%d0	| EXC_UNFL
+	jeq	1f
+	btst	#FPSR_EXC_INEX2,%d0	| EXC_INEX2
+	jeq	1f
+	bset	#FPSR_AEXC_UNFL,%d0	| set UNFL bit
+1:	btst	#FPSR_EXC_DZ,%d0	| EXC_INEX1
+	jeq	1f
+	bset	#FPSR_AEXC_DZ,%d0	| set DZ bit
+1:	btst	#FPSR_EXC_OVFL,%d0	| EXC_OVFL
+	jne	1f
+	btst	#FPSR_EXC_INEX2,%d0	| EXC_INEX2
+	jne	1f
+	btst	#FPSR_EXC_INEX1,%d0	| EXC_INEX1
+	jeq	2f
+1:	bset	#FPSR_AEXC_INEX,%d0	| set INEX bit
+2:	move.l	%d0,(FPD_FPSR,FPDATA)
+#else
+	| same as above, greatly optimized, but untested (yet)
+	move.l	%d0,%d2
+	lsr.l	#5,%d0
+	move.l	%d0,%d1
+	lsr.l	#4,%d1
+	or.l	%d0,%d1
+	and.b	#0x08,%d1
+	move.l	%d2,%d0
+	lsr.l	#6,%d0
+	or.l	%d1,%d0
+	move.l	%d2,%d1
+	lsr.l	#4,%d1
+	or.b	#0xdf,%d1
+	and.b	%d1,%d0
+	move.l	%d2,%d1
+	lsr.l	#7,%d1
+	and.b	#0x80,%d1
+	or.b	%d1,%d0
+	and.b	#0xf8,%d0
+	or.b	%d0,%d2
+	move.l	%d2,(FPD_FPSR,FPDATA)
+#endif
+	move.b	(FPD_FPSR+2,FPDATA),%d0
+	and.b	(FPD_FPCR+2,FPDATA),%d0
+	jeq	1f
+	printf	,"send signal!!!\n"
+1:	jra	fp_end
diff -u --recursive --new-file v2.3.13/linux/arch/m68k/math-emu/multi_arith.h linux/arch/m68k/math-emu/multi_arith.h
--- v2.3.13/linux/arch/m68k/math-emu/multi_arith.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/math-emu/multi_arith.h	Sun Aug 15 11:47:29 1999
@@ -0,0 +1,822 @@
+/* multi_arith.h: multi-precision integer arithmetic functions, needed
+   to do extended-precision floating point.
+
+   (c) 1998 David Huggins-Daines.
+
+   Somewhat based on arch/alpha/math-emu/ieee-math.c, which is (c)
+   David Mosberger-Tang.
+
+   You may copy, modify, and redistribute this file under the terms of
+   the GNU General Public License, version 2, or any later version, at
+   your convenience. */
+
+/* Note:
+
+   These are not general multi-precision math routines.  Rather, they
+   implement the subset of integer arithmetic that we need in order to
+   multiply, divide, and normalize 128-bit unsigned mantissae.  */
+
+#ifndef MULTI_ARITH_H
+#define MULTI_ARITH_H
+
+#if 0	/* old code... */
+
+/* Unsigned only, because we don't need signs to multiply and divide. */
+typedef unsigned int int128[4];
+
+/* Word order */
+enum {
+	MSW128,
+	NMSW128,
+	NLSW128,
+	LSW128
+};
+
+/* big-endian */
+#define LO_WORD(ll) (((unsigned int *) &ll)[1])
+#define HI_WORD(ll) (((unsigned int *) &ll)[0])
+
+/* Convenience functions to stuff various integer values into int128s */
+
+extern inline void zero128(int128 a)
+{
+	a[LSW128] = a[NLSW128] = a[NMSW128] = a[MSW128] = 0;
+}
+
+/* Human-readable word order in the arguments */
+extern inline void set128(unsigned int i3,
+			  unsigned int i2,
+			  unsigned int i1,
+			  unsigned int i0,
+			  int128 a)
+{
+	a[LSW128] = i0;
+	a[NLSW128] = i1;
+	a[NMSW128] = i2;
+	a[MSW128] = i3;
+}
+
+/* Convenience functions (for testing as well) */
+extern inline void int64_to_128(unsigned long long src,
+				int128 dest)
+{
+	dest[LSW128] = (unsigned int) src;
+	dest[NLSW128] = src >> 32;
+	dest[NMSW128] = dest[MSW128] = 0;
+}
+
+extern inline void int128_to_64(const int128 src,
+				unsigned long long *dest)
+{
+	*dest = src[LSW128] | (long long) src[NLSW128] << 32;
+}
+
+extern inline void put_i128(const int128 a)
+{
+	printk("%08x %08x %08x %08x\n", a[MSW128], a[NMSW128],
+	       a[NLSW128], a[LSW128]);
+}
+
+/* Internal shifters:
+
+   Note that these are only good for 0 < count < 32.
+ */
+
+extern inline void _lsl128(unsigned int count, int128 a)
+{
+	a[MSW128] = (a[MSW128] << count) | (a[NMSW128] >> (32 - count));
+	a[NMSW128] = (a[NMSW128] << count) | (a[NLSW128] >> (32 - count));
+	a[NLSW128] = (a[NLSW128] << count) | (a[LSW128] >> (32 - count));
+	a[LSW128] <<= count;
+}
+
+extern inline void _lsr128(unsigned int count, int128 a)
+{
+	a[LSW128] = (a[LSW128] >> count) | (a[NLSW128] << (32 - count));
+	a[NLSW128] = (a[NLSW128] >> count) | (a[NMSW128] << (32 - count));
+	a[NMSW128] = (a[NMSW128] >> count) | (a[MSW128] << (32 - count));
+	a[MSW128] >>= count;
+}
+
+/* Should be faster, one would hope */
+
+extern inline void lslone128(int128 a)
+{
+	asm volatile ("lsl.l #1,%0\n"
+		      "roxl.l #1,%1\n"
+		      "roxl.l #1,%2\n"
+		      "roxl.l #1,%3\n"
+		      :
+		      "=d" (a[LSW128]),
+		      "=d"(a[NLSW128]),
+		      "=d"(a[NMSW128]),
+		      "=d"(a[MSW128])
+		      :
+		      "0"(a[LSW128]),
+		      "1"(a[NLSW128]),
+		      "2"(a[NMSW128]),
+		      "3"(a[MSW128]));
+}
+
+extern inline void lsrone128(int128 a)
+{
+	asm volatile ("lsr.l #1,%0\n"
+		      "roxr.l #1,%1\n"
+		      "roxr.l #1,%2\n"
+		      "roxr.l #1,%3\n"
+		      :
+		      "=d" (a[MSW128]),
+		      "=d"(a[NMSW128]),
+		      "=d"(a[NLSW128]),
+		      "=d"(a[LSW128])
+		      :
+		      "0"(a[MSW128]),
+		      "1"(a[NMSW128]),
+		      "2"(a[NLSW128]),
+		      "3"(a[LSW128]));
+}
+
+/* Generalized 128-bit shifters:
+
+   These bit-shift to a multiple of 32, then move whole longwords.  */
+
+extern inline void lsl128(unsigned int count, int128 a)
+{
+	int wordcount, i;
+
+	if (count % 32)
+		_lsl128(count % 32, a);
+
+	if (0 == (wordcount = count / 32))
+		return;
+
+	/* argh, gak, endian-sensitive */
+	for (i = 0; i < 4 - wordcount; i++) {
+		a[i] = a[i + wordcount];
+	}
+	for (i = 3; i >= 4 - wordcount; --i) {
+		a[i] = 0;
+	}
+}
+
+extern inline void lsr128(unsigned int count, int128 a)
+{
+	int wordcount, i;
+
+	if (count % 32)
+		_lsr128(count % 32, a);
+
+	if (0 == (wordcount = count / 32))
+		return;
+
+	for (i = 3; i >= wordcount; --i) {
+		a[i] = a[i - wordcount];
+	}
+	for (i = 0; i < wordcount; i++) {
+		a[i] = 0;
+	}
+}
+
+extern inline int orl128(int a, int128 b)
+{
+	b[LSW128] |= a;
+}
+
+extern inline int btsthi128(const int128 a)
+{
+	return a[MSW128] & 0x80000000;
+}
+
+/* test bits (numbered from 0 = LSB) up to and including "top" */
+extern inline int bftestlo128(int top, const int128 a)
+{
+	int r = 0;
+
+	if (top > 31)
+		r |= a[LSW128];
+	if (top > 63)
+		r |= a[NLSW128];
+	if (top > 95)
+		r |= a[NMSW128];
+
+	r |= a[3 - (top / 32)] & ((1 << (top % 32 + 1)) - 1);
+
+	return (r != 0);
+}
+
+/* Aargh.  We need these because GCC is broken */
+/* FIXME: do them in assembly, for goodness' sake! */
+extern inline void mask64(int pos, unsigned long long *mask)
+{
+	*mask = 0;
+
+	if (pos < 32) {
+		LO_WORD(*mask) = (1 << pos) - 1;
+		return;
+	}
+	LO_WORD(*mask) = -1;
+	HI_WORD(*mask) = (1 << (pos - 32)) - 1;
+}
+
+extern inline void bset64(int pos, unsigned long long *dest)
+{
+	/* This conditional will be optimized away.  Thanks, GCC! */
+	if (pos < 32)
+		asm volatile ("bset %1,%0":"=m"
+			      (LO_WORD(*dest)):"id"(pos));
+	else
+		asm volatile ("bset %1,%0":"=m"
+			      (HI_WORD(*dest)):"id"(pos - 32));
+}
+
+extern inline int btst64(int pos, unsigned long long dest)
+{
+	if (pos < 32)
+		return (0 != (LO_WORD(dest) & (1 << pos)));
+	else
+		return (0 != (HI_WORD(dest) & (1 << (pos - 32))));
+}
+
+extern inline void lsl64(int count, unsigned long long *dest)
+{
+	if (count < 32) {
+		HI_WORD(*dest) = (HI_WORD(*dest) << count)
+		    | (LO_WORD(*dest) >> count);
+		LO_WORD(*dest) <<= count;
+		return;
+	}
+	count -= 32;
+	HI_WORD(*dest) = LO_WORD(*dest) << count;
+	LO_WORD(*dest) = 0;
+}
+
+extern inline void lsr64(int count, unsigned long long *dest)
+{
+	if (count < 32) {
+		LO_WORD(*dest) = (LO_WORD(*dest) >> count)
+		    | (HI_WORD(*dest) << (32 - count));
+		HI_WORD(*dest) >>= count;
+		return;
+	}
+	count -= 32;
+	LO_WORD(*dest) = HI_WORD(*dest) >> count;
+	HI_WORD(*dest) = 0;
+}
+#endif
+
+extern inline void fp_denormalize(struct fp_ext *reg, unsigned int cnt)
+{
+	reg->exp += cnt;
+
+	switch (cnt) {
+	case 0 ... 8:
+		reg->lowmant = reg->mant.m32[1] << (8 - cnt);
+		reg->mant.m32[1] = (reg->mant.m32[1] >> cnt) |
+				   (reg->mant.m32[0] << (32 - cnt));
+		reg->mant.m32[0] = reg->mant.m32[0] >> cnt;
+		break;
+	case 9 ... 32:
+		reg->lowmant = reg->mant.m32[1] >> (cnt - 8);
+		if (reg->mant.m32[1] << (40 - cnt))
+			reg->lowmant |= 1;
+		reg->mant.m32[1] = (reg->mant.m32[1] >> cnt) |
+				   (reg->mant.m32[0] << (32 - cnt));
+		reg->mant.m32[0] = reg->mant.m32[0] >> cnt;
+		break;
+	case 33 ... 39:
+		asm volatile ("bfextu %1{%2,#8},%0" : "=d" (reg->lowmant)
+			: "m" (reg->mant.m32[0]), "d" (64 - cnt));
+		if (reg->mant.m32[1] << (40 - cnt))
+			reg->lowmant |= 1;
+		reg->mant.m32[1] = reg->mant.m32[0] >> (cnt - 32);
+		reg->mant.m32[0] = 0;
+		break;
+	case 40 ... 71:
+		reg->lowmant = reg->mant.m32[0] >> (cnt - 40);
+		if ((reg->mant.m32[0] << (72 - cnt)) || reg->mant.m32[1])
+			reg->lowmant |= 1;
+		reg->mant.m32[1] = reg->mant.m32[0] >> (cnt - 32);
+		reg->mant.m32[0] = 0;
+		break;
+	default:
+		reg->lowmant = reg->mant.m32[0] || reg->mant.m32[1];
+		reg->mant.m32[0] = 0;
+		reg->mant.m32[1] = 0;
+		break;
+	}
+}
+
+extern inline int fp_overnormalize(struct fp_ext *reg)
+{
+	int shift;
+
+	if (reg->mant.m32[0]) {
+		asm ("bfffo %1{#0,#32},%0" : "=d" (shift) : "dm" (reg->mant.m32[0]));
+		reg->mant.m32[0] = (reg->mant.m32[0] << shift) | (reg->mant.m32[1] >> (32 - shift));
+		reg->mant.m32[1] = (reg->mant.m32[1] << shift);
+	} else {
+		asm ("bfffo %1{#0,#32},%0" : "=d" (shift) : "dm" (reg->mant.m32[1]));
+		reg->mant.m32[0] = (reg->mant.m32[1] << shift);
+		reg->mant.m32[1] = 0;
+		shift += 32;
+	}
+
+	return shift;
+}
+
+extern inline int fp_addmant(struct fp_ext *dest, struct fp_ext *src)
+{
+	int carry;
+
+	/* we assume here, gcc only insert move and a clr instr */
+	asm volatile ("add.b %1,%0" : "=d,=g" (dest->lowmant)
+		: "g,d" (src->lowmant), "0,0" (dest->lowmant));
+	asm volatile ("addx.l %1,%0" : "=d" (dest->mant.m32[1])
+		: "d" (src->mant.m32[1]), "0" (dest->mant.m32[1]));
+	asm volatile ("addx.l %1,%0" : "=d" (dest->mant.m32[0])
+		: "d" (src->mant.m32[0]), "0" (dest->mant.m32[0]));
+	asm volatile ("addx.l %0,%0" : "=d" (carry) : "0" (0));
+
+	return carry;
+}
+
+extern inline int fp_addcarry(struct fp_ext *reg)
+{
+	if (++reg->exp == 0x7fff) {
+		if (reg->mant.m64)
+			fp_set_sr(FPSR_EXC_INEX2);
+		reg->mant.m64 = 0;
+		fp_set_sr(FPSR_EXC_OVFL);
+		return 0;
+	}
+	reg->lowmant = (reg->mant.m32[1] << 7) | (reg->lowmant ? 1 : 0);
+	reg->mant.m32[1] = (reg->mant.m32[1] >> 1) |
+			   (reg->mant.m32[0] << 31);
+	reg->mant.m32[0] = (reg->mant.m32[0] >> 1) | 0x80000000;
+
+	return 1;
+}
+
+extern inline void fp_submant(struct fp_ext *dest, struct fp_ext *src1, struct fp_ext *src2)
+{
+	/* we assume here, gcc only insert move and a clr instr */
+	asm volatile ("sub.b %1,%0" : "=d,=g" (dest->lowmant)
+		: "g,d" (src2->lowmant), "0,0" (src1->lowmant));
+	asm volatile ("subx.l %1,%0" : "=d" (dest->mant.m32[1])
+		: "d" (src2->mant.m32[1]), "0" (src1->mant.m32[1]));
+	asm volatile ("subx.l %1,%0" : "=d" (dest->mant.m32[0])
+		: "d" (src2->mant.m32[0]), "0" (src1->mant.m32[0]));
+}
+
+#define fp_mul64(desth, destl, src1, src2) ({				\
+	asm ("mulu.l %2,%1:%0" : "=d" (destl), "=d" (desth)		\
+		: "g" (src1), "0" (src2));				\
+})
+#define fp_div64(quot, rem, srch, srcl, div)				\
+	asm ("divu.l %2,%1:%0" : "=d" (quot), "=d" (rem)		\
+		: "dm" (div), "1" (srch), "0" (srcl))
+#define fp_add64(dest1, dest2, src1, src2) ({				\
+	asm ("add.l %1,%0" : "=d,=dm" (dest2)				\
+		: "dm,d" (src2), "0,0" (dest2));			\
+	asm ("addx.l %1,%0" : "=d" (dest1)				\
+		: "d" (src1), "0" (dest1));				\
+})
+#define fp_addx96(dest, src) ({						\
+	/* we assume here, gcc only insert move and a clr instr */	\
+	asm volatile ("add.l %1,%0" : "=d,=g" (dest->m32[2])		\
+		: "g,d" (temp.m32[1]), "0,0" (dest->m32[2]));		\
+	asm volatile ("addx.l %1,%0" : "=d" (dest->m32[1])		\
+		: "d" (temp.m32[0]), "0" (dest->m32[1]));		\
+	asm volatile ("addx.l %1,%0" : "=d" (dest->m32[0])		\
+		: "d" (0), "0" (dest->m32[0]));				\
+})
+#define fp_sub64(dest, src) ({						\
+	asm ("sub.l %1,%0" : "=d,=dm" (dest.m32[1])			\
+		: "dm,d" (src.m32[1]), "0,0" (dest.m32[1]));		\
+	asm ("subx.l %1,%0" : "=d" (dest.m32[0])			\
+		: "d" (src.m32[0]), "0" (dest.m32[0]));			\
+})
+#define fp_sub96c(dest, srch, srcm, srcl) ({				\
+	char carry;							\
+	asm ("sub.l %1,%0" : "=d,=dm" (dest.m32[2])			\
+		: "dm,d" (srcl), "0,0" (dest.m32[2]));			\
+	asm ("subx.l %1,%0" : "=d" (dest.m32[1])			\
+		: "d" (srcm), "0" (dest.m32[1]));			\
+	asm ("subx.l %2,%1; scs %0" : "=d" (carry), "=d" (dest.m32[0])	\
+		: "d" (srch), "1" (dest.m32[0]));			\
+	carry;								\
+})
+
+extern inline void fp_multiplymant(union fp_mant128 *dest, struct fp_ext *src1, struct fp_ext *src2)
+{
+	union fp_mant64 temp;
+
+	fp_mul64(dest->m32[0], dest->m32[1], src1->mant.m32[0], src2->mant.m32[0]);
+	fp_mul64(dest->m32[2], dest->m32[3], src1->mant.m32[1], src2->mant.m32[1]);
+
+	fp_mul64(temp.m32[0], temp.m32[1], src1->mant.m32[0], src2->mant.m32[1]);
+	fp_addx96(dest, temp);
+
+	fp_mul64(temp.m32[0], temp.m32[1], src1->mant.m32[1], src2->mant.m32[0]);
+	fp_addx96(dest, temp);
+}
+
+extern inline void fp_dividemant(union fp_mant128 *dest, struct fp_ext *src, struct fp_ext *div)
+{
+	union fp_mant128 tmp;
+	union fp_mant64 tmp64;
+	unsigned long *mantp = dest->m32;
+	unsigned long fix, rem, first, dummy;
+	int i;
+
+	/* the algorithm below requires dest to be smaller than div,
+	   but both have the high bit set */
+	if (src->mant.m64 >= div->mant.m64) {
+		fp_sub64(src->mant, div->mant);
+		*mantp = 1;
+	} else
+		*mantp = 0;
+	mantp++;
+
+	/* basic idea behind this algorithm: we can't divide two 64bit numbers
+	   (AB/CD) directly, but we can calculate AB/C0, but this means this
+	   quotient is off by C0/CD, so we have to multiply the first result
+	   to fix the result, after that we have nearly the correct result
+	   and only a few corrections are needed. */
+
+	/* C0/CD can be precalculated, but it's an 64bit division again, but
+	   we can make it a bit easier, by dividing first through C so we get
+	   10/1D and now only a single shift and the value fits into 32bit. */
+	fix = 0x80000000;
+	dummy = div->mant.m32[1] / div->mant.m32[0] + 1;
+	dummy = (dummy >> 1) | fix;
+	fp_div64(fix, dummy, fix, 0, dummy);
+	fix--;
+
+	for (i = 0; i < 3; i++, mantp++) {
+		if (src->mant.m32[0] == div->mant.m32[0]) {
+			fp_div64(first, rem, 0, src->mant.m32[1], div->mant.m32[0]);
+
+			fp_mul64(*mantp, dummy, first, fix);
+			*mantp += fix;
+		} else {
+			fp_div64(first, rem, src->mant.m32[0], src->mant.m32[1], div->mant.m32[0]);
+
+			fp_mul64(*mantp, dummy, first, fix);
+		}
+
+		fp_mul64(tmp.m32[0], tmp.m32[1], div->mant.m32[0], first - *mantp);
+		fp_add64(tmp.m32[0], tmp.m32[1], 0, rem);
+		tmp.m32[2] = 0;
+
+		fp_mul64(tmp64.m32[0], tmp64.m32[1], *mantp, div->mant.m32[1]);
+		fp_sub96c(tmp, 0, tmp64.m32[0], tmp64.m32[1]);
+
+		src->mant.m32[0] = tmp.m32[1];
+		src->mant.m32[1] = tmp.m32[2];
+
+		while (!fp_sub96c(tmp, 0, div->mant.m32[0], div->mant.m32[1])) {
+			src->mant.m32[0] = tmp.m32[1];
+			src->mant.m32[1] = tmp.m32[2];
+			*mantp += 1;
+		}
+	}
+}
+
+#if 0
+extern inline unsigned int fp_fls128(union fp_mant128 *src)
+{
+	unsigned long data;
+	unsigned int res, off;
+
+	if ((data = src->m32[0]))
+		off = 0;
+	else if ((data = src->m32[1]))
+		off = 32;
+	else if ((data = src->m32[2]))
+		off = 64;
+	else if ((data = src->m32[3]))
+		off = 96;
+	else
+		return 128;
+
+	asm ("bfffo %1{#0,#32},%0" : "=d" (res) : "dm" (data));
+	return res + off;
+}
+
+extern inline void fp_shiftmant128(union fp_mant128 *src, int shift)
+{
+	unsigned long sticky;
+
+	switch (shift) {
+	case 0:
+		return;
+	case 1:
+		asm volatile ("lsl.l #1,%0"
+			: "=d" (src->m32[3]) : "0" (src->m32[3]));
+		asm volatile ("roxl.l #1,%0"
+			: "=d" (src->m32[2]) : "0" (src->m32[2]));
+		asm volatile ("roxl.l #1,%0"
+			: "=d" (src->m32[1]) : "0" (src->m32[1]));
+		asm volatile ("roxl.l #1,%0"
+			: "=d" (src->m32[0]) : "0" (src->m32[0]));
+		return;
+	case 2 ... 31:
+		src->m32[0] = (src->m32[0] << shift) | (src->m32[1] >> (32 - shift));
+		src->m32[1] = (src->m32[1] << shift) | (src->m32[2] >> (32 - shift));
+		src->m32[2] = (src->m32[2] << shift) | (src->m32[3] >> (32 - shift));
+		src->m32[3] = (src->m32[3] << shift);
+		return;
+	case 32 ... 63:
+		shift -= 32;
+		src->m32[0] = (src->m32[1] << shift) | (src->m32[2] >> (32 - shift));
+		src->m32[1] = (src->m32[2] << shift) | (src->m32[3] >> (32 - shift));
+		src->m32[2] = (src->m32[3] << shift);
+		src->m32[3] = 0;
+		return;
+	case 64 ... 95:
+		shift -= 64;
+		src->m32[0] = (src->m32[2] << shift) | (src->m32[3] >> (32 - shift));
+		src->m32[1] = (src->m32[3] << shift);
+		src->m32[2] = src->m32[3] = 0;
+		return;
+	case 96 ... 127:
+		shift -= 96;
+		src->m32[0] = (src->m32[3] << shift);
+		src->m32[1] = src->m32[2] = src->m32[3] = 0;
+		return;
+	case -31 ... -1:
+		shift = -shift;
+		sticky = 0;
+		if (src->m32[3] << (32 - shift))
+			sticky = 1;
+		src->m32[3] = (src->m32[3] >> shift) | (src->m32[2] << (32 - shift)) | sticky;
+		src->m32[2] = (src->m32[2] >> shift) | (src->m32[1] << (32 - shift));
+		src->m32[1] = (src->m32[1] >> shift) | (src->m32[0] << (32 - shift));
+		src->m32[0] = (src->m32[0] >> shift);
+		return;
+	case -63 ... -32:
+		shift = -shift - 32;
+		sticky = 0;
+		if ((src->m32[2] << (32 - shift)) || src->m32[3])
+			sticky = 1;
+		src->m32[3] = (src->m32[2] >> shift) | (src->m32[1] << (32 - shift)) | sticky;
+		src->m32[2] = (src->m32[1] >> shift) | (src->m32[0] << (32 - shift));
+		src->m32[1] = (src->m32[0] >> shift);
+		src->m32[0] = 0;
+		return;
+	case -95 ... -64:
+		shift = -shift - 64;
+		sticky = 0;
+		if ((src->m32[1] << (32 - shift)) || src->m32[2] || src->m32[3])
+			sticky = 1;
+		src->m32[3] = (src->m32[1] >> shift) | (src->m32[0] << (32 - shift)) | sticky;
+		src->m32[2] = (src->m32[0] >> shift);
+		src->m32[1] = src->m32[0] = 0;
+		return;
+	case -127 ... -96:
+		shift = -shift - 96;
+		sticky = 0;
+		if ((src->m32[0] << (32 - shift)) || src->m32[1] || src->m32[2] || src->m32[3])
+			sticky = 1;
+		src->m32[3] = (src->m32[0] >> shift) | sticky;
+		src->m32[2] = src->m32[1] = src->m32[0] = 0;
+		return;
+	}
+
+	if (shift < 0 && (src->m32[0] || src->m32[1] || src->m32[2] || src->m32[3]))
+		src->m32[3] = 1;
+	else
+		src->m32[3] = 0;
+	src->m32[2] = 0;
+	src->m32[1] = 0;
+	src->m32[0] = 0;
+}
+#endif
+
+extern inline void fp_putmant128(struct fp_ext *dest, union fp_mant128 *src, int shift)
+{
+	unsigned long tmp;
+
+	switch (shift) {
+	case 0:
+		dest->mant.m64 = src->m64[0];
+		dest->lowmant = src->m32[2] >> 24;
+		if (src->m32[3] || (src->m32[2] << 8))
+			dest->lowmant |= 1;
+		break;
+	case 1:
+		asm volatile ("lsl.l #1,%0"
+			: "=d" (tmp) : "0" (src->m32[2]));
+		asm volatile ("roxl.l #1,%0"
+			: "=d" (dest->mant.m32[1]) : "0" (src->m32[1]));
+		asm volatile ("roxl.l #1,%0"
+			: "=d" (dest->mant.m32[0]) : "0" (src->m32[0]));
+		dest->lowmant = tmp >> 24;
+		if (src->m32[3] || (tmp << 8))
+			dest->lowmant |= 1;
+		break;
+	case 31:
+		asm volatile ("lsr.l #1,%1; roxr.l #1,%0"
+			: "=d" (dest->mant.m32[0])
+			: "d" (src->m32[0]), "0" (src->m32[1]));
+		asm volatile ("roxr.l #1,%0"
+			: "=d" (dest->mant.m32[1]) : "0" (src->m32[2]));
+		asm volatile ("roxr.l #1,%0"
+			: "=d" (tmp) : "0" (src->m32[3]));
+		dest->lowmant = tmp >> 24;
+		if (src->m32[3] << 7)
+			dest->lowmant |= 1;
+		break;
+	case 32:
+		dest->mant.m32[0] = src->m32[1];
+		dest->mant.m32[1] = src->m32[2];
+		dest->lowmant = src->m32[3] >> 24;
+		if (src->m32[3] << 8)
+			dest->lowmant |= 1;
+		break;
+	}
+}
+
+#if 0 /* old code... */
+extern inline int fls(unsigned int a)
+{
+	int r;
+
+	asm volatile ("bfffo %1{#0,#32},%0"
+		      : "=d" (r) : "md" (a));
+	return r;
+}
+
+/* fls = "find last set" (cf. ffs(3)) */
+extern inline int fls128(const int128 a)
+{
+	if (a[MSW128])
+		return fls(a[MSW128]);
+	if (a[NMSW128])
+		return fls(a[NMSW128]) + 32;
+	/* XXX: it probably never gets beyond this point in actual
+	   use, but that's indicative of a more general problem in the
+	   algorithm (i.e. as per the actual 68881 implementation, we
+	   really only need at most 67 bits of precision [plus
+	   overflow]) so I'm not going to fix it. */
+	if (a[NLSW128])
+		return fls(a[NLSW128]) + 64;
+	if (a[LSW128])
+		return fls(a[LSW128]) + 96;
+	else
+		return -1;
+}
+
+extern inline int zerop128(const int128 a)
+{
+	return !(a[LSW128] | a[NLSW128] | a[NMSW128] | a[MSW128]);
+}
+
+extern inline int nonzerop128(const int128 a)
+{
+	return (a[LSW128] | a[NLSW128] | a[NMSW128] | a[MSW128]);
+}
+
+/* Addition and subtraction */
+/* Do these in "pure" assembly, because "extended" asm is unmanageable
+   here */
+extern inline void add128(const int128 a, int128 b)
+{
+	/* rotating carry flags */
+	unsigned int carry[2];
+
+	carry[0] = a[LSW128] > (0xffffffff - b[LSW128]);
+	b[LSW128] += a[LSW128];
+
+	carry[1] = a[NLSW128] > (0xffffffff - b[NLSW128] - carry[0]);
+	b[NLSW128] = a[NLSW128] + b[NLSW128] + carry[0];
+
+	carry[0] = a[NMSW128] > (0xffffffff - b[NMSW128] - carry[1]);
+	b[NMSW128] = a[NMSW128] + b[NMSW128] + carry[1];
+
+	b[MSW128] = a[MSW128] + b[MSW128] + carry[0];
+}
+
+/* Note: assembler semantics: "b -= a" */
+extern inline void sub128(const int128 a, int128 b)
+{
+	/* rotating borrow flags */
+	unsigned int borrow[2];
+
+	borrow[0] = b[LSW128] < a[LSW128];
+	b[LSW128] -= a[LSW128];
+
+	borrow[1] = b[NLSW128] < a[NLSW128] + borrow[0];
+	b[NLSW128] = b[NLSW128] - a[NLSW128] - borrow[0];
+
+	borrow[0] = b[NMSW128] < a[NMSW128] + borrow[1];
+	b[NMSW128] = b[NMSW128] - a[NMSW128] - borrow[1];
+
+	b[MSW128] = b[MSW128] - a[MSW128] - borrow[0];
+}
+
+/* Poor man's 64-bit expanding multiply */
+extern inline void mul64(unsigned long long a,
+		  unsigned long long b,
+		  int128 c)
+{
+	unsigned long long acc;
+	int128 acc128;
+
+	zero128(acc128);
+	zero128(c);
+
+	/* first the low words */
+	if (LO_WORD(a) && LO_WORD(b)) {
+		acc = (long long) LO_WORD(a) * LO_WORD(b);
+		c[NLSW128] = HI_WORD(acc);
+		c[LSW128] = LO_WORD(acc);
+	}
+	/* Next the high words */
+	if (HI_WORD(a) && HI_WORD(b)) {
+		acc = (long long) HI_WORD(a) * HI_WORD(b);
+		c[MSW128] = HI_WORD(acc);
+		c[NMSW128] = LO_WORD(acc);
+	}
+	/* The middle words */
+	if (LO_WORD(a) && HI_WORD(b)) {
+		acc = (long long) LO_WORD(a) * HI_WORD(b);
+		acc128[NMSW128] = HI_WORD(acc);
+		acc128[NLSW128] = LO_WORD(acc);
+		add128(acc128, c);
+	}
+	/* The first and last words */
+	if (HI_WORD(a) && LO_WORD(b)) {
+		acc = (long long) HI_WORD(a) * LO_WORD(b);
+		acc128[NMSW128] = HI_WORD(acc);
+		acc128[NLSW128] = LO_WORD(acc);
+		add128(acc128, c);
+	}
+}
+
+/* Note: unsigned */
+extern inline int cmp128(int128 a, int128 b)
+{
+	if (a[MSW128] < b[MSW128])
+		return -1;
+	if (a[MSW128] > b[MSW128])
+		return 1;
+	if (a[NMSW128] < b[NMSW128])
+		return -1;
+	if (a[NMSW128] > b[NMSW128])
+		return 1;
+	if (a[NLSW128] < b[NLSW128])
+		return -1;
+	if (a[NLSW128] > b[NLSW128])
+		return 1;
+
+	return (signed) a[LSW128] - b[LSW128];
+}
+
+inline void div128(int128 a, int128 b, int128 c)
+{
+	int128 mask;
+
+	/* Algorithm:
+
+	   Shift the divisor until it's at least as big as the
+	   dividend, keeping track of the position to which we've
+	   shifted it, i.e. the power of 2 which we've multiplied it
+	   by.
+
+	   Then, for this power of 2 (the mask), and every one smaller
+	   than it, subtract the mask from the dividend and add it to
+	   the quotient until the dividend is smaller than the raised
+	   divisor.  At this point, divide the dividend and the mask
+	   by 2 (i.e. shift one place to the right).  Lather, rinse,
+	   and repeat, until there are no more powers of 2 left. */
+
+	/* FIXME: needless to say, there's room for improvement here too. */
+
+	/* Shift up */
+	/* XXX: since it just has to be "at least as big", we can
+	   probably eliminate this horribly wasteful loop.  I will
+	   have to prove this first, though */
+	set128(0, 0, 0, 1, mask);
+	while (cmp128(b, a) < 0 && !btsthi128(b)) {
+		lslone128(b);
+		lslone128(mask);
+	}
+
+	/* Shift down */
+	zero128(c);
+	do {
+		if (cmp128(a, b) >= 0) {
+			sub128(b, a);
+			add128(mask, c);
+		}
+		lsrone128(mask);
+		lsrone128(b);
+	} while (nonzerop128(mask));
+
+	/* The remainder is in a... */
+}
+#endif
+
+#endif	/* MULTI_ARITH_H */
diff -u --recursive --new-file v2.3.13/linux/arch/m68k/q40/README linux/arch/m68k/q40/README
--- v2.3.13/linux/arch/m68k/q40/README	Tue May 11 09:57:14 1999
+++ linux/arch/m68k/q40/README	Sun Aug 15 11:47:29 1999
@@ -7,7 +7,7 @@
 and mirrors.
 
 Hints to documentation usually refer to the linux source tree in
-/usr/src/linux unless URL given.
+/usr/src/linux/Documentation unless URL given.
 
 It seems IRQ unmasking can't be safely done on a Q40. Autoprobing is 
 not yet implemented - do not try it! (See below)
@@ -18,8 +18,8 @@
 The floppy imposes a very high interrupt load on the CPU, approx 30K/s.
 When something blocks interrupts (HD) it will loose some of them, so far 
 this is not known to have caused any data loss. On hihgly loaded systems
-it can make the floppy very slow. Other Q40 OS' simply poll the floppy
-for this reason - something that can't be done in Linux.
+it can make the floppy very slow or practicaly stop. Other Q40 OS' simply 
+poll the floppy for this reason - something that can't be done in Linux.
 Only possible cure is getting a 82072 contoler with fifo instead of 
 the 8272A
 
@@ -48,7 +48,7 @@
 Upon startup the kernel will usually output "ABCQGHIJ" into the SRAM, 
 preceded by the booter signature. This is a trace just in case something 
 went wrong during earliest setup stages. 
-*Changed* to preserve SRAM contents by default, this is only done when 
+**Changed** to preserve SRAM contents by default, this is only done when 
 requested - SRAM must start with '%LX$' signature to do this. '-d' option 
 to 'lxx' loader enables this.
 
@@ -92,12 +92,22 @@
 ==========
 
 q40 master chip handles only level triggered interrupts :-((
-further limitation is no disabling etc. Unless someone finds 
-some ingenious clue this means autoprobing will never work.
-Parallel port interrupts cause most trouble..
-
-IRQ sharing is not yet implemented.
-
+further limitation is no disabling etc. There is NO WAY to remove
+an ISA irq request other than serve the HW specific control register,
+the ISA irq lines are connected straight to the CPU ipl1 pin..
+
+IRQ sharing is not yet implemented but this should be only a minor
+problem..
+
+Linux has some requirements wrt interrupt architecture, these are
+to my knowledge:
+	(a) interrupt handler must not be reentered even when sti() is called
+	(b) working enable/disable_irq
+
+Luckily these requirements are only important for drivers shared
+with other architectures - ide,serial,parallel, ethernet..
+q40ints.c now contains a trivial hack for (a), however (b) could
+be only solved by driver-specific code
 
 Keyboard
 ========
diff -u --recursive --new-file v2.3.13/linux/arch/m68k/q40/config.c linux/arch/m68k/q40/config.c
--- v2.3.13/linux/arch/m68k/q40/config.c	Mon Aug  9 14:59:19 1999
+++ linux/arch/m68k/q40/config.c	Sun Aug 15 11:47:29 1999
@@ -1,12 +1,12 @@
 /*
  *  arch/m68k/q40/config.c
  *
+ *  Copyright (C) 1999 Richard Zidlicky
+ *
  * originally based on:
  *
  *  linux/bvme/config.c
  *
- *  Copyright (C) 1993 Hamish Macdonald
- *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file README.legal in the main directory of this archive
  * for more details.
@@ -23,6 +23,7 @@
 #include <linux/init.h>
 #include <linux/major.h>
 
+#include <asm/rtc.h>
 #include <asm/bootinfo.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
@@ -134,12 +135,11 @@
 void q40_reset()
 {
 
-	printk ("\n\n*******************************************\n"
-                     "Called q40_reset : press the RESET button!! \n");
-	printk(     "*******************************************\n");
-
-	while(1)
-		;
+        printk ("\n\n*******************************************\n"
+		"Called q40_reset : press the RESET button!! \n"
+		"*******************************************\n");
+	
+	while(1) ;
 }
 
 static void q40_get_model(char *model)
@@ -232,6 +232,9 @@
 }
 
 static void (*q40_timer_routine)(int, void *, struct pt_regs *);
+static short rtc_oldsecs=0;
+unsigned rtc_irq_flags=0;
+unsigned rtc_irq_ctrl=0;
 
 static void q40_timer_int (int irq, void *dev_id, struct pt_regs *fp)
 {
@@ -250,6 +253,14 @@
 	*DAC_LEFT=sval;
 	*DAC_RIGHT=sval;
       }
+#ifdef CONFIG_Q40RTC
+    if (rtc_irq_ctrl && (rtc_oldsecs != RTC_SECS))
+      {
+	rtc_oldsecs = RTC_SECS;
+	rtc_irq_flags = RTC_UIE;
+	rtc_interrupt();
+      }
+#endif
     if (ql_ticks) return;
 #endif
     q40_timer_routine(irq, dev_id, fp);
diff -u --recursive --new-file v2.3.13/linux/arch/m68k/q40/q40ints.c linux/arch/m68k/q40/q40ints.c
--- v2.3.13/linux/arch/m68k/q40/q40ints.c	Tue May 11 09:57:14 1999
+++ linux/arch/m68k/q40/q40ints.c	Tue Aug 17 10:39:32 1999
@@ -29,7 +29,7 @@
  *            3,4,5,6,7,10,11,14,15 : ISA dev IRQs
  *            16-31: reserved
  *            32   : keyboard int
- *            33   : frame int (50 Hz periodic timer)
+ *            33   : frame int (50/200 Hz periodic timer)
  *            34   : sample int (10/20 KHz periodic timer)
  *          
 */
@@ -45,20 +45,21 @@
 static void q40_defhand (int irq, void *dev_id, struct pt_regs *fp);
 static void sys_default_handler(int lev, void *dev_id, struct pt_regs *regs);
 
-/*
- * This should ideally be 4 elements only, for speed.
- */
 
 #define DEVNAME_SIZE 24
 
-static struct {
+static struct q40_irq_node {
 	void		(*handler)(int, void *, struct pt_regs *);
 	unsigned long	flags;
 	void		*dev_id;
+  /*        struct q40_irq_node *next;*/
         char	        devname[DEVNAME_SIZE];
 	unsigned	count;
+        unsigned short  state;
 } irq_tab[Q40_IRQ_MAX+1];
 
+short unsigned q40_ablecount[Q40_IRQ_MAX+1];
+
 /*
  * void q40_init_IRQ (void)
  *
@@ -78,8 +79,11 @@
 		irq_tab[i].handler = q40_defhand;
 		irq_tab[i].flags = IRQ_FLG_STD;
 		irq_tab[i].dev_id = NULL;
+		/*		irq_tab[i].next = NULL;*/
 		irq_tab[i].devname[0] = 0;
 		irq_tab[i].count = 0;
+		irq_tab[i].state =0;
+		q40_ablecount[i]=0;   /* all enabled */
 	}
 
 	/* setup handler for ISA ints */
@@ -108,23 +112,20 @@
 	}
 
 	/* test for ISA ints not implemented by HW */
-	if (irq<15) 
+	switch (irq)
 	  {
-	    switch (irq){
-	    case 1: case 2: case 8: case 9:
-	    case 12: case 13:
-	      printk("%s: ISA IRQ %d from %s not implemented by HW\n", __FUNCTION__, irq, devname);
-	      return -ENXIO;
-	    default:
-	    }
+	  case 1: case 2: case 8: case 9:
+	  case 12: case 13:
+	    printk("%s: ISA IRQ %d from %s not implemented by HW\n", __FUNCTION__, irq, devname);
+	    return -ENXIO;
+	  case 11: 	      
+	    printk("warning IRQ 10 and 11 not distinguishable\n");
+	    irq=10;
+	  default:
 	  }
 
 	if (irq<Q40_IRQ_TIMER)
 	  {
-	    if (irq==11) {
-	      printk("warning IRQ 10 and 11 not distinguishable\n");
-	      irq=10;
-	    }
 	    if (!(irq_tab[irq].flags & IRQ_FLG_STD)) 
 	      {
 		if (irq_tab[irq].flags & IRQ_FLG_LOCK) 
@@ -145,6 +146,7 @@
 	    irq_tab[irq].flags   = flags;
 	    irq_tab[irq].dev_id  = dev_id;
 	    strncpy(irq_tab[irq].devname,devname,DEVNAME_SIZE);
+	    irq_tab[irq].state = 0;
 	    return 0;
 	  }
 	else {
@@ -163,30 +165,33 @@
 	}
 
 	/* test for ISA ints not implemented by HW */
-	if (irq<15) {
-	  switch (irq){
+	switch (irq)
+	  {
 	  case 1: case 2: case 8: case 9:
 	  case 12: case 13:
-	        printk("%s: ISA IRQ %d from %x illegal\n", __FUNCTION__, irq, (unsigned)dev_id);
-		return;
+	    printk("%s: ISA IRQ %d from %x illegal\n", __FUNCTION__, irq, (unsigned)dev_id);
+	    return;
+	  case 11: irq=10;
 	  default:
-		  }
-	}
+	  }
 	
-	if (irq<Q40_IRQ_TIMER){
-	  if (irq==11) irq=10;
-	  if (irq_tab[irq].dev_id != dev_id)
-	    printk("%s: Removing probably wrong IRQ %d from %s\n",
-		   __FUNCTION__, irq, irq_tab[irq].devname);
-	  
-	  irq_tab[irq].handler = q40_defhand;
-	  irq_tab[irq].flags   = IRQ_FLG_STD;
-	  irq_tab[irq].dev_id  = NULL;
-	  /* irq_tab[irq].devname = NULL; */
-	} else { /* == Q40_IRQ_TIMER */
-	  sys_free_irq(4,dev_id);
-	  sys_free_irq(6,dev_id);
-	}
+	if (irq<Q40_IRQ_TIMER)
+	  {
+	    if (irq_tab[irq].dev_id != dev_id)
+	      printk("%s: Removing probably wrong IRQ %d from %s\n",
+		     __FUNCTION__, irq, irq_tab[irq].devname);
+	    
+	    irq_tab[irq].handler = q40_defhand;
+	    irq_tab[irq].flags   = IRQ_FLG_STD;
+	    irq_tab[irq].dev_id  = NULL;
+	    /* irq_tab[irq].devname = NULL; */
+	    /* do not reset state !! */
+	  }
+	else
+	  { /* == Q40_IRQ_TIMER */
+	    sys_free_irq(4,dev_id);
+	    sys_free_irq(6,dev_id);
+	  }
 }
 
 #if 1
@@ -224,11 +229,16 @@
 
   {0,0}};
 
-/* complaiun only this many times about spurious ints : */
+/* complain only this many times about spurious ints : */
 static int ccleirq=60;    /* ISA dev IRQ's*/
 static int cclirq=60;     /* internal */
 
-/* FIX: add IRQ_INPROGRESS,mask,unmask,probing.... */
+/* FIX: add shared ints,mask,unmask,probing.... */
+
+/* this is an awfull hack.. */
+#define IRQ_INPROGRESS 1
+static int disabled=0;
+/*static unsigned short saved_mask;*/
 
 void q40_irq2_handler (int vec, void *devname, struct pt_regs *fp)
 {
@@ -238,11 +248,6 @@
 	unsigned mer;
 	int irq,i;
 
-	/*
-	 *  more than 1 bit might be set, must handle atmost 1 int source,
-	 *  - handle only those with explicitly set handler
-	 */
-
 	if ((mir&IRQ_SER_MASK) || (mir&IRQ_EXT_MASK)) 
 	  {
 	    
@@ -257,9 +262,37 @@
 		    irq=eirqs[i].irq;
 		    irq_tab[irq].count++;
 		    if (irq_tab[irq].handler == q40_defhand )
-		      continue; /* ignore uninited INTs :-( */
-		    
+		      {
+			printk("handler for IRQ %d not defined\n",irq);
+			continue; /* ignore uninited INTs :-( */
+		      }
+
+		    if ( irq_tab[irq].state & IRQ_INPROGRESS )
+		      {
+			/*printk("IRQ_INPROGRESS detected for irq %d, disabling - %s disabled\n",irq,disabled ? "already" : "not yet"); */
+
+			/*saved_mask = fp->sr;*/
+			fp->sr = (fp->sr & (~0x700))+0x200;
+			disabled=1;
+			return;
+		      }
+		    irq_tab[irq].state |= IRQ_INPROGRESS;
 		    irq_tab[irq].handler(irq,irq_tab[irq].dev_id,fp);
+
+		    /* naively enable everything, if that fails than    */
+		    /* this function will be reentered immediately thus */
+		    /* getting another chance to disable the IRQ        */
+
+		    irq_tab[irq].state &= ~IRQ_INPROGRESS;
+		    if ( disabled ) 
+		      {
+			/*printk("reenabling irq %d\n",irq); */
+			fp->sr = (fp->sr & (~0x700)); /*saved_mask; */
+			disabled=0;
+		      }
+		    else if ( fp->sr &0x200 )
+		      printk("exiting irq handler: fp->sr &0x200 !!\n");
+
 		    return;
 		  }
 	      }
@@ -279,7 +312,17 @@
 		    if (irq_tab[irq].handler == q40_defhand )
 		      continue; /* ignore uninited INTs :-( */
 		    
+		    /* the INPROGRESS stuff should be completely useless*/
+		    /* for internal ints, nevertheless test it..*/
+		    if ( irq_tab[irq].state & IRQ_INPROGRESS )
+		      {
+			/*disable_irq(irq);
+			  return;*/
+			printk("rentering handler for IRQ %d !!\n",irq);
+		      }
 		    irq_tab[irq].handler(irq,irq_tab[irq].dev_id,fp);
+		    irq_tab[irq].state &= ~IRQ_INPROGRESS;
+		    /*enable_irq(irq);*/ /* better not try luck !*/
 		    return;
 		  }
 	      }
@@ -327,19 +370,59 @@
    sys_default_handler,sys_default_handler,sys_default_handler,sys_default_handler
  };
 
+int irq_disabled=0;
 void q40_enable_irq (unsigned int irq)
 {
+  /* enable ISA iqs */
+  if ( irq>=0 && irq<=15 ) /* the moderately bad case */
+    master_outb(1,EXT_ENABLE_REG);
+#if 0
+  unsigned long flags;
+  int i;
+
+  if (irq>=10 && irq <= 15)
+    {
+      if ( !(--q40_ablecount[irq]))
+	for (i=10,irq_disabled=0; i<=15; i++)
+	  {
+	    irq_disabled |= (q40_ablecount[irq] !=0);
+	  }
+      if ( !irq_disabled )
+	{
+	  save_flags(flags);
+	  restore_flags(flags & (~0x700));
+	}
+    }
+#endif
 }
 
 
 void q40_disable_irq (unsigned int irq)
 {
+  /* disable ISA iqs : only do something if the driver has been
+  * verified to be Q40 "compatible" - right now only IDE
+  * Any driver should not attempt to sleep accross disable_irq !!
+  */
+
+  if ( irq>=10 && irq<=15 ) /* the moderately bad case */
+    master_outb(0,EXT_ENABLE_REG);
+#if 0
+  unsigned long flags;
+
+  if (irq>=10 && irq <= 15)
+    {
+      save_flags(flags);
+      restore_flags(flags | 0x200 );
+      irq_disabled=1;
+      q40_ablecount[irq]++;
+    }
+#endif
 }
 
 unsigned long q40_probe_irq_on (void)
 {
-  printk("sorry, irq probing not yet implemented - reconfigure the driver to avoid this\n");
-  return 0;
+  printk("irq probing not working - reconfigure the driver to avoid this\n");
+  return -1;
 }
 int q40_probe_irq_off (unsigned long irqs)
 {
diff -u --recursive --new-file v2.3.13/linux/arch/ppc/8xx_io/enet.c linux/arch/ppc/8xx_io/enet.c
--- v2.3.13/linux/arch/ppc/8xx_io/enet.c	Fri Apr 16 08:20:23 1999
+++ linux/arch/ppc/8xx_io/enet.c	Wed Aug 18 11:39:01 1999
@@ -152,13 +152,13 @@
 	unsigned long lock;
 };
 
-static int cpm_enet_open(struct device *dev);
-static int cpm_enet_start_xmit(struct sk_buff *skb, struct device *dev);
-static int cpm_enet_rx(struct device *dev);
+static int cpm_enet_open(struct net_device *dev);
+static int cpm_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int cpm_enet_rx(struct net_device *dev);
 static void cpm_enet_interrupt(void *dev_id);
-static int cpm_enet_close(struct device *dev);
-static struct net_device_stats *cpm_enet_get_stats(struct device *dev);
-static void set_multicast_list(struct device *dev);
+static int cpm_enet_close(struct net_device *dev);
+static struct net_device_stats *cpm_enet_get_stats(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
 
 /* Get this from various configuration locations (depends on board).
 */
@@ -181,7 +181,7 @@
 #endif
 
 static int
-cpm_enet_open(struct device *dev)
+cpm_enet_open(struct net_device *dev)
 {
 
 	/* I should reset the ring buffers here, but I don't yet know
@@ -196,7 +196,7 @@
 }
 
 static int
-cpm_enet_start_xmit(struct sk_buff *skb, struct device *dev)
+cpm_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct cpm_enet_private *cep = (struct cpm_enet_private *)dev->priv;
 	volatile cbd_t	*bdp;
@@ -326,7 +326,7 @@
 static void
 cpm_enet_interrupt(void *dev_id)
 {
-	struct	device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	volatile struct	cpm_enet_private *cep;
 	volatile cbd_t	*bdp;
 	ushort	int_events;
@@ -503,7 +503,7 @@
  * effectively tossing the packet.
  */
 static int
-cpm_enet_rx(struct device *dev)
+cpm_enet_rx(struct net_device *dev)
 {
 	struct	cpm_enet_private *cep;
 	volatile cbd_t	*bdp;
@@ -597,7 +597,7 @@
 }
 
 static int
-cpm_enet_close(struct device *dev)
+cpm_enet_close(struct net_device *dev)
 {
 	/* Don't know what to do yet.
 	*/
@@ -605,7 +605,7 @@
 	return 0;
 }
 
-static struct net_device_stats *cpm_enet_get_stats(struct device *dev)
+static struct net_device_stats *cpm_enet_get_stats(struct net_device *dev)
 {
 	struct cpm_enet_private *cep = (struct cpm_enet_private *)dev->priv;
 
@@ -622,7 +622,7 @@
  * this kind of feature?).
  */
 
-static void set_multicast_list(struct device *dev)
+static void set_multicast_list(struct net_device *dev)
 {
 	struct	cpm_enet_private *cep;
 	struct	dev_mc_list *dmi;
@@ -701,7 +701,7 @@
 int __init cpm_enet_init() { m8xx_enet_init(); }
 int __init m8xx_enet_init(void)
 {
-	struct device *dev;
+	struct net_device *dev;
 	struct cpm_enet_private *cep;
 	int i, j;
 	unsigned char	*eap;
diff -u --recursive --new-file v2.3.13/linux/arch/ppc/8xx_io/fec.c linux/arch/ppc/8xx_io/fec.c
--- v2.3.13/linux/arch/ppc/8xx_io/fec.c	Wed Sep 30 10:14:16 1998
+++ linux/arch/ppc/8xx_io/fec.c	Wed Aug 18 11:39:01 1999
@@ -106,14 +106,14 @@
 	unsigned long lock;
 };
 
-static int fec_enet_open(struct device *dev);
-static int fec_enet_start_xmit(struct sk_buff *skb, struct device *dev);
-static int fec_enet_rx(struct device *dev);
-static void fec_enet_mii(struct device *dev);
+static int fec_enet_open(struct net_device *dev);
+static int fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int fec_enet_rx(struct net_device *dev);
+static void fec_enet_mii(struct net_device *dev);
 static	void fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs);
-static int fec_enet_close(struct device *dev);
-static struct net_device_stats *fec_enet_get_stats(struct device *dev);
-static void set_multicast_list(struct device *dev);
+static int fec_enet_close(struct net_device *dev);
+static struct net_device_stats *fec_enet_get_stats(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
 
 static	ushort	my_enet_addr[] = { 0x0800, 0x3e26, 0x1559 };
 
@@ -142,7 +142,7 @@
 						(VAL & 0xffff))
 
 static int
-fec_enet_open(struct device *dev)
+fec_enet_open(struct net_device *dev)
 {
 
 	/* I should reset the ring buffers here, but I don't yet know
@@ -157,7 +157,7 @@
 }
 
 static int
-fec_enet_start_xmit(struct sk_buff *skb, struct device *dev)
+fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct fec_enet_private *fep = (struct fec_enet_private *)dev->priv;
 	volatile cbd_t	*bdp;
@@ -282,7 +282,7 @@
 static	void
 fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
 {
-	struct	device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	struct	fec_enet_private *fep;
 	volatile cbd_t	*bdp;
 	volatile fec_t	*ep;
@@ -393,7 +393,7 @@
  * effectively tossing the packet.
  */
 static int
-fec_enet_rx(struct device *dev)
+fec_enet_rx(struct net_device *dev)
 {
 	struct	fec_enet_private *fep;
 	volatile cbd_t *bdp;
@@ -506,7 +506,7 @@
 }
 
 static void
-fec_enet_mii(struct device *dev)
+fec_enet_mii(struct net_device *dev)
 {
 	struct	fec_enet_private *fep;
 	volatile fec_t	*ep;
@@ -676,7 +676,7 @@
 static	void
 mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs)
 {
-	struct	device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	struct	fec_enet_private *fep;
 	volatile fec_t	*ep;
 
@@ -696,7 +696,7 @@
 }
 
 static int
-fec_enet_close(struct device *dev)
+fec_enet_close(struct net_device *dev)
 {
 	/* Don't know what to do yet.
 	*/
@@ -704,7 +704,7 @@
 	return 0;
 }
 
-static struct net_device_stats *fec_enet_get_stats(struct device *dev)
+static struct net_device_stats *fec_enet_get_stats(struct net_device *dev)
 {
 	struct fec_enet_private *fep = (struct fec_enet_private *)dev->priv;
 
@@ -721,7 +721,7 @@
  * this kind of feature?).
  */
 
-static void set_multicast_list(struct device *dev)
+static void set_multicast_list(struct net_device *dev)
 {
 	struct	fec_enet_private *fep;
 	struct	dev_mc_list *dmi;
@@ -792,7 +792,7 @@
  */
 __initfunc(int m8xx_enet_init(void))
 {
-	struct device *dev;
+	struct net_device *dev;
 	struct fec_enet_private *fep;
 	int i, j;
 	unsigned char	*eap;
diff -u --recursive --new-file v2.3.13/linux/arch/ppc/kernel/smp.c linux/arch/ppc/kernel/smp.c
--- v2.3.13/linux/arch/ppc/kernel/smp.c	Mon Aug  9 14:59:19 1999
+++ linux/arch/ppc/kernel/smp.c	Thu Aug 12 11:50:14 1999
@@ -31,7 +31,6 @@
 #include <asm/spinlock.h>
 #include <asm/hardirq.h>
 #include <asm/softirq.h>
-#include <linux/init.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 
diff -u --recursive --new-file v2.3.13/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c
--- v2.3.13/linux/arch/sparc64/kernel/ioctl32.c	Mon Aug  9 14:59:19 1999
+++ linux/arch/sparc64/kernel/ioctl32.c	Wed Aug 18 11:39:01 1999
@@ -421,7 +421,7 @@
 
 static int dev_ifname32(unsigned int fd, unsigned long arg)
 {
-	struct device *dev;
+	struct net_device *dev;
 	struct ifreq32 ifr32;
 	int err;
 
diff -u --recursive --new-file v2.3.13/linux/arch/sparc64/solaris/ioctl.c linux/arch/sparc64/solaris/ioctl.c
--- v2.3.13/linux/arch/sparc64/solaris/ioctl.c	Mon Aug  9 14:59:19 1999
+++ linux/arch/sparc64/solaris/ioctl.c	Wed Aug 18 11:39:02 1999
@@ -663,7 +663,7 @@
 #endif		
 	case 87: /* SIOCGIFNUM */
 		{
-			struct device *d;
+			struct net_device *d;
 			int i = 0;
 			
 			read_lock_bh(&dev_base_lock);
diff -u --recursive --new-file v2.3.13/linux/drivers/Makefile linux/drivers/Makefile
--- v2.3.13/linux/drivers/Makefile	Wed Jul 28 14:47:42 1999
+++ linux/drivers/Makefile	Mon Aug  9 16:11:33 1999
@@ -7,7 +7,7 @@
 #
 # Note 2! The CFLAGS definitions are now in the main makefile.
 
-SUB_DIRS     := block char net parport sound
+SUB_DIRS     := block char net parport sound misc
 MOD_SUB_DIRS := $(SUB_DIRS)
 ALL_SUB_DIRS := $(SUB_DIRS) pci sgi scsi sbus cdrom isdn pnp i2o \
 				macintosh video dio zorro fc4 usb \
diff -u --recursive --new-file v2.3.13/linux/drivers/acorn/net/ether1.c linux/drivers/acorn/net/ether1.c
--- v2.3.13/linux/drivers/acorn/net/ether1.c	Thu Jun 17 01:11:35 1999
+++ linux/drivers/acorn/net/ether1.c	Wed Aug 18 11:38:59 1999
@@ -85,7 +85,7 @@
 #define ether1_outw(dev, val, addr, type, offset, svflgs) ether1_outw_p (dev, val, addr + (int)(&((type *)0)->offset), svflgs)
 
 static inline unsigned short
-ether1_inw_p (struct device *dev, int addr, int svflgs)
+ether1_inw_p (struct net_device *dev, int addr, int svflgs)
 {
 	unsigned long flags;
 	unsigned short ret;
@@ -101,7 +101,7 @@
 }
 
 static inline void
-ether1_outw_p (struct device *dev, unsigned short val, int addr, int svflgs)
+ether1_outw_p (struct net_device *dev, unsigned short val, int addr, int svflgs)
 {
 	unsigned long flags;
 
@@ -211,7 +211,7 @@
 
 
 static void
-ether1_writebuffer (struct device *dev, void *data, unsigned int start, unsigned int length)
+ether1_writebuffer (struct net_device *dev, void *data, unsigned int start, unsigned int length)
 {
 	unsigned int page, thislen, offset;
 
@@ -233,7 +233,7 @@
 }
 
 static void
-ether1_readbuffer (struct device *dev, void *data, unsigned int start, unsigned int length)
+ether1_readbuffer (struct net_device *dev, void *data, unsigned int start, unsigned int length)
 {
 	unsigned int page, thislen, offset;
 
@@ -255,7 +255,7 @@
 }
 
 __initfunc(static int
-ether1_ramtest (struct device *dev, unsigned char byte))
+ether1_ramtest (struct net_device *dev, unsigned char byte))
 {
 	unsigned char *buffer = kmalloc (BUFFER_SIZE, GFP_KERNEL);
 	int i, ret = BUFFER_SIZE;
@@ -302,14 +302,14 @@
 }
 
 static int
-ether1_reset (struct device *dev)
+ether1_reset (struct net_device *dev)
 {
 	outb (CTRL_RST|CTRL_ACK, REG_CONTROL);
 	return BUS_16;
 }
 
 __initfunc(static int
-ether1_init_2 (struct device *dev))
+ether1_init_2 (struct net_device *dev))
 {
 	int i;
 	dev->mem_start = 0;
@@ -447,7 +447,7 @@
 #define TBD_SIZE	(0x08)
 
 static int
-ether1_init_for_open (struct device *dev)
+ether1_init_for_open (struct net_device *dev)
 {
 	struct ether1_priv *priv = (struct ether1_priv *)dev->priv;
 	int i, status, addr, next, next2;
@@ -613,7 +613,7 @@
 }
 
 __initfunc(static int
-ether1_probe1 (struct device *dev))
+ether1_probe1 (struct net_device *dev))
 {
 	static unsigned int version_printed = 0;
 	struct ether1_priv *priv;
@@ -665,7 +665,7 @@
 /* ------------------------------------------------------------------------- */
 
 __initfunc(static void
-ether1_addr (struct device *dev))
+ether1_addr (struct net_device *dev))
 {
 	int i;
     
@@ -674,7 +674,7 @@
 }
 
 __initfunc(int
-ether1_probe (struct device *dev))
+ether1_probe (struct net_device *dev))
 {
 #ifndef MODULE
 	struct expansion_card *ec;
@@ -702,7 +702,7 @@
 /* ------------------------------------------------------------------------- */
 
 static int
-ether1_txalloc (struct device *dev, int size)
+ether1_txalloc (struct net_device *dev, int size)
 {
 	struct ether1_priv *priv = (struct ether1_priv *)dev->priv;
 	int start, tail;
@@ -728,7 +728,7 @@
 }
 
 static void
-ether1_restart (struct device *dev, char *reason)
+ether1_restart (struct net_device *dev, char *reason)
 {
 	struct ether1_priv *priv = (struct ether1_priv *)dev->priv;
 	priv->stats.tx_errors ++;
@@ -750,7 +750,7 @@
 }
 
 static int
-ether1_open (struct device *dev)
+ether1_open (struct net_device *dev)
 {
 	struct ether1_priv *priv = (struct ether1_priv *)dev->priv;
 
@@ -775,7 +775,7 @@
 }
 
 static int
-ether1_sendpacket (struct sk_buff *skb, struct device *dev)
+ether1_sendpacket (struct sk_buff *skb, struct net_device *dev)
 {
 	struct ether1_priv *priv = (struct ether1_priv *)dev->priv;
 
@@ -860,7 +860,7 @@
 }
 
 static void
-ether1_xmit_done (struct device *dev)
+ether1_xmit_done (struct net_device *dev)
 {
 	struct ether1_priv *priv = (struct ether1_priv *)dev->priv;
 	nop_t nop;
@@ -963,7 +963,7 @@
 }
 
 static void
-ether1_recv_done (struct device *dev)
+ether1_recv_done (struct net_device *dev)
 {
 	struct ether1_priv *priv = (struct ether1_priv *)dev->priv;
 	int status;
@@ -1020,7 +1020,7 @@
 static void
 ether1_interrupt (int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev = (struct device *)dev_id;
+	struct net_device *dev = (struct net_device *)dev_id;
 	struct ether1_priv *priv = (struct ether1_priv *)dev->priv;
 	int status;
 
@@ -1070,7 +1070,7 @@
 }
 
 static int
-ether1_close (struct device *dev)
+ether1_close (struct net_device *dev)
 {
 	ether1_reset (dev);
 
@@ -1085,7 +1085,7 @@
 }
 
 static struct enet_statistics *
-ether1_getstats (struct device *dev)
+ether1_getstats (struct net_device *dev)
 {
 	struct ether1_priv *priv = (struct ether1_priv *)dev->priv;
 	return &priv->stats;
@@ -1099,7 +1099,7 @@
  *			best-effort filtering.
  */
 static void
-ether1_setmulticastlist (struct device *dev)
+ether1_setmulticastlist (struct net_device *dev)
 {
 }
 
@@ -1110,7 +1110,7 @@
 static struct ether_dev {
 	struct expansion_card	*ec;
 	char			name[9];
-	struct device		dev;
+	struct net_device		dev;
 } ether_devs[MAX_ECARDS];
 
 int
diff -u --recursive --new-file v2.3.13/linux/drivers/acorn/net/ether1.h linux/drivers/acorn/net/ether1.h
--- v2.3.13/linux/drivers/acorn/net/ether1.h	Mon Feb 16 15:49:47 1998
+++ linux/drivers/acorn/net/ether1.h	Wed Aug 18 11:38:59 1999
@@ -43,12 +43,12 @@
 	unsigned char restart      : 1;
 };
 
-static int ether1_open (struct device *dev);
-static int ether1_sendpacket (struct sk_buff *skb, struct device *dev);
+static int ether1_open (struct net_device *dev);
+static int ether1_sendpacket (struct sk_buff *skb, struct net_device *dev);
 static void ether1_interrupt (int irq, void *dev_id, struct pt_regs *regs);
-static int ether1_close (struct device *dev);
-static struct enet_statistics *ether1_getstats (struct device *dev);
-static void ether1_setmulticastlist (struct device *dev);
+static int ether1_close (struct net_device *dev);
+static struct enet_statistics *ether1_getstats (struct net_device *dev);
+static void ether1_setmulticastlist (struct net_device *dev);
 
 #define I82586_NULL (-1)
 
diff -u --recursive --new-file v2.3.13/linux/drivers/acorn/net/ether3.c linux/drivers/acorn/net/ether3.c
--- v2.3.13/linux/drivers/acorn/net/ether3.c	Mon Aug  9 14:59:19 1999
+++ linux/drivers/acorn/net/ether3.c	Wed Aug 18 11:38:59 1999
@@ -74,9 +74,9 @@
 	{ 0xffff, 0xffff }
 };
 
-static void ether3_setmulticastlist(struct device *dev);
-static int  ether3_rx(struct device *dev, struct dev_priv *priv, unsigned int maxcnt);
-static void ether3_tx(struct device *dev, struct dev_priv *priv);
+static void ether3_setmulticastlist(struct net_device *dev);
+static int  ether3_rx(struct net_device *dev, struct dev_priv *priv, unsigned int maxcnt);
+static void ether3_tx(struct net_device *dev, struct dev_priv *priv);
 
 #define BUS_16		2
 #define BUS_8		1
@@ -115,7 +115,7 @@
 #define ether3_inw(r)		({ unsigned int __v = inw((r)); udelay(1); __v; })
 
 static int
-ether3_setbuffer(struct device *dev, buffer_rw_t read, int start)
+ether3_setbuffer(struct net_device *dev, buffer_rw_t read, int start)
 {
 	struct dev_priv *priv = (struct dev_priv *)dev->priv;
 	int timeout = 1000;
@@ -175,7 +175,7 @@
 static void
 ether3_ledoff(unsigned long data)
 {
-	struct device *dev = (struct device *)data;
+	struct net_device *dev = (struct net_device *)data;
 	struct dev_priv *priv = (struct dev_priv *)dev->priv;
 	ether3_outw(priv->regs.config2 |= CFG2_CTRLO, REG_CONFIG2);
 }
@@ -184,7 +184,7 @@
  * switch LED on...
  */
 static inline void
-ether3_ledon(struct device *dev, struct dev_priv *priv)
+ether3_ledon(struct net_device *dev, struct dev_priv *priv)
 {
 	del_timer(&priv->timer);
 	priv->timer.expires = jiffies + HZ / 50; /* leave on for 1/50th second */
@@ -225,7 +225,7 @@
 /* --------------------------------------------------------------------------- */
 
 __initfunc(static int
-ether3_ramtest(struct device *dev, unsigned char byte))
+ether3_ramtest(struct net_device *dev, unsigned char byte))
 {
 	unsigned char *buffer = kmalloc(RX_END, GFP_KERNEL);
 	int i,ret = 0;
@@ -274,7 +274,7 @@
 /* ------------------------------------------------------------------------------- */
 
 __initfunc(static int
-ether3_init_2(struct device *dev))
+ether3_init_2(struct net_device *dev))
 {
 	struct dev_priv *priv = (struct dev_priv *)dev->priv;
 	int i;
@@ -324,7 +324,7 @@
 }
 
 static void
-ether3_init_for_open(struct device *dev)
+ether3_init_for_open(struct net_device *dev)
 {
 	struct dev_priv *priv = (struct dev_priv *)dev->priv;
 	int i;
@@ -364,7 +364,7 @@
 }
 
 static inline int
-ether3_probe_bus_8(struct device *dev, int val)
+ether3_probe_bus_8(struct net_device *dev, int val)
 {
 	int write_low, write_high, read_low, read_high;
 
@@ -385,7 +385,7 @@
 }
 
 static inline int
-ether3_probe_bus_16(struct device *dev, int val)
+ether3_probe_bus_16(struct net_device *dev, int val)
 {
 	int read_val;
 
@@ -401,7 +401,7 @@
  * This is the real probe routine.
  */
 __initfunc(static int
-ether3_probe1(struct device *dev))
+ether3_probe1(struct net_device *dev))
 {
 	static unsigned version_printed = 0;
 	struct dev_priv *priv;
@@ -479,7 +479,7 @@
 }
 
 __initfunc(static void
-ether3_get_dev(struct device *dev, struct expansion_card *ec))
+ether3_get_dev(struct net_device *dev, struct expansion_card *ec))
 {
 	ecard_claim(ec);
 
@@ -499,7 +499,7 @@
 
 #ifndef MODULE
 __initfunc(int
-ether3_probe(struct device *dev))
+ether3_probe(struct net_device *dev))
 {
 	struct expansion_card *ec;
 
@@ -526,7 +526,7 @@
  * there is non-reboot way to recover if something goes wrong.
  */
 static int
-ether3_open(struct device *dev)
+ether3_open(struct net_device *dev)
 {
 	MOD_INC_USE_COUNT;
 
@@ -548,7 +548,7 @@
  * The inverse routine to ether3_open().
  */
 static int
-ether3_close(struct device *dev)
+ether3_close(struct net_device *dev)
 {
 	struct dev_priv *priv = (struct dev_priv *)dev->priv;
 
@@ -573,7 +573,7 @@
  * Get the current statistics.	This may be called with the card open or
  * closed.
  */
-static struct enet_statistics *ether3_getstats(struct device *dev)
+static struct enet_statistics *ether3_getstats(struct net_device *dev)
 {
 	struct dev_priv *priv = (struct dev_priv *)dev->priv;
 	return &priv->stats;
@@ -585,7 +585,7 @@
  * We don't attempt any packet filtering.  The card may have a SEEQ 8004
  * in which does not have the other ethernet address registers present...
  */
-static void ether3_setmulticastlist(struct device *dev)
+static void ether3_setmulticastlist(struct net_device *dev)
 {
 	struct dev_priv *priv = (struct dev_priv *)dev->priv;
 
@@ -606,7 +606,7 @@
  * Transmit a packet
  */
 static int
-ether3_sendpacket(struct sk_buff *skb, struct device *dev)
+ether3_sendpacket(struct sk_buff *skb, struct net_device *dev)
 {
 	struct dev_priv *priv = (struct dev_priv *)dev->priv;
 retry:
@@ -710,7 +710,7 @@
 static void
 ether3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev = (struct device *)dev_id;
+	struct net_device *dev = (struct net_device *)dev_id;
 	struct dev_priv *priv;
 	unsigned int status;
 
@@ -747,7 +747,7 @@
  * If we have a good packet(s), get it/them out of the buffers.
  */
 static int
-ether3_rx(struct device *dev, struct dev_priv *priv, unsigned int maxcnt)
+ether3_rx(struct net_device *dev, struct dev_priv *priv, unsigned int maxcnt)
 {
 	unsigned int next_ptr = priv->rx_head, received = 0;
 	ether3_ledon(dev, priv);
@@ -867,7 +867,7 @@
  * Update stats for the transmitted packet(s)
  */
 static void
-ether3_tx(struct device *dev, struct dev_priv *priv)
+ether3_tx(struct net_device *dev, struct dev_priv *priv)
 {
 	unsigned int tx_tail = priv->tx_tail;
 	int max_work = 14;
@@ -914,7 +914,7 @@
 static struct ether_dev {
 	struct expansion_card	*ec;
 	char			name[9];
-	struct device		dev;
+	struct net_device		dev;
 } ether_devs[MAX_ECARDS];
 
 int
diff -u --recursive --new-file v2.3.13/linux/drivers/acorn/net/ether3.h linux/drivers/acorn/net/ether3.h
--- v2.3.13/linux/drivers/acorn/net/ether3.h	Thu Jun 17 01:11:35 1999
+++ linux/drivers/acorn/net/ether3.h	Wed Aug 18 11:38:59 1999
@@ -159,13 +159,13 @@
     int broken;				/* 0 = ok, 1 = something went wrong	 */
 };
 
-extern int	ether3_probe (struct device *dev);
-static int	ether3_probe1 (struct device *dev);
-static int	ether3_open (struct device *dev);
-static int	ether3_sendpacket (struct sk_buff *skb, struct device *dev);
+extern int	ether3_probe (struct net_device *dev);
+static int	ether3_probe1 (struct net_device *dev);
+static int	ether3_open (struct net_device *dev);
+static int	ether3_sendpacket (struct sk_buff *skb, struct net_device *dev);
 static void	ether3_interrupt (int irq, void *dev_id, struct pt_regs *regs);
-static int	ether3_close (struct device *dev);
-static struct enet_statistics *ether3_getstats (struct device *dev);
-static void	ether3_setmulticastlist (struct device *dev);
+static int	ether3_close (struct net_device *dev);
+static struct enet_statistics *ether3_getstats (struct net_device *dev);
+static void	ether3_setmulticastlist (struct net_device *dev);
 
 #endif
diff -u --recursive --new-file v2.3.13/linux/drivers/acorn/net/etherh.c linux/drivers/acorn/net/etherh.c
--- v2.3.13/linux/drivers/acorn/net/etherh.c	Thu Jun 17 01:11:35 1999
+++ linux/drivers/acorn/net/etherh.c	Wed Aug 18 11:38:59 1999
@@ -104,7 +104,7 @@
 }
 
 static void
-etherh_setif(struct device *dev)
+etherh_setif(struct net_device *dev)
 {
 	unsigned long addr;
 	unsigned long flags;
@@ -140,7 +140,7 @@
 }
 
 static int
-etherh_getifstat(struct device *dev)
+etherh_getifstat(struct net_device *dev)
 {
 	int stat;
 
@@ -172,7 +172,7 @@
  * Reset the 8390 (hard reset)
  */
 static void
-etherh_reset(struct device *dev)
+etherh_reset(struct net_device *dev)
 {
 	outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, dev->base_addr);
 
@@ -183,7 +183,7 @@
  * Write a block of data out to the 8390
  */
 static void
-etherh_block_output (struct device *dev, int count, const unsigned char *buf, int start_page)
+etherh_block_output (struct net_device *dev, int count, const unsigned char *buf, int start_page)
 {
 	unsigned int addr, dma_addr;
 	unsigned long dma_start;
@@ -241,7 +241,7 @@
  * Read a block of data from the 8390
  */
 static void
-etherh_block_input (struct device *dev, int count, struct sk_buff *skb, int ring_offset)
+etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
 {
 	unsigned int addr, dma_addr;
 	unsigned char *buf;
@@ -281,7 +281,7 @@
  * Read a header from the 8390
  */
 static void
-etherh_get_header (struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 {
 	unsigned int addr, dma_addr;
 
@@ -322,7 +322,7 @@
  * there is non-reboot way to recover if something goes wrong.
  */
 static int
-etherh_open(struct device *dev)
+etherh_open(struct net_device *dev)
 {
 	MOD_INC_USE_COUNT;
 
@@ -340,7 +340,7 @@
  * The inverse routine to etherh_open().
  */
 static int
-etherh_close(struct device *dev)
+etherh_close(struct net_device *dev)
 {
 	ei_close (dev);
 	free_irq (dev->irq, dev);
@@ -353,7 +353,7 @@
  * This is the real probe routine.
  */
 __initfunc(static int
-etherh_probe1(struct device *dev))
+etherh_probe1(struct net_device *dev))
 {
 	static int version_printed;
 	unsigned int addr, i, reg0, tmp;
@@ -464,7 +464,7 @@
 };
 
 __initfunc(static void
-etherh_initdev(ecard_t *ec, struct device *dev))
+etherh_initdev(ecard_t *ec, struct net_device *dev))
 {
 	ecard_claim (ec);
 	
@@ -497,7 +497,7 @@
 
 #ifndef MODULE
 __initfunc(int
-etherh_probe(struct device *dev))
+etherh_probe(struct net_device *dev))
 {
 	if (!dev)
 		return ENODEV;
@@ -522,13 +522,13 @@
 static int io[MAX_ETHERH_CARDS];
 static int irq[MAX_ETHERH_CARDS];
 static char ethernames[MAX_ETHERH_CARDS][9];
-static struct device *my_ethers[MAX_ETHERH_CARDS];
+static struct net_device *my_ethers[MAX_ETHERH_CARDS];
 static struct expansion_card *ec[MAX_ETHERH_CARDS];
 
 static int
 init_all_cards(void)
 {
-	struct device *dev = NULL;
+	struct net_device *dev = NULL;
 	int i, found = 0;
 
 	for (i = 0; i < MAX_ETHERH_CARDS; i++) {
@@ -541,9 +541,9 @@
 
 	for (i = 0; i < MAX_ETHERH_CARDS; i++) {
 		if (!dev)
-			dev = (struct device *)kmalloc (sizeof (struct device), GFP_KERNEL);
+			dev = (struct net_device *)kmalloc (sizeof (struct net_device), GFP_KERNEL);
 		if (dev)
-			memset (dev, 0, sizeof (struct device));
+			memset (dev, 0, sizeof (struct net_device));
 
 		if (!io[i]) {
 			if ((ec[i] = ecard_find (0, etherh_cids)) == NULL)
diff -u --recursive --new-file v2.3.13/linux/drivers/acorn/net/net-probe.c linux/drivers/acorn/net/net-probe.c
--- v2.3.13/linux/drivers/acorn/net/net-probe.c	Mon Feb 16 15:49:48 1998
+++ linux/drivers/acorn/net/net-probe.c	Wed Aug 18 11:38:59 1999
@@ -8,11 +8,11 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 
-extern int ether1_probe (struct device *dev);
-extern int ether3_probe (struct device *dev);
-extern int etherh_probe (struct 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);
 
-__initfunc(int acorn_ethif_probe(struct device *dev))
+__initfunc(int acorn_ethif_probe(struct net_device *dev))
 {
 	if (1
 #ifdef CONFIG_ARM_ETHERH
diff -u --recursive --new-file v2.3.13/linux/drivers/ap1000/apfddi.c linux/drivers/ap1000/apfddi.c
--- v2.3.13/linux/drivers/ap1000/apfddi.c	Wed Mar 10 16:51:35 1999
+++ linux/drivers/ap1000/apfddi.c	Wed Aug 18 11:38:58 1999
@@ -124,7 +124,7 @@
 /* XXX our hardware address, canonical bit order */
 static u_char apfddi_saddr[6] = { 0x42, 0x9a, 0x08, 0x6e, 0x11, 0x41 };
 
-struct device *apfddi_device = NULL;
+struct net_device *apfddi_device = NULL;
 struct net_device_stats *apfddi_stats = NULL;
 
 volatile struct apfddi_queue *apfddi_queue_top = NULL;
@@ -249,11 +249,11 @@
 }
 
 
-int apfddi_init(struct device *dev);
+int apfddi_init(struct net_device *dev);
 static void apfddi_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static int apfddi_xmit(struct sk_buff *skb, struct device *dev);
+static int apfddi_xmit(struct sk_buff *skb, struct net_device *dev);
 int apfddi_rx(struct mac_buf *mbuf);
-static struct net_device_stats *apfddi_get_stats(struct device *dev);
+static struct net_device_stats *apfddi_get_stats(struct net_device *dev);
 #if APFDDI_DEBUG
 void dump_packet(char *action, char *buf, int len, int seq);
 #endif
@@ -264,7 +264,7 @@
  * saddr=NULL means use device source address (always will anyway)
  * daddr=NULL means leave destination address (eg unresolved arp)
  */
-static int apfddi_hard_header(struct sk_buff *skb, struct device *dev,
+static int apfddi_hard_header(struct sk_buff *skb, struct net_device *dev,
 			      unsigned short type, void *daddr,
 			      void *saddr, unsigned len)
 {
@@ -366,7 +366,7 @@
  * other address resolution) has completed on this sk_buff. We now let
  * ARP fill in the other fields.  
  */
-static int apfddi_rebuild_header(void *buff, struct device *dev,
+static int apfddi_rebuild_header(void *buff, struct net_device *dev,
 				 unsigned long raddr, struct sk_buff *skb)
 {
     int i, status;
@@ -399,7 +399,7 @@
     return(status);
 }
 
-static int apfddi_set_mac_address(struct device *dev, void *addr)
+static int apfddi_set_mac_address(struct net_device *dev, void *addr)
 {
 #if APFDDI_DEBUG
     printk("In apfddi_set_mac_address\n");
@@ -407,14 +407,14 @@
     return (0);
 }
 
-static void apfddi_set_multicast_list(struct device *dev)
+static void apfddi_set_multicast_list(struct net_device *dev)
 {
 #if APFDDI_DEBUG
     printk("In apfddi_set_multicast_list\n");
 #endif
 }
 
-static int apfddi_do_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
+static int apfddi_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 #if APFDDI_DEBUG
     printk("In apfddi_do_ioctl\n");
@@ -422,7 +422,7 @@
     return (0);
 }
 
-static int apfddi_set_config(struct device *dev, struct ifmap *map)
+static int apfddi_set_config(struct net_device *dev, struct ifmap *map)
 {
 #if APFDDI_DEBUG
     printk("In apfddi_set_config\n");
@@ -433,7 +433,7 @@
 /*
  * Opening the fddi device through ifconfig.
  */
-int apfddi_open(struct device *dev)
+int apfddi_open(struct net_device *dev)
 {
     static int already_run = 0;
     unsigned flags;
@@ -473,7 +473,7 @@
 /*
  * Stop the fddi device through ifconfig.
  */
-int apfddi_stop(struct device *dev)
+int apfddi_stop(struct net_device *dev)
 {
     *csr0 &= ~CS0_INT_ENABLE;
     apfddi_sleep();
@@ -484,7 +484,7 @@
 /*
  * Initialise fddi network interface.
  */
-int apfddi_init(struct device *dev)
+int apfddi_init(struct net_device *dev)
 {
     int i;
 
@@ -625,7 +625,7 @@
 /*
  * Transmitting packet over FDDI.
  */
-static int apfddi_xmit(struct sk_buff *skb, struct device *dev)
+static int apfddi_xmit(struct sk_buff *skb, struct net_device *dev)
 {
     unsigned long flags;
     
@@ -692,7 +692,7 @@
 /*
  * Return statistics of fddi driver.
  */
-static struct net_device_stats *apfddi_get_stats(struct device *dev)
+static struct net_device_stats *apfddi_get_stats(struct net_device *dev)
 {
     return((struct net_device_stats *)dev->priv);
 }
diff -u --recursive --new-file v2.3.13/linux/drivers/ap1000/apfddi.h linux/drivers/ap1000/apfddi.h
--- v2.3.13/linux/drivers/ap1000/apfddi.h	Fri Feb  7 05:54:54 1997
+++ linux/drivers/ap1000/apfddi.h	Wed Aug 18 11:38:58 1999
@@ -137,6 +137,6 @@
 void rmt_event(int st);
 void set_cf_join(int on);
 
-extern struct device *apfddi_device;
+extern struct net_device *apfddi_device;
 extern struct net_device_stats *apfddi_stats;
 
diff -u --recursive --new-file v2.3.13/linux/drivers/ap1000/bif.c linux/drivers/ap1000/bif.c
--- v2.3.13/linux/drivers/ap1000/bif.c	Thu Jul  8 15:42:19 1999
+++ linux/drivers/ap1000/bif.c	Wed Aug 18 11:38:58 1999
@@ -44,17 +44,17 @@
 
 #define BIF_MTU 10240
 
-static struct device *bif_device = 0;
+static struct net_device *bif_device = 0;
 static struct net_device_stats *bif_stats = 0;
 
-int bif_init(struct device *dev);
-int bif_open(struct device *dev);
-static int bif_xmit(struct sk_buff *skb, struct device *dev);
+int bif_init(struct net_device *dev);
+int bif_open(struct net_device *dev);
+static int bif_xmit(struct sk_buff *skb, struct net_device *dev);
 int bif_rx(struct sk_buff *skb);
-int bif_stop(struct device *dev);
-static struct net_device_stats *bif_get_stats(struct device *dev);
+int bif_stop(struct net_device *dev);
+static struct net_device_stats *bif_get_stats(struct net_device *dev);
 
-static int bif_hard_header(struct sk_buff *skb, struct device *dev,
+static int bif_hard_header(struct sk_buff *skb, struct net_device *dev,
 			   unsigned short type, void *daddr,
 			   void *saddr, unsigned len)
 {
@@ -70,7 +70,7 @@
   return (dev->hard_header_len);
 }
 
-static int bif_rebuild_header(void *buff, struct device *dev,
+static int bif_rebuild_header(void *buff, struct net_device *dev,
 			      unsigned long raddr, struct sk_buff *skb)
 {
   /* this would normally be used to fill in hardware addresses after
@@ -82,24 +82,24 @@
   return(0);
 }
 
-static int bif_set_mac_address(struct device *dev, void *addr)
+static int bif_set_mac_address(struct net_device *dev, void *addr)
 {
   printk("BIF: set_mac_address called\n");
   return (0);
 }
 
-static void bif_set_multicast_list(struct device *dev)
+static void bif_set_multicast_list(struct net_device *dev)
 {
   return;
 }
 
-static int bif_do_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
+static int bif_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
   printk("BIF: Called do_ioctl\n");
   return (0);
 }
 
-static int bif_set_config(struct device *dev, struct ifmap *map)
+static int bif_set_config(struct net_device *dev, struct ifmap *map)
 {
   printk("BIF: Called bif_set_config\n");
   return (0);
@@ -108,7 +108,7 @@
 /*
  * Initialise bif network interface.
  */
-int bif_init(struct device *dev)
+int bif_init(struct net_device *dev)
 {
     int i;
 
@@ -149,7 +149,7 @@
     return(0);
 }
 
-int bif_open(struct device *dev)
+int bif_open(struct net_device *dev)
 {
     printk("In bif_open\n");
     dev->tbusy = 0;
@@ -189,7 +189,7 @@
 #endif
 
 
-static int bif_xmit(struct sk_buff *skb, struct device *dev)
+static int bif_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	extern int bif_send_ip(int cid,struct sk_buff *skb);
 	extern int tnet_send_ip(int cid,struct sk_buff *skb);
@@ -260,7 +260,7 @@
 	return 0;
 }
 
-int bif_stop(struct device *dev)
+int bif_stop(struct net_device *dev)
 {
 	printk("in bif_close\n");
 
@@ -273,7 +273,7 @@
 /*
  * Return statistics of bif driver.
  */
-static struct net_device_stats *bif_get_stats(struct device *dev)
+static struct net_device_stats *bif_get_stats(struct net_device *dev)
 {
     return((struct net_device_stats *)dev->priv);
 }
diff -u --recursive --new-file v2.3.13/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v2.3.13/linux/drivers/block/floppy.c	Mon Aug  9 14:59:19 1999
+++ linux/drivers/block/floppy.c	Tue Aug 17 10:48:20 1999
@@ -106,6 +106,12 @@
  * 1998/09/20 -- David Weinehall -- Added slow-down code for buggy PS/2-drives.
  */
 
+/*
+ * 1999/08/13 -- Paul Slootman -- floppy stopped working on Alpha after 24
+ * days, 6 hours, 32 minutes and 32 seconds (i.e. MAXINT jiffies; ints were
+ * being used to store jiffies, which are unsigned longs).
+ */
+
 #define FLOPPY_SANITY_CHECK
 #undef  FLOPPY_SILENT_DCL_CLEAR
 
@@ -606,10 +612,10 @@
 #define OLOGSIZE 20
 
 static void (*lasthandler)(void) = NULL;
-static int interruptjiffies=0;
-static int resultjiffies=0;
+static unsigned long interruptjiffies=0;
+static unsigned long resultjiffies=0;
 static int resultsize=0;
-static int lastredo=0;
+static unsigned long lastredo=0;
 
 static struct output_log {
 	unsigned char data;
@@ -629,7 +635,7 @@
 		drive = current_drive;
 	del_timer(&fd_timeout);
 	if (drive < 0 || drive > N_DRIVE) {
-		fd_timeout.expires = jiffies + 20*HZ;
+		fd_timeout.expires = jiffies + 20UL*HZ;
 		drive=0;
 	} else
 		fd_timeout.expires = jiffies + UDP->timeout;
@@ -712,7 +718,7 @@
 #ifdef DCL_DEBUG
 	if (UDP->flags & FD_DEBUG){
 		DPRINT("checking disk change line for drive %d\n",drive);
-		DPRINT("jiffies=%ld\n", jiffies);
+		DPRINT("jiffies=%lu\n", jiffies);
 		DPRINT("disk change line=%x\n",fd_inb(FD_DIR)&0x80);
 		DPRINT("flags=%lx\n",UDRS->flags);
 	}
@@ -1006,7 +1012,7 @@
 }
 
 /* waits for a delay (spinup or select) to pass */
-static int wait_for_completion(int delay, timeout_fn function)
+static int wait_for_completion(unsigned long delay, timeout_fn function)
 {
 	if (FDCS->reset){
 		reset_fdc(); /* do the reset during sleep to win time
@@ -1277,7 +1283,7 @@
 static void fdc_specify(void)
 {
 	unsigned char spec1, spec2;
-	int srt, hlt, hut;
+	unsigned long srt, hlt, hut;
 	unsigned long dtr = NOMINAL_DTR;
 	unsigned long scale_dtr = NOMINAL_DTR;
 	int hlt_max_code = 0x7f;
@@ -1367,7 +1373,7 @@
 	 * Pause 5 msec to avoid trouble. (Needs to be 2 jiffies)
 	 */
 	FDCS->dtr = raw_cmd->rate & 3;
-	return(wait_for_completion(jiffies+2*HZ/100,
+	return(wait_for_completion(jiffies+2UL*HZ/100,
 				   (timeout_fn) floppy_ready));
 } /* fdc_dtr */
 
@@ -1463,7 +1469,8 @@
  */
 static void setup_rw_floppy(void)
 {
-	int i,ready_date,r, flags,dflags;
+	int i,r, flags,dflags;
+	unsigned long ready_date;
 	timeout_fn function;
 
 	flags = raw_cmd->flags;
@@ -1536,7 +1543,7 @@
 #ifdef DCL_DEBUG
 		if (DP->flags & FD_DEBUG){
 			DPRINT("clearing NEWCHANGE flag because of effective seek\n");
-			DPRINT("jiffies=%ld\n", jiffies);
+			DPRINT("jiffies=%lu\n", jiffies);
 		}
 #endif
 		CLEARF(FD_DISK_NEWCHANGE); /* effective seek */
@@ -1826,20 +1833,20 @@
 	printk("\n");
 	printk("floppy driver state\n");
 	printk("-------------------\n");
-	printk("now=%ld last interrupt=%d last called handler=%p\n",
-	       jiffies, interruptjiffies, lasthandler);
+	printk("now=%lu last interrupt=%lu diff=%lu last called handler=%p\n",
+	       jiffies, interruptjiffies, jiffies-interruptjiffies, lasthandler);
 
 
 #ifdef FLOPPY_SANITY_CHECK
 	printk("timeout_message=%s\n", timeout_message);
 	printk("last output bytes:\n");
 	for (i=0; i < OLOGSIZE; i++)
-		printk("%2x %2x %ld\n",
+		printk("%2x %2x %lu\n",
 		       output_log[(i+output_log_pos) % OLOGSIZE].data,
 		       output_log[(i+output_log_pos) % OLOGSIZE].status,
 		       output_log[(i+output_log_pos) % OLOGSIZE].jiffies);
-	printk("last result at %d\n", resultjiffies);
-	printk("last redo_fd_request at %d\n", lastredo);
+	printk("last result at %lu\n", resultjiffies);
+	printk("last redo_fd_request at %lu\n", lastredo);
 	for (i=0; i<resultsize; i++){
 		printk("%2x ", reply_buffer[i]);
 	}
@@ -1856,8 +1863,8 @@
 		printk("fd_timer.function=%p\n", fd_timer.function);
 	if (fd_timeout.prev){
 		printk("timer_table=%p\n",fd_timeout.function);
-		printk("expires=%ld\n",fd_timeout.expires-jiffies);
-		printk("now=%ld\n",jiffies);
+		printk("expires=%lu\n",fd_timeout.expires-jiffies);
+		printk("now=%lu\n",jiffies);
 	}
 	printk("cont=%p\n", cont);
 	printk("CURRENT=%p\n", CURRENT);
@@ -3002,12 +3009,12 @@
  * Misc Ioctl's and support
  * ========================
  */
-static inline int fd_copyout(void *param, const void *address, int size)
+static inline int fd_copyout(void *param, const void *address, unsigned long size)
 {
 	return copy_to_user(param,address, size) ? -EFAULT : 0;
 }
 
-static inline int fd_copyin(void *param, void *address, int size)
+static inline int fd_copyin(void *param, void *address, unsigned long size)
 {
 	return copy_from_user(address, param, size) ? -EFAULT : 0;
 }
@@ -3805,7 +3812,7 @@
 	if (UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY))
 		return 1;
 
-	if (UDP->checkfreq < jiffies - UDRS->last_checked){
+	if (UDP->checkfreq < (int)(jiffies - UDRS->last_checked)) {
 		lock_fdc(drive,0);
 		poll_drive(0,0);
 		process_fd_request();
@@ -4061,8 +4068,7 @@
 	{ "no_unexpected_interrupts", 0, &print_unex, 0, 0 },
 	{ "L40SX", 0, &print_unex, 0, 0 } };
 
-#define FLOPPY_SETUP
-void __init floppy_setup(char *str)
+static int __init floppy_setup(char *str)
 {
 	int i;
 	int param;
@@ -4084,7 +4090,7 @@
 					DPRINT("%s=%d\n", str, param);
 					*config_params[i].var = param;
 				}
-				return;
+				return 1;
 			}
 		}
 	}
@@ -4098,6 +4104,7 @@
 	} else
 		DPRINT("botched floppy option\n");
 	DPRINT("Read linux/drivers/block/README.fd\n");
+	return 1;
 }
 
 static int have_no_fdc= -EIO;
@@ -4365,7 +4372,6 @@
 static void __init parse_floppy_cfg_string(char *cfg)
 {
 	char *ptr;
-	int ints[11];
 
 	while(*cfg) {
 		for(ptr = cfg;*cfg && *cfg != ' ' && *cfg != '\t'; cfg++);
@@ -4457,6 +4463,9 @@
 #endif
 
 #else
+
+__setup ("floppy=", floppy_setup);
+
 /* eject the boot floppy (if we need the drive for a different root floppy) */
 /* This should only be called at boot time when we're sure that there's no
  * resource contention. */
diff -u --recursive --new-file v2.3.13/linux/drivers/block/genhd.c linux/drivers/block/genhd.c
--- v2.3.13/linux/drivers/block/genhd.c	Mon Aug  9 14:59:19 1999
+++ linux/drivers/block/genhd.c	Thu Aug 12 12:26:06 1999
@@ -4,1404 +4,27 @@
  *
  *  Copyright (C) 1991-1998  Linus Torvalds
  *
- *
- *  Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
- *  in the early extended-partition checks and added DM partitions
- *
- *  Support for DiskManager v6.0x added by Mark Lord,
- *  with information provided by OnTrack.  This now works for linux fdisk
- *  and LILO, as well as loadlin and bootln.  Note that disks other than
- *  /dev/hda *must* have a "DOS" type 0x51 partition in the first slot (hda1).
- *
- *  More flexible handling of extended partitions - aeb, 950831
- *
- *  Check partition table on IDE disks for common CHS translations
- *
- *  Added needed MAJORS for new pairs, {hdi,hdj}, {hdk,hdl}
+ *  Moved partition checking code to fs/partitions* - Russell King
+ *  (linux@arm.uk.linux.org)
  */
 
 #include <linux/config.h>
 #include <linux/fs.h>
 #include <linux/genhd.h>
 #include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/string.h>
 #include <linux/blk.h>
 #include <linux/init.h>
 
-#include <asm/system.h>
-#include <asm/byteorder.h>
-
-/*
- * Many architectures don't like unaligned accesses, which is
- * frequently the case with the nr_sects and start_sect partition
- * table entries.
- */
-#include <asm/unaligned.h>
-
-#define SYS_IND(p)	(get_unaligned(&p->sys_ind))
-#define NR_SECTS(p)	({ __typeof__(p->nr_sects) __a =	\
-				get_unaligned(&p->nr_sects);	\
-				le32_to_cpu(__a); \
-			})
-
-#define START_SECT(p)	({ __typeof__(p->start_sect) __a =	\
-				get_unaligned(&p->start_sect);	\
-				le32_to_cpu(__a); \
-			})
-
-struct gendisk *gendisk_head = NULL;
-
-static int current_minor = 0;
-extern int *blk_size[];
-extern void rd_load(void);
-extern void initrd_load(void);
-
+extern int parport_init(void);
 extern int chr_dev_init(void);
 extern int blk_dev_init(void);
 extern int scsi_dev_init(void);
 extern int net_dev_init(void);
-extern int i2o_init(void);
-
-#ifdef CONFIG_PPC
-extern void note_bootable_part(kdev_t dev, int part);
-#endif
-
-/*
- * disk_name() is used by genhd.c and blkpg.c.
- * It formats the devicename of the indicated disk into
- * the supplied buffer (of size at least 32), and returns
- * a pointer to that same buffer (for convenience).
- */
-char *disk_name (struct gendisk *hd, int minor, char *buf)
-{
-	unsigned int part;
-	const char *maj = hd->major_name;
-	int unit = (minor >> hd->minor_shift) + 'a';
-
-	/*
-	 * IDE devices use multiple major numbers, but the drives
-	 * are named as:  {hda,hdb}, {hdc,hdd}, {hde,hdf}, {hdg,hdh}..
-	 * This requires special handling here.
-	 */
-	switch (hd->major) {
-		case IDE9_MAJOR:
-			unit += 2;
-		case IDE8_MAJOR:
-			unit += 2;
-		case IDE7_MAJOR:
-			unit += 2;
-		case IDE6_MAJOR:
-			unit += 2;
-		case IDE5_MAJOR:
-			unit += 2;
-		case IDE4_MAJOR:
-			unit += 2;
-		case IDE3_MAJOR:
-			unit += 2;
-		case IDE2_MAJOR:
-			unit += 2;
-		case IDE1_MAJOR:
-			unit += 2;
-		case IDE0_MAJOR:
-			maj = "hd";
-			break;
-	}
-	part = minor & ((1 << hd->minor_shift) - 1);
-	if (hd->major >= SCSI_DISK1_MAJOR && hd->major <= SCSI_DISK7_MAJOR) {
-		unit = unit + (hd->major - SCSI_DISK1_MAJOR + 1) * 16;
-		if (unit > 'z') {
-			unit -= 'z' + 1;
-			sprintf(buf, "sd%c%c", 'a' + unit / 26, 'a' + unit % 26);
-			if (part)
-				sprintf(buf + 4, "%d", part);
-			return buf;
-		}
-	}
-	if (hd->major >= COMPAQ_SMART2_MAJOR && hd->major <= COMPAQ_SMART2_MAJOR+7) {
-		int ctlr = hd->major - COMPAQ_SMART2_MAJOR;
- 		int disk = minor >> hd->minor_shift;
- 		int part = minor & (( 1 << hd->minor_shift) - 1);
- 		if (part == 0)
- 			sprintf(buf, "%s/c%dd%d", maj, ctlr, disk);
- 		else
- 			sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, disk, part);
- 		return buf;
- 	}
-	if (part)
-		sprintf(buf, "%s%c%d", maj, unit, part);
-	else
-		sprintf(buf, "%s%c", maj, unit);
-	return buf;
-}
-
-static void add_partition (struct gendisk *hd, int minor, int start, int size)
-{
-	char buf[40];
-	hd->part[minor].start_sect = start;
-	hd->part[minor].nr_sects   = size;
-	if (hd->major >= COMPAQ_SMART2_MAJOR+0 && hd->major <= COMPAQ_SMART2_MAJOR+7)
-		printk(" p%d", (minor & ((1 << hd->minor_shift) - 1)));
-	else
-		printk(" %s", disk_name(hd, minor, buf));
-}
-
-static inline int is_extended_partition(struct partition *p)
-{
-	return (SYS_IND(p) == DOS_EXTENDED_PARTITION ||
-		SYS_IND(p) == WIN98_EXTENDED_PARTITION ||
-		SYS_IND(p) == LINUX_EXTENDED_PARTITION);
-}
-
-int get_hardsect_size(kdev_t dev)
-{
-	if (hardsect_size[MAJOR(dev)] != NULL)
-		return hardsect_size[MAJOR(dev)][MINOR(dev)];
-	else
-		return 512;
-}
-
-static unsigned int get_ptable_blocksize(kdev_t dev)
-{
-  int ret = 1024;
-
-  /*
-   * See whether the low-level driver has given us a minumum blocksize.
-   * If so, check to see whether it is larger than the default of 1024.
-   */
-  if (!blksize_size[MAJOR(dev)])
-    {
-      return ret;
-    }
-
-  /*
-   * Check for certain special power of two sizes that we allow.
-   * With anything larger than 1024, we must force the blocksize up to
-   * the natural blocksize for the device so that we don't have to try
-   * and read partial sectors.  Anything smaller should be just fine.
-   */
-
-  switch( blksize_size[MAJOR(dev)][MINOR(dev)] )
-    {
-    case 2048:
-      ret = 2048;
-      break;
-    case 4096:
-      ret = 4096;
-      break;
-    case 8192:
-      ret = 8192;
-      break;
-    case 1024:
-    case 512:
-    case 256:
-    case 0:
-      /*
-       * These are all OK.
-       */
-      break;
-    default:
-      panic("Strange blocksize for partition table\n");
-    }
-
-  return ret;
-
-}
-
-#ifdef CONFIG_MSDOS_PARTITION
-/*
- * Create devices for each logical partition in an extended partition.
- * The logical partitions form a linked list, with each entry being
- * a partition table with two entries.  The first entry
- * is the real data partition (with a start relative to the partition
- * table start).  The second is a pointer to the next logical partition
- * (with a start relative to the entire extended partition).
- * We do not create a Linux partition for the partition tables, but
- * only for the actual data partitions.
- */
-
-#define MSDOS_LABEL_MAGIC		0xAA55
-
-static void extended_partition(struct gendisk *hd, kdev_t dev)
-{
-	struct buffer_head *bh;
-	struct partition *p;
-	unsigned long first_sector, first_size, this_sector, this_size;
-	int mask = (1 << hd->minor_shift) - 1;
-	int sector_size = get_hardsect_size(dev) / 512;
-	int i;
-
-	first_sector = hd->part[MINOR(dev)].start_sect;
-	first_size = hd->part[MINOR(dev)].nr_sects;
-	this_sector = first_sector;
-
-	while (1) {
-		if ((current_minor & mask) == 0)
-			return;
-		if (!(bh = bread(dev,0,get_ptable_blocksize(dev))))
-			return;
-
-		if ((*(__u16 *) (bh->b_data+510)) != cpu_to_le16(MSDOS_LABEL_MAGIC))
-			goto done;
-
-		p = (struct partition *) (0x1BE + bh->b_data);
-
-		this_size = hd->part[MINOR(dev)].nr_sects;
-
-		/*
-		 * Usually, the first entry is the real data partition,
-		 * the 2nd entry is the next extended partition, or empty,
-		 * and the 3rd and 4th entries are unused.
-		 * However, DRDOS sometimes has the extended partition as
-		 * the first entry (when the data partition is empty),
-		 * and OS/2 seems to use all four entries.
-		 */
-
-		/* 
-		 * First process the data partition(s)
-		 */
-		for (i=0; i<4; i++, p++) {
-			if (!NR_SECTS(p) || is_extended_partition(p))
-				continue;
-
-			/* Check the 3rd and 4th entries -
-			   these sometimes contain random garbage */
-			if (i >= 2
-				&& START_SECT(p) + NR_SECTS(p) > this_size
-				&& (this_sector + START_SECT(p) < first_sector ||
-				    this_sector + START_SECT(p) + NR_SECTS(p) >
-				     first_sector + first_size))
-				continue;
-
-			add_partition(hd, current_minor, this_sector+START_SECT(p)*sector_size, NR_SECTS(p)*sector_size);
-			current_minor++;
-			if ((current_minor & mask) == 0)
-				goto done;
-		}
-		/*
-		 * Next, process the (first) extended partition, if present.
-		 * (So far, there seems to be no reason to make
-		 *  extended_partition()  recursive and allow a tree
-		 *  of extended partitions.)
-		 * It should be a link to the next logical partition.
-		 * Create a minor for this just long enough to get the next
-		 * partition table.  The minor will be reused for the next
-		 * data partition.
-		 */
-		p -= 4;
-		for (i=0; i<4; i++, p++)
-			if(NR_SECTS(p) && is_extended_partition(p))
-				break;
-		if (i == 4)
-			goto done;	 /* nothing left to do */
-
-		hd->part[current_minor].nr_sects = NR_SECTS(p) * sector_size; /* JSt */
-		hd->part[current_minor].start_sect = first_sector + START_SECT(p) * sector_size;
-		this_sector = first_sector + START_SECT(p) * sector_size;
-		dev = MKDEV(hd->major, current_minor);
-
-		/* Use bforget(), as we have changed the disk geometry */
-		bforget(bh);
-	}
-done:
-	bforget(bh);
-}
-
-#ifdef CONFIG_SOLARIS_X86_PARTITION
-static void
-solaris_x86_partition(struct gendisk *hd, kdev_t dev, long offset) {
-
-	struct buffer_head *bh;
-	struct solaris_x86_vtoc *v;
-	struct solaris_x86_slice *s;
-	int i;
-
-	if(!(bh = bread(dev, 0, get_ptable_blocksize(dev))))
-		return;
-	v = (struct solaris_x86_vtoc *)(bh->b_data + 512);
-	if(v->v_sanity != SOLARIS_X86_VTOC_SANE) {
-		brelse(bh);
-		return;
-	}
-	printk(" <solaris:");
-	if(v->v_version != 1) {
-		printk("  cannot handle version %ld vtoc>", v->v_version);
-		brelse(bh);
-		return;
-	}
-	for(i=0; i<SOLARIS_X86_NUMSLICE; i++) {
-		s = &v->v_slice[i];
-
-		if (s->s_size == 0)
-			continue;
-		printk(" [s%d]", i);
-		/* solaris partitions are relative to current MS-DOS
-		 * one but add_partition starts relative to sector
-		 * zero of the disk.  Therefore, must add the offset
-		 * of the current partition */
-		add_partition(hd, current_minor, s->s_start+offset, s->s_size);
-		current_minor++;
-	}
-	brelse(bh);
-	printk(" >");
-}
-#endif
-
-#ifdef CONFIG_BSD_DISKLABEL
-static void check_and_add_bsd_partition(struct gendisk *hd,
-					struct bsd_partition *bsd_p, kdev_t dev)
-{
-	struct hd_struct *lin_p;
-		/* check relative position of partitions.  */
-	for (lin_p = hd->part + 1 + MINOR(dev);
-	     lin_p - hd->part - MINOR(dev) < current_minor; lin_p++) {
-			/* no relationship -> try again */
-		if (lin_p->start_sect + lin_p->nr_sects <= bsd_p->p_offset 
-			|| lin_p->start_sect >= bsd_p->p_offset + bsd_p->p_size)
-			continue;	
-			/* equal -> no need to add */
-		if (lin_p->start_sect == bsd_p->p_offset && 
-			lin_p->nr_sects == bsd_p->p_size) 
-			return;
-			/* bsd living within dos partition */
-		if (lin_p->start_sect <= bsd_p->p_offset && lin_p->start_sect 
-			+ lin_p->nr_sects >= bsd_p->p_offset + bsd_p->p_size) {
-#ifdef DEBUG_BSD_DISKLABEL
-			printk("w: %d %ld+%ld,%d+%d", 
-				lin_p - hd->part, 
-				lin_p->start_sect, lin_p->nr_sects, 
-				bsd_p->p_offset, bsd_p->p_size);
-#endif
-			break;
-		}
-	 /* ouch: bsd and linux overlap. Don't even try for that partition */
-#ifdef DEBUG_BSD_DISKLABEL
-		printk("???: %d %ld+%ld,%d+%d",
-			lin_p - hd->part, lin_p->start_sect, lin_p->nr_sects,
-			bsd_p->p_offset, bsd_p->p_size);
-#endif
-		printk("???");
-		return;
-	} /* if the bsd partition is not currently known to linux, we end
-	   * up here 
-	   */
-	add_partition(hd, current_minor, bsd_p->p_offset, bsd_p->p_size);
-	current_minor++;
-}
-/* 
- * Create devices for BSD partitions listed in a disklabel, under a
- * dos-like partition. See extended_partition() for more information.
- */
-static void bsd_disklabel_partition(struct gendisk *hd, kdev_t dev, 
-   int max_partitions)
-{
-	struct buffer_head *bh;
-	struct bsd_disklabel *l;
-	struct bsd_partition *p;
-	int mask = (1 << hd->minor_shift) - 1;
-
-	if (!(bh = bread(dev,0,get_ptable_blocksize(dev))))
-		return;
-	l = (struct bsd_disklabel *) (bh->b_data+512);
-	if (l->d_magic != BSD_DISKMAGIC) {
-		brelse(bh);
-		return;
-	}
-
-	if (l->d_npartitions < max_partitions)
-		max_partitions = l->d_npartitions;
-	for (p = l->d_partitions; p - l->d_partitions <  max_partitions; p++) {
-		if ((current_minor & mask) >= (4 + hd->max_p))
-			break;
-
-		if (p->p_fstype != BSD_FS_UNUSED) 
-			check_and_add_bsd_partition(hd, p, dev);
-	}
-
-	/* Use bforget(), as we have changed the disk setup */
-	bforget(bh);
-
-}
-#endif
-
-#ifdef CONFIG_UNIXWARE_DISKLABEL
-/*
- * Create devices for Unixware partitions listed in a disklabel, under a
- * dos-like partition. See extended_partition() for more information.
- */
-static void unixware_partition(struct gendisk *hd, kdev_t dev)
-{
-	struct buffer_head *bh;
-	struct unixware_disklabel *l;
-	struct unixware_slice *p;
-	int mask = (1 << hd->minor_shift) - 1;
-
-	if (!(bh = bread(dev, 14, get_ptable_blocksize(dev))))
-		return;
-	l = (struct unixware_disklabel *) (bh->b_data+512);
-	if (le32_to_cpu(l->d_magic) != UNIXWARE_DISKMAGIC ||
-	    le32_to_cpu(l->vtoc.v_magic) != UNIXWARE_DISKMAGIC2) {
-		brelse(bh);
-		return;
-	}
-	printk(" <unixware:");
-	p = &l->vtoc.v_slice[1];
-	/* I omit the 0th slice as it is the same as whole disk. */
-	while (p - &l->vtoc.v_slice[0] < UNIXWARE_NUMSLICE) {
-		if ((current_minor & mask) == 0)
-			break;
-
-		if (p->s_label != UNIXWARE_FS_UNUSED) {
-			add_partition(hd, current_minor, START_SECT(p), NR_SECTS(p));
-			current_minor++;
-		}
-		p++;
-	}
-	/* Use bforget, as we have changed the disk setup */
-	bforget(bh);
-	printk(" >");
-}
-#endif
-
-static int msdos_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
-{
-	int i, minor = current_minor;
-	struct buffer_head *bh;
-	struct partition *p;
-	unsigned char *data;
-	int mask = (1 << hd->minor_shift) - 1;
-	int sector_size = get_hardsect_size(dev) / 512;
-#ifdef CONFIG_BSD_DISKLABEL
-	/* no bsd disklabel as a default */
-	kdev_t bsd_kdev = 0;
-	int bsd_maxpart = BSD_MAXPARTITIONS;
-#endif
-#ifdef CONFIG_BLK_DEV_IDE
-	int tested_for_xlate = 0;
-
-read_mbr:
-#endif
-	if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) {
-		printk(" unable to read partition table\n");
-		return -1;
-	}
-	data = bh->b_data;
-#ifdef CONFIG_BLK_DEV_IDE
-check_table:
-#endif
-	/* Use bforget(), because we have potentially changed the disk geometry */
-	if (*(unsigned short *)  (0x1fe + data) != cpu_to_le16(MSDOS_LABEL_MAGIC)) {
-		bforget(bh);
-		return 0;
-	}
-	p = (struct partition *) (0x1be + data);
-
-#ifdef CONFIG_BLK_DEV_IDE
-	if (!tested_for_xlate++) {	/* Do this only once per disk */
-		/*
-		 * Look for various forms of IDE disk geometry translation
-		 */
-		extern int ide_xlate_1024(kdev_t, int, const char *);
-		unsigned int sig = le16_to_cpu(*(unsigned short *)(data + 2));
-		if (SYS_IND(p) == EZD_PARTITION) {
-			/*
-			 * The remainder of the disk must be accessed using
-			 * a translated geometry that reduces the number of 
-			 * apparent cylinders to less than 1024 if possible.
-			 *
-			 * ide_xlate_1024() will take care of the necessary
-			 * adjustments to fool fdisk/LILO and partition check.
-			 */
-			if (ide_xlate_1024(dev, -1, " [EZD]")) {
-				data += 512;
-				goto check_table;
-			}
-		} else if (SYS_IND(p) == DM6_PARTITION) {
-
-			/*
-			 * Everything on the disk is offset by 63 sectors,
-			 * including a "new" MBR with its own partition table,
-			 * and the remainder of the disk must be accessed using
-			 * a translated geometry that reduces the number of 
-			 * apparent cylinders to less than 1024 if possible.
-			 *
-			 * ide_xlate_1024() will take care of the necessary
-			 * adjustments to fool fdisk/LILO and partition check.
-			 */
-			if (ide_xlate_1024(dev, 1, " [DM6:DDO]")) {
-				bforget(bh);
-				goto read_mbr;	/* start over with new MBR */
-			}
-		} else if (sig <= 0x1ae &&
-			   *(unsigned short *)(data + sig) == cpu_to_le16(0x55AA) &&
-			   (1 & *(unsigned char *)(data + sig + 2))) {
-			/* DM6 signature in MBR, courtesy of OnTrack */
-			(void) ide_xlate_1024 (dev, 0, " [DM6:MBR]");
-		} else if (SYS_IND(p) == DM6_AUX1PARTITION || SYS_IND(p) == DM6_AUX3PARTITION) {
-			/*
-			 * DM6 on other than the first (boot) drive
-			 */
-			(void) ide_xlate_1024(dev, 0, " [DM6:AUX]");
-		} else {
-			/*
-			 * Examine the partition table for common translations.
-			 * This is useful for drives in situations where the
-			 * translated geometry is unavailable from the BIOS.
-			 */
-			for (i = 0; i < 4; i++) {
-				struct partition *q = &p[i];
-				if (NR_SECTS(q)
-				   && (q->sector & 63) == 1
-				   && (q->end_sector & 63) == 63) {
-					unsigned int heads = q->end_head + 1;
-					if (heads == 32 || heads == 64 ||
-					    heads == 128 || heads == 240 ||
-					    heads == 255) {
-						(void) ide_xlate_1024(dev, heads, " [PTBL]");
-						break;
-					}
-				}
-			}
-		}
-	}
-#endif	/* CONFIG_BLK_DEV_IDE */
-
-	current_minor += 4;  /* first "extra" minor (for extended partitions) */
-	for (i=1 ; i<=4 ; minor++,i++,p++) {
-		if (!NR_SECTS(p))
-			continue;
-               add_partition(hd, minor, first_sector+START_SECT(p)*sector_size, NR_SECTS(p)*sector_size);
-		if (is_extended_partition(p)) {
-			printk(" <");
-			/*
-			 * If we are rereading the partition table, we need
-			 * to set the size of the partition so that we will
-			 * be able to bread the block containing the extended
-			 * partition info.
-			 */
-			hd->sizes[minor] = hd->part[minor].nr_sects 
-			  	>> (BLOCK_SIZE_BITS - 9);
-			extended_partition(hd, MKDEV(hd->major, minor));
-			printk(" >");
-			/* prevent someone doing mkfs or mkswap on an
-			   extended partition, but leave room for LILO */
-			if (hd->part[minor].nr_sects > 2)
-				hd->part[minor].nr_sects = 2;
-		}
-#ifdef CONFIG_BSD_DISKLABEL
-			/* tag first disklabel for late recognition */
-		if (SYS_IND(p) == BSD_PARTITION || SYS_IND(p) == NETBSD_PARTITION) {
-			printk("!");
-			if (!bsd_kdev)
-				bsd_kdev = MKDEV(hd->major, minor);
-		} else if (SYS_IND(p) == OPENBSD_PARTITION) {
-			printk("!");
-			if (!bsd_kdev) {
-				bsd_kdev = MKDEV(hd->major, minor);
-				bsd_maxpart = OPENBSD_MAXPARTITIONS;
-			}
-		}
-#endif
-#ifdef CONFIG_UNIXWARE_DISKLABEL
-		if (SYS_IND(p) == UNIXWARE_PARTITION)
-			unixware_partition(hd, MKDEV(hd->major, minor));
-#endif
-#ifdef CONFIG_SOLARIS_X86_PARTITION
-
-		/* james@bpgc.com: Solaris has a nasty indicator: 0x82
-		 * which also means linux swap.  For that reason, all
-		 * of the prints are done inside the
-		 * solaris_x86_partition routine */
-
-		if(SYS_IND(p) == SOLARIS_X86_PARTITION) {
-			solaris_x86_partition(hd, MKDEV(hd->major, minor),
-					      first_sector+START_SECT(p));
-		}
-#endif
-	}
-#ifdef CONFIG_BSD_DISKLABEL
-	if (bsd_kdev) {
-		printk(" <");
-		bsd_disklabel_partition(hd, bsd_kdev, bsd_maxpart);
-		printk(" >");
-	}
-#endif
-	/*
-	 *  Check for old-style Disk Manager partition table
-	 */
-	if (*(unsigned short *) (data+0xfc) == cpu_to_le16(MSDOS_LABEL_MAGIC)) {
-		p = (struct partition *) (0x1be + data);
-		for (i = 4 ; i < 16 ; i++, current_minor++) {
-			p--;
-			if ((current_minor & mask) == 0)
-				break;
-			if (!(START_SECT(p) && NR_SECTS(p)))
-				continue;
-			add_partition(hd, current_minor, START_SECT(p), NR_SECTS(p));
-		}
-	}
-	printk("\n");
-	bforget(bh);
-	return 1;
-}
-
-#endif /* CONFIG_MSDOS_PARTITION */
-
-#ifdef CONFIG_OSF_PARTITION
-
-static int osf_partition(struct gendisk *hd, unsigned int dev, unsigned long first_sector)
-{
-	int i;
-	int mask = (1 << hd->minor_shift) - 1;
-	struct buffer_head *bh;
-	struct disklabel {
-		u32 d_magic;
-		u16 d_type,d_subtype;
-		u8 d_typename[16];
-		u8 d_packname[16];
-		u32 d_secsize;
-		u32 d_nsectors;
-		u32 d_ntracks;
-		u32 d_ncylinders;
-		u32 d_secpercyl;
-		u32 d_secprtunit;
-		u16 d_sparespertrack;
-		u16 d_sparespercyl;
-		u32 d_acylinders;
-		u16 d_rpm, d_interleave, d_trackskew, d_cylskew;
-		u32 d_headswitch, d_trkseek, d_flags;
-		u32 d_drivedata[5];
-		u32 d_spare[5];
-		u32 d_magic2;
-		u16 d_checksum;
-		u16 d_npartitions;
-		u32 d_bbsize, d_sbsize;
-		struct d_partition {
-			u32 p_size;
-			u32 p_offset;
-			u32 p_fsize;
-			u8  p_fstype;
-			u8  p_frag;
-			u16 p_cpg;
-		} d_partitions[8];
-	} * label;
-	struct d_partition * partition;
-#define DISKLABELMAGIC (0x82564557UL)
-
-	if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) {
-		printk("unable to read partition table\n");
-		return -1;
-	}
-	label = (struct disklabel *) (bh->b_data+64);
-	partition = label->d_partitions;
-	if (label->d_magic != DISKLABELMAGIC) {
-		brelse(bh);
-		return 0;
-	}
-	if (label->d_magic2 != DISKLABELMAGIC) {
-		brelse(bh);
-		return 0;
-	}
-	for (i = 0 ; i < label->d_npartitions; i++, partition++) {
-		if ((current_minor & mask) == 0)
-		        break;
-		if (partition->p_size)
-			add_partition(hd, current_minor,
-				first_sector+partition->p_offset,
-				partition->p_size);
-		current_minor++;
-	}
-	printk("\n");
-	brelse(bh);
-	return 1;
-}
-
-#endif /* CONFIG_OSF_PARTITION */
-
-#ifdef CONFIG_SUN_PARTITION
-
-static int sun_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
-{
-	int i, csum;
-	unsigned short *ush;
-	struct buffer_head *bh;
-	struct sun_disklabel {
-		unsigned char info[128];   /* Informative text string */
-		unsigned char spare[292];  /* Boot information etc. */
-		unsigned short rspeed;     /* Disk rotational speed */
-		unsigned short pcylcount;  /* Physical cylinder count */
-		unsigned short sparecyl;   /* extra sects per cylinder */
-		unsigned char spare2[4];   /* More magic... */
-		unsigned short ilfact;     /* Interleave factor */
-		unsigned short ncyl;       /* Data cylinder count */
-		unsigned short nacyl;      /* Alt. cylinder count */
-		unsigned short ntrks;      /* Tracks per cylinder */
-		unsigned short nsect;      /* Sectors per track */
-		unsigned char spare3[4];   /* Even more magic... */
-		struct sun_partition {
-			__u32 start_cylinder;
-			__u32 num_sectors;
-		} partitions[8];
-		unsigned short magic;      /* Magic number */
-		unsigned short csum;       /* Label xor'd checksum */
-	} * label;		
-	struct sun_partition *p;
-	unsigned long spc;
-#define SUN_LABEL_MAGIC          0xDABE
-
-	if(!(bh = bread(dev, 0, get_ptable_blocksize(dev)))) {
-		printk("Dev %s: unable to read partition table\n",
-		       kdevname(dev));
-		return -1;
-	}
-	label = (struct sun_disklabel *) bh->b_data;
-	p = label->partitions;
-	if (be16_to_cpu(label->magic) != SUN_LABEL_MAGIC) {
-		printk("Dev %s Sun disklabel: bad magic %04x\n",
-		       kdevname(dev), be16_to_cpu(label->magic));
-		brelse(bh);
-		return 0;
-	}
-	/* Look at the checksum */
-	ush = ((unsigned short *) (label+1)) - 1;
-	for(csum = 0; ush >= ((unsigned short *) label);)
-		csum ^= *ush--;
-	if(csum) {
-		printk("Dev %s Sun disklabel: Csum bad, label corrupted\n",
-		       kdevname(dev));
-		brelse(bh);
-		return 0;
-	}
-	/* All Sun disks have 8 partition entries */
-	spc = be16_to_cpu(label->ntrks) * be16_to_cpu(label->nsect);
-	for(i=0; i < 8; i++, p++) {
-		unsigned long st_sector;
-		int num_sectors;
-
-		st_sector = first_sector + be32_to_cpu(p->start_cylinder) * spc;
-		num_sectors = be32_to_cpu(p->num_sectors);
-		if (num_sectors)
-			add_partition(hd, current_minor, st_sector, num_sectors);
-		current_minor++;
-	}
-	printk("\n");
-	brelse(bh);
-	return 1;
-}
-
-#endif /* CONFIG_SUN_PARTITION */
-
-#ifdef CONFIG_SGI_PARTITION
+extern void console_map_init(void);
+extern int soc_probe(void);
 
-static int sgi_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
+void __init device_init(void)
 {
-	int i, csum, magic;
-	unsigned int *ui, start, blocks, cs;
-	struct buffer_head *bh;
-	struct sgi_disklabel {
-		int magic_mushroom;         /* Big fat spliff... */
-		short root_part_num;        /* Root partition number */
-		short swap_part_num;        /* Swap partition number */
-		char boot_file[16];         /* Name of boot file for ARCS */
-		unsigned char _unused0[48]; /* Device parameter useless crapola.. */
-		struct sgi_volume {
-			char name[8];       /* Name of volume */
-			int  block_num;     /* Logical block number */
-			int  num_bytes;     /* How big, in bytes */
-		} volume[15];
-		struct sgi_partition {
-			int num_blocks;     /* Size in logical blocks */
-			int first_block;    /* First logical block */
-			int type;           /* Type of this partition */
-		} partitions[16];
-		int csum;                   /* Disk label checksum */
-		int _unused1;               /* Padding */
-	} *label;
-	struct sgi_partition *p;
-#define SGI_LABEL_MAGIC 0x0be5a941
-
-	if(!(bh = bread(dev, 0, get_ptable_blocksize(dev)))) {
-		printk("Dev %s: unable to read partition table\n", kdevname(dev));
-		return -1;
-	}
-	label = (struct sgi_disklabel *) bh->b_data;
-	p = &label->partitions[0];
-	magic = label->magic_mushroom;
-	if(be32_to_cpu(magic) != SGI_LABEL_MAGIC) {
-		printk("Dev %s SGI disklabel: bad magic %08x\n",
-		       kdevname(dev), magic);
-		brelse(bh);
-		return 0;
-	}
-	ui = ((unsigned int *) (label + 1)) - 1;
-	for(csum = 0; ui >= ((unsigned int *) label);) {
-		cs = *ui--;
-		csum += be32_to_cpu(cs);
-	}
-	if(csum) {
-		printk("Dev %s SGI disklabel: csum bad, label corrupted\n",
-		       kdevname(dev));
-		brelse(bh);
-		return 0;
-	}
-	/* All SGI disk labels have 16 partitions, disks under Linux only
-	 * have 15 minor's.  Luckily there are always a few zero length
-	 * partitions which we don't care about so we never overflow the
-	 * current_minor.
-	 */
-	for(i = 0; i < 16; i++, p++) {
-		blocks = be32_to_cpu(p->num_blocks);
-		start  = be32_to_cpu(p->first_block);
-		if(!blocks)
-			continue;
-		add_partition(hd, current_minor, start, blocks);
-		current_minor++;
-	}
-	printk("\n");
-	brelse(bh);
-	return 1;
-}
-
-#endif
-
-#ifdef CONFIG_AMIGA_PARTITION
-#include <linux/affs_hardblocks.h>
-
-static __inline__ u32
-checksum_block(u32 *m, int size)
-{
-	u32 sum = 0;
-
-	while (size--)
-		sum += htonl(*m++);
-	return sum;
-}
-
-static int
-amiga_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
-{
-	struct buffer_head	*bh;
-	struct RigidDiskBlock	*rdb;
-	struct PartitionBlock	*pb;
-	int			 start_sect;
-	int			 nr_sects;
-	int			 blk;
-	int			 part, res;
-	int			 old_blocksize;
-	int			 blocksize;
-
-	old_blocksize = get_ptable_blocksize(dev);
-	blocksize = get_hardsect_size(dev);
-
-	set_blocksize(dev,blocksize);
-	res = 0;
-
-	for (blk = 0; blk < RDB_ALLOCATION_LIMIT; blk++) {
-		if(!(bh = bread(dev,blk,blocksize))) {
-			printk("Dev %s: unable to read RDB block %d\n",
-			       kdevname(dev),blk);
-			goto rdb_done;
-		}
-		if (*(u32 *)bh->b_data == htonl(IDNAME_RIGIDDISK)) {
-			rdb = (struct RigidDiskBlock *)bh->b_data;
-			if (checksum_block((u32 *)bh->b_data,htonl(rdb->rdb_SummedLongs) & 0x7F)) {
-				/* Try again with 0xdc..0xdf zeroed, Windows might have
-				 * trashed it.
-				 */
-				*(u32 *)(&bh->b_data[0xdc]) = 0;
-				if (checksum_block((u32 *)bh->b_data,
-						htonl(rdb->rdb_SummedLongs) & 0x7F)) {
-					brelse(bh);
-					printk("Dev %s: RDB in block %d has bad checksum\n",
-					       kdevname(dev),blk);
-					continue;
-				}
-				printk("Warning: Trashed word at 0xd0 in block %d "
-					"ignored in checksum calculation\n",blk);
-			}
-			printk(" RDSK");
-			blk = htonl(rdb->rdb_PartitionList);
-			brelse(bh);
-			for (part = 1; blk > 0 && part <= 16; part++) {
-				if (!(bh = bread(dev,blk,blocksize))) {
-					printk("Dev %s: unable to read partition block %d\n",
-						       kdevname(dev),blk);
-					goto rdb_done;
-				}
-				pb  = (struct PartitionBlock *)bh->b_data;
-				blk = htonl(pb->pb_Next);
-				if (pb->pb_ID == htonl(IDNAME_PARTITION) && checksum_block(
-				    (u32 *)pb,htonl(pb->pb_SummedLongs) & 0x7F) == 0 ) {
-
-					/* Tell Kernel about it */
-
-					if (!(nr_sects = (htonl(pb->pb_Environment[10]) + 1 -
-							  htonl(pb->pb_Environment[9])) *
-							 htonl(pb->pb_Environment[3]) *
-							 htonl(pb->pb_Environment[5]))) {
-						brelse(bh);
-						continue;
-					}
-					start_sect = htonl(pb->pb_Environment[9]) *
-						     htonl(pb->pb_Environment[3]) *
-						     htonl(pb->pb_Environment[5]);
-					add_partition(hd,current_minor,start_sect,nr_sects);
-					current_minor++;
-					res = 1;
-				}
-				brelse(bh);
-			}
-			printk("\n");
-		}
-		else
-			brelse(bh);
-	}
-
-rdb_done:
-	set_blocksize(dev,old_blocksize);
-	return res;
-}
-#endif /* CONFIG_AMIGA_PARTITION */
-
-#ifdef CONFIG_MAC_PARTITION
-#include <linux/ctype.h>
-
-/*
- * Code to understand MacOS partition tables.
- */
-
-#define MAC_PARTITION_MAGIC	0x504d
-
-/* type field value for A/UX or other Unix partitions */
-#define APPLE_AUX_TYPE	"Apple_UNIX_SVR2"
-
-struct mac_partition {
-	__u16	signature;	/* expected to be MAC_PARTITION_MAGIC */
-	__u16	res1;
-	__u32	map_count;	/* # blocks in partition map */
-	__u32	start_block;	/* absolute starting block # of partition */
-	__u32	block_count;	/* number of blocks in partition */
-	char	name[32];	/* partition name */
-	char	type[32];	/* string type description */
-	__u32	data_start;	/* rel block # of first data block */
-	__u32	data_count;	/* number of data blocks */
-	__u32	status;		/* partition status bits */
-	__u32	boot_start;
-	__u32	boot_size;
-	__u32	boot_load;
-	__u32	boot_load2;
-	__u32	boot_entry;
-	__u32	boot_entry2;
-	__u32	boot_cksum;
-	char	processor[16];	/* identifies ISA of boot */
-	/* there is more stuff after this that we don't need */
-};
-
-#define MAC_STATUS_BOOTABLE	8	/* partition is bootable */
-
-#define MAC_DRIVER_MAGIC	0x4552
-
-/* Driver descriptor structure, in block 0 */
-struct mac_driver_desc {
-	__u16	signature;	/* expected to be MAC_DRIVER_MAGIC */
-	__u16	block_size;
-	__u32	block_count;
-    /* ... more stuff */
-};
-
-static int mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec)
-{
-	struct buffer_head *bh;
-	int blk, blocks_in_map;
-	int dev_bsize, dev_pos, pos;
-	unsigned secsize;
-#ifdef CONFIG_PPC
-	int first_bootable = 1;
-#endif
-	struct mac_partition *part;
-	struct mac_driver_desc *md;
-
-	dev_bsize = get_ptable_blocksize(dev);
-	dev_pos = 0;
-	/* Get 0th block and look at the first partition map entry. */
-	if ((bh = bread(dev, 0, dev_bsize)) == 0) {
-	    printk("%s: error reading partition table\n",
-		   kdevname(dev));
-	    return -1;
-	}
-	md = (struct mac_driver_desc *) bh->b_data;
-	if (be16_to_cpu(md->signature) != MAC_DRIVER_MAGIC) {
-		brelse(bh);
-		return 0;
-	}
-	secsize = be16_to_cpu(md->block_size);
-	if (secsize >= dev_bsize) {
-		brelse(bh);
-		dev_pos = secsize;
-		if ((bh = bread(dev, secsize/dev_bsize, dev_bsize)) == 0) {
-			printk("%s: error reading partition table\n",
-			       kdevname(dev));
-			return -1;
-		}
-	}
-	part = (struct mac_partition *) (bh->b_data + secsize - dev_pos);
-	if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) {
-		brelse(bh);
-		return 0;		/* not a MacOS disk */
-	}
-	blocks_in_map = be32_to_cpu(part->map_count);
-	for (blk = 1; blk <= blocks_in_map; ++blk) {
-		pos = blk * secsize;
-		if (pos >= dev_pos + dev_bsize) {
-			brelse(bh);
-			dev_pos = pos;
-			if ((bh = bread(dev, pos/dev_bsize, dev_bsize)) == 0) {
-				printk("%s: error reading partition table\n",
-				       kdevname(dev));
-				return -1;
-			}
-		}
-		part = (struct mac_partition *) (bh->b_data + pos - dev_pos);
-		if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC)
-			break;
-		blocks_in_map = be32_to_cpu(part->map_count);
-		add_partition(hd, current_minor,
-			fsec + be32_to_cpu(part->start_block) * (secsize/512),
-			be32_to_cpu(part->block_count) * (secsize/512));
-
-#ifdef CONFIG_PPC
-		/*
-		 * If this is the first bootable partition, tell the
-		 * setup code, in case it wants to make this the root.
-		 */
-		if ( (_machine == _MACH_Pmac) && first_bootable
-		    && (be32_to_cpu(part->status) & MAC_STATUS_BOOTABLE)
-		    && strcasecmp(part->processor, "powerpc") == 0) {
-			note_bootable_part(dev, blk);
-			first_bootable = 0;
-		}
-#endif /* CONFIG_PPC */
-
-		++current_minor;
-	}
-	brelse(bh);
-	printk("\n");
-	return 1;
-}
-
-#endif /* CONFIG_MAC_PARTITION */
-
-#ifdef CONFIG_ATARI_PARTITION
-#include <linux/atari_rootsec.h>
-
-/* ++guenther: this should be settable by the user ("make config")?.
- */
-#define ICD_PARTS
-
-static int atari_partition (struct gendisk *hd, kdev_t dev,
-			    unsigned long first_sector)
-{
-  int minor = current_minor, m_lim = current_minor + hd->max_p;
-  struct buffer_head *bh;
-  struct rootsector *rs;
-  struct partition_info *pi;
-  ulong extensect;
-  unsigned int psum;
-  int i;
-#ifdef ICD_PARTS
-  int part_fmt = 0; /* 0:unknown, 1:AHDI, 2:ICD/Supra */
-#endif
-
-  bh = bread (dev, 0, get_ptable_blocksize(dev));
-  if (!bh) {
-      printk (" unable to read block 0 (partition table)\n");
-      return -1;
-  }
-
-  /* Verify this is an Atari rootsector: */
-  psum=0;
-  for (i=0;i<256;i++) {
-    psum+=ntohs(((__u16 *) (bh->b_data))[i]);
-  }
-  if ((psum & 0xFFFF) != 0x1234) {
-    brelse(bh);
-    return 0;
-  }
-
-  rs = (struct rootsector *) bh->b_data;
-  pi = &rs->part[0];
-  printk (" AHDI");
-  for (; pi < &rs->part[4] && minor < m_lim; minor++, pi++)
-    {
-      if (pi->flg & 1)
-	/* active partition */
-	{
-	  if (memcmp (pi->id, "XGM", 3) == 0)
-	    /* extension partition */
-	    {
-	      struct rootsector *xrs;
-	      struct buffer_head *xbh;
-	      ulong partsect;
-
-#ifdef ICD_PARTS
-	      part_fmt = 1;
-#endif
-	      printk(" XGM<");
-	      partsect = extensect = ntohl(pi->st);
-	      while (1)
-		{
-		  xbh = bread (dev, partsect / 2, get_ptable_blocksize(dev));
-		  if (!xbh)
-		    {
-		      printk (" block %ld read failed\n", partsect);
-		      brelse(bh);
-		      return 0;
-		    }
-		  if (partsect & 1)
-		    xrs = (struct rootsector *) &xbh->b_data[512];
-		  else
-		    xrs = (struct rootsector *) &xbh->b_data[0];
-
-		  /* ++roman: sanity check: bit 0 of flg field must be set */
-		  if (!(xrs->part[0].flg & 1)) {
-		    printk( "\nFirst sub-partition in extended partition is not valid!\n" );
-		    break;
-		  }
-
-		  add_partition(hd, minor, partsect + ntohl(xrs->part[0].st),
-				ntohl(xrs->part[0].siz));
-
-		  if (!(xrs->part[1].flg & 1)) {
-		    /* end of linked partition list */
-		    brelse( xbh );
-		    break;
-		  }
-		  if (memcmp( xrs->part[1].id, "XGM", 3 ) != 0) {
-		    printk( "\nID of extended partition is not XGM!\n" );
-		    brelse( xbh );
-		    break;
-		  }
-
-		  partsect = ntohl(xrs->part[1].st) + extensect;
-		  brelse (xbh);
-		  minor++;
-		  if (minor >= m_lim) {
-		    printk( "\nMaximum number of partitions reached!\n" );
-		    break;
-		  }
-		}
-	      printk(" >");
-	    }
-	  else
-	    {
-	      /* we don't care about other id's */
-	      add_partition (hd, minor, ntohl(pi->st), ntohl(pi->siz));
-	    }
-	}
-    }
-#ifdef ICD_PARTS
-  if ( part_fmt!=1 ) /* no extended partitions -> test ICD-format */
-  {
-    pi = &rs->icdpart[0];
-    /* sanity check: no ICD format if first partition invalid */
-    if (memcmp (pi->id, "GEM", 3) == 0 ||
-        memcmp (pi->id, "BGM", 3) == 0 ||
-        memcmp (pi->id, "LNX", 3) == 0 ||
-        memcmp (pi->id, "SWP", 3) == 0 ||
-        memcmp (pi->id, "RAW", 3) == 0 )
-    {
-      printk(" ICD<");
-      for (; pi < &rs->icdpart[8] && minor < m_lim; minor++, pi++)
-      {
-        /* accept only GEM,BGM,RAW,LNX,SWP partitions */
-        if (pi->flg & 1 && 
-            (memcmp (pi->id, "GEM", 3) == 0 ||
-             memcmp (pi->id, "BGM", 3) == 0 ||
-             memcmp (pi->id, "LNX", 3) == 0 ||
-             memcmp (pi->id, "SWP", 3) == 0 ||
-             memcmp (pi->id, "RAW", 3) == 0) )
-        {
-          part_fmt = 2;
-	  add_partition (hd, minor, ntohl(pi->st), ntohl(pi->siz));
-        }
-      }
-      printk(" >");
-    }
-  }
-#endif
-  brelse (bh);
-
-  printk ("\n");
-
-  return 1;
-}
-#endif /* CONFIG_ATARI_PARTITION */
-
-#ifdef CONFIG_ULTRIX_PARTITION
-
-static int ultrix_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
-{
-	int i, minor = current_minor;
-	struct buffer_head *bh;
-	struct ultrix_disklabel {
-		s32	pt_magic;	/* magic no. indicating part. info exits */
-		s32	pt_valid;	/* set by driver if pt is current */
-		struct  pt_info {
-			s32		pi_nblocks; /* no. of sectors */
-			u32		pi_blkoff;  /* block offset for start */
-		} pt_part[8];
-	} *label;
-
-#define PT_MAGIC	0x032957	/* Partition magic number */
-#define PT_VALID	1		/* Indicates if struct is valid */
-
-#define	SBLOCK	((unsigned long)((16384 - sizeof(struct ultrix_disklabel)) \
-                  /get_ptable_blocksize(dev)))
-
-	bh = bread (dev, SBLOCK, get_ptable_blocksize(dev));
-	if (!bh) {
-		printk (" unable to read block 0x%lx\n", SBLOCK);
-		return -1;
-	}
-	
-	label = (struct ultrix_disklabel *)(bh->b_data
-                                            + get_ptable_blocksize(dev)
-                                            - sizeof(struct ultrix_disklabel));
-
-	if (label->pt_magic == PT_MAGIC && label->pt_valid == PT_VALID) {
-		for (i=0; i<8; i++, minor++)
-			if (label->pt_part[i].pi_nblocks)
-				add_partition(hd, minor, 
-					      label->pt_part[i].pi_blkoff,
-					      label->pt_part[i].pi_nblocks);
-		brelse(bh);
-		printk ("\n");
-		return 1;
-	} else {
-		brelse(bh);
-		return 0;
-	}
-}
-
-#endif /* CONFIG_ULTRIX_PARTITION */
-
-static void check_partition(struct gendisk *hd, kdev_t dev)
-{
-	static int first_time = 1;
-	unsigned long first_sector;
-	char buf[40];
-
-	if (first_time)
-		printk(KERN_INFO "Partition check:\n");
-	first_time = 0;
-	first_sector = hd->part[MINOR(dev)].start_sect;
-
-	/*
-	 * This is a kludge to allow the partition check to be
-	 * skipped for specific drives (e.g. IDE CD-ROM drives)
-	 */
-	if ((int)first_sector == -1) {
-		hd->part[MINOR(dev)].start_sect = 0;
-		return;
-	}
-
-	printk(KERN_INFO " %s:", disk_name(hd, MINOR(dev), buf));
-#ifdef CONFIG_MSDOS_PARTITION
-	if (msdos_partition(hd, dev, first_sector))
-		return;
-#endif
-#ifdef CONFIG_OSF_PARTITION
-	if (osf_partition(hd, dev, first_sector))
-		return;
-#endif
-#ifdef CONFIG_SUN_PARTITION
-	if(sun_partition(hd, dev, first_sector))
-		return;
-#endif
-#ifdef CONFIG_AMIGA_PARTITION
-	if(amiga_partition(hd, dev, first_sector))
-		return;
-#endif
-#ifdef CONFIG_ATARI_PARTITION
-	if(atari_partition(hd, dev, first_sector))
-		return;
-#endif
-#ifdef CONFIG_MAC_PARTITION
-	if (mac_partition(hd, dev, first_sector))
-		return;
-#endif
-#ifdef CONFIG_SGI_PARTITION
-	if(sgi_partition(hd, dev, first_sector))
-		return;
-#endif
-#ifdef CONFIG_ULTRIX_PARTITION
-	if(ultrix_partition(hd, dev, first_sector))
-		return;
-#endif
-	printk(" unknown partition table\n");
-}
-
-/* This function is used to re-read partition tables for removable disks.
-   Much of the cleanup from the old partition tables should have already been
-   done */
-
-/* This function will re-read the partition tables for a given device,
-and set things back up again.  There are some important caveats,
-however.  You must ensure that no one is using the device, and no one
-can start using the device while this function is being executed. */
-
-void resetup_one_dev(struct gendisk *dev, int drive)
-{
-	int i;
-	int first_minor	= drive << dev->minor_shift;
-	int end_minor	= first_minor + dev->max_p;
-
-	blk_size[dev->major] = NULL;
-	current_minor = 1 + first_minor;
-	check_partition(dev, MKDEV(dev->major, first_minor));
-
- 	/*
- 	 * We need to set the sizes array before we will be able to access
- 	 * any of the partitions on this device.
- 	 */
-	if (dev->sizes != NULL) {	/* optional safeguard in ll_rw_blk.c */
-		for (i = first_minor; i < end_minor; i++)
-			dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
-		blk_size[dev->major] = dev->sizes;
-	}
-}
-
-static inline void setup_dev(struct gendisk *dev)
-{
-	int i, drive;
-	int end_minor	= dev->max_nr * dev->max_p;
-
-	blk_size[dev->major] = NULL;
-	for (i = 0; i < end_minor; i++) {
-		dev->part[i].start_sect = 0;
-		dev->part[i].nr_sects = 0;
-		dev->sizes[i] = 0;
-	}
-	dev->init(dev);	
-	for (drive = 0; drive < dev->nr_real; drive++)
-		resetup_one_dev(dev, drive);
-}
-
-static int __init device_setup(void)
-{
-	extern void console_map_init(void);
-	extern void cpqarray_init(void);
-#ifdef CONFIG_PARPORT
-	extern int parport_init(void) __init;
-#endif
-#ifdef CONFIG_MD_BOOT
-        extern void md_setup_drive(void) __init;
-#endif
-#ifdef CONFIG_FC4_SOC
-	extern int soc_probe(void);
-#endif
-	struct gendisk *p;
-
 #ifdef CONFIG_PARPORT
 	parport_init();
 #endif
@@ -1431,43 +54,4 @@
 #ifdef CONFIG_VT
 	console_map_init();
 #endif
-
-	for (p = gendisk_head ; p ; p=p->next)
-		setup_dev(p);
-
-#ifdef CONFIG_BLK_DEV_RAM
-#ifdef CONFIG_BLK_DEV_INITRD
-	if (initrd_start && mount_initrd) initrd_load();
-	else
-#endif
-	rd_load();
-#endif
-#ifdef CONFIG_MD_BOOT
-        md_setup_drive();
-#endif
-	return 0;
 }
-
-__initcall(device_setup);
-
-#ifdef CONFIG_PROC_FS
-int get_partition_list(char * page)
-{
-	struct gendisk *p;
-	char buf[40];
-	int n, len;
-
-	len = sprintf(page, "major minor  #blocks  name\n\n");
-	for (p = gendisk_head; p; p = p->next) {
-		for (n=0; n < (p->nr_real << p->minor_shift); n++) {
-			if (p->part[n].nr_sects && len < PAGE_SIZE - 80) {
-				len += sprintf(page+len,
-					       "%4d  %4d %10d %s\n",
-					       p->major, n, p->sizes[n],
-					       disk_name(p, n, buf));
-			}
-		}
-	}
-	return len;
-}
-#endif
diff -u --recursive --new-file v2.3.13/linux/drivers/block/hd.c linux/drivers/block/hd.c
--- v2.3.13/linux/drivers/block/hd.c	Mon Aug  9 14:59:19 1999
+++ linux/drivers/block/hd.c	Thu Aug 12 11:50:14 1999
@@ -27,7 +27,6 @@
 /* Uncomment the following if you want verbose error reports. */
 /* #define VERBOSE_ERRORS */
   
-#include <asm/irq.h>
 #include <linux/errno.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
@@ -52,7 +51,9 @@
 
 #ifdef __arm__
 #undef  HD_IRQ
+#endif
 #include <asm/irq.h>
+#ifdef __arm__
 #define HD_IRQ IRQ_HARDDISK
 #endif
 
diff -u --recursive --new-file v2.3.13/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v2.3.13/linux/drivers/block/ide.c	Mon Aug  9 14:59:19 1999
+++ linux/drivers/block/ide.c	Wed Aug 18 16:14:46 1999
@@ -39,7 +39,7 @@
  *  October, 1994 -- Complete line-by-line overhaul for linux 1.1.x, by:
  *
  *	Mark Lord	(mlord@pobox.com)		(IDE Perf.Pkg)
- *	Delman Lee	(delman@mipg.upenn.edu)		("Mr. atdisk2")
+ *	Delman Lee	(delman@ieee.org)		("Mr. atdisk2")
  *	Scott Snyder	(snyder@fnald0.fnal.gov)	(ATAPI IDE cd-rom)
  *
  *  This was a rewrite of just about everything from hd.c, though some original
@@ -434,8 +434,8 @@
 void atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount)
 {
 	++bytecount;
-#ifdef CONFIG_ATARI
-	if (MACH_IS_ATARI) {
+#if defined(CONFIG_ATARI) || defined(CONFIG_Q40)
+	if (MACH_IS_ATARI || MACH_IS_Q40) {
 		/* Atari has a byte-swapped IDE interface */
 		insw_swapw(IDE_DATA_REG, buffer, bytecount / 2);
 		return;
@@ -449,8 +449,8 @@
 void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount)
 {
 	++bytecount;
-#ifdef CONFIG_ATARI
-	if (MACH_IS_ATARI) {
+#if defined(CONFIG_ATARI) || defined(CONFIG_Q40)
+	if (MACH_IS_ATARI || MACH_IS_Q40) {
 		/* Atari has a byte-swapped IDE interface */
 		outsw_swapw(IDE_DATA_REG, buffer, bytecount / 2);
 		return;
diff -u --recursive --new-file v2.3.13/linux/drivers/block/md.c linux/drivers/block/md.c
--- v2.3.13/linux/drivers/block/md.c	Mon Aug  9 14:59:19 1999
+++ linux/drivers/block/md.c	Thu Aug 12 10:16:28 1999
@@ -740,7 +740,7 @@
 		if (buffer_locked(bh))
 			return 0;
 		set_bit(BH_Lock, &bh->b_state);
-		if (rw == WRITE || rw == WRITEA) {
+		if (rw == WRITE) {
 			if (!buffer_dirty(bh)) {
 				bh->b_end_io(bh, test_bit(BH_Uptodate, &bh->b_state));
 				return 0;
diff -u --recursive --new-file v2.3.13/linux/drivers/block/raid1.c linux/drivers/block/raid1.c
--- v2.3.13/linux/drivers/block/raid1.c	Wed Jun 30 13:38:19 1999
+++ linux/drivers/block/raid1.c	Thu Aug 12 10:16:28 1999
@@ -159,7 +159,7 @@
 	}
 
 	/*
-	 * WRITE or WRITEA.
+	 * WRITE.
 	 */
 	PRINTK(("raid1_end_request(), write branch.\n"));
 
@@ -215,15 +215,14 @@
 	memset (r1_bh, 0, sizeof (struct raid1_bh));
 
 /*
- * make_request() can abort the operation when READA or WRITEA are being
+ * make_request() can abort the operation when READA is being
  * used and no empty request is available.
  *
  * Currently, just replace the command with READ/WRITE.
  */
 	if (rw == READA) rw = READ;
-	if (rw == WRITEA) rw = WRITE;
 
-	if (rw == WRITE || rw == WRITEA)
+	if (rw == WRITE)
 		mark_buffer_clean(bh);		/* Too early ? */
 
 /*
@@ -269,7 +268,7 @@
 	}
 
 	/*
-	 * WRITE or WRITEA.
+	 * WRITE.
 	 */
 	PRINTK(("raid1_make_request(n=%d), write branch.\n",n));
 
diff -u --recursive --new-file v2.3.13/linux/drivers/block/raid5.c linux/drivers/block/raid5.c
--- v2.3.13/linux/drivers/block/raid5.c	Wed Jun 30 13:38:19 1999
+++ linux/drivers/block/raid5.c	Thu Aug 12 10:16:28 1999
@@ -1206,7 +1206,6 @@
 	struct stripe_head *sh;
 
 	if (rw == READA) rw = READ;
-	if (rw == WRITEA) rw = WRITE;
 
 	new_sector = raid5_compute_sector(bh->b_rsector, raid_disks, data_disks,
 						&dd_idx, &pd_idx, raid_conf);
diff -u --recursive --new-file v2.3.13/linux/drivers/block/z2ram.c linux/drivers/block/z2ram.c
--- v2.3.13/linux/drivers/block/z2ram.c	Mon Aug  9 14:59:19 1999
+++ linux/drivers/block/z2ram.c	Thu Aug 12 11:50:14 1999
@@ -27,7 +27,6 @@
 
 #define MAJOR_NR    Z2RAM_MAJOR
 
-#include <linux/config.h>
 #include <linux/major.h>
 #include <linux/malloc.h>
 #include <linux/blk.h>
diff -u --recursive --new-file v2.3.13/linux/drivers/char/adbmouse.c linux/drivers/char/adbmouse.c
--- v2.3.13/linux/drivers/char/adbmouse.c	Mon Aug  9 14:59:19 1999
+++ linux/drivers/char/adbmouse.c	Thu Aug 12 11:50:14 1999
@@ -40,7 +40,7 @@
 #ifdef __powerpc__
 #include <asm/processor.h>
 #endif
-#ifdef __mc68000__
+#if defined(__mc68000__) || defined(MODULE)
 #include <asm/setup.h>
 #endif
 
@@ -186,8 +186,6 @@
 }
 
 #ifdef MODULE
-#include <asm/setup.h>
-
 int init_module(void)
 {
 	return adb_mouse_init();
diff -u --recursive --new-file v2.3.13/linux/drivers/char/busmouse.c linux/drivers/char/busmouse.c
--- v2.3.13/linux/drivers/char/busmouse.c	Mon Aug  9 14:59:19 1999
+++ linux/drivers/char/busmouse.c	Sun Aug 15 11:48:40 1999
@@ -380,7 +380,7 @@
 	if (busmouse_data[msedev])
 		return -EBUSY;
 
-	mse = kmalloc(GFP_KERNEL, sizeof(*mse));
+	mse = kmalloc(sizeof(*mse), GFP_KERNEL);
 	if (!mse)
 		return -ENOMEM;
 
@@ -465,6 +465,7 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(busmouse_add_movementbuttons);
 EXPORT_SYMBOL(busmouse_add_movement);
 EXPORT_SYMBOL(busmouse_add_buttons);
 EXPORT_SYMBOL(register_busmouse);
diff -u --recursive --new-file v2.3.13/linux/drivers/char/console.c linux/drivers/char/console.c
--- v2.3.13/linux/drivers/char/console.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/char/console.c	Fri Aug 13 12:19:25 1999
@@ -1984,7 +1984,7 @@
 	static unsigned long printing = 0;
 	const ushort *start;
 	ushort cnt = 0;
-	ushort myx = x;
+	ushort myx;
 
 	/* console busy or not yet initialized */
 	if (!printable || test_and_set_bit(0, &printing))
@@ -1992,6 +1992,10 @@
 
 	if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1))
 		currcons = kmsg_redirect - 1;
+
+	/* read `x' only after setting currecons properly (otherwise
+	   the `x' macro will read the x of the foreground console). */
+	myx = x;
 
 	if (!vc_cons_allocated(currcons)) {
 		/* impossible */
diff -u --recursive --new-file v2.3.13/linux/drivers/char/defkeymap.c linux/drivers/char/defkeymap.c
--- v2.3.13/linux/drivers/char/defkeymap.c	Fri Feb 24 11:38:27 1995
+++ linux/drivers/char/defkeymap.c	Thu Aug 12 10:17:17 1999
@@ -233,6 +233,7 @@
 	{'A', 'A', '\305'},	{'a', 'a', '\345'},
 	{'A', 'E', '\306'},	{'a', 'e', '\346'},
 	{',', 'C', '\307'},	{',', 'c', '\347'},
+	{'\'', 'C', '\307'},	{'\'', 'c', '\347'},
 	{'`', 'E', '\310'},	{'`', 'e', '\350'},
 	{'\'', 'E', '\311'},	{'\'', 'e', '\351'},
 	{'^', 'E', '\312'},	{'^', 'e', '\352'},
@@ -259,4 +260,4 @@
 	{'s', 'z', '\337'},	{'i', 'j', '\377'},
 };
 
-unsigned int accent_table_size = 68;
+unsigned int accent_table_size = 70;
diff -u --recursive --new-file v2.3.13/linux/drivers/char/ftape/lowlevel/ftape-setup.c linux/drivers/char/ftape/lowlevel/ftape-setup.c
--- v2.3.13/linux/drivers/char/ftape/lowlevel/ftape-setup.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/char/ftape/lowlevel/ftape-setup.c	Thu Aug 12 11:53:22 1999
@@ -60,12 +60,15 @@
 	{ "mach2",     &ft_mach2,          CONFIG_FT_MACH2,          0,     1}
 };
 
-void __init ftape_setup(char *str, int *ints)
+static int __init ftape_setup(char *str)
 {
 	int i;
 	int param;
+	int ints[2];
+
 	TRACE_FUN(ft_t_flow);
 
+	str = get_options(str, ARRAY_SIZE(ints), ints);
 	if (str) {
 		for (i=0; i < NR_ITEMS(config_params); i++) {
 			if (strcmp(str,config_params[i].name) == 0){
@@ -81,13 +84,13 @@
 					      config_params[i].name,
 					      config_params[i].min,
 					      config_params[i].max);
-					TRACE_EXIT;
+					goto out;
 				}
 				if(config_params[i].var) {
 					TRACE(ft_t_info, "%s=%d", str, param);
 					*config_params[i].var = param;
 				}
-				TRACE_EXIT;
+				goto out;
 			}
 		}
 	}
@@ -101,5 +104,8 @@
 	} else {
 		TRACE(ft_t_err, "botched ftape option");
 	}
-	TRACE_EXIT;
+ out:
+	TRACE_EXIT 1;
 }
+
+__setup("ftape=", ftape_setup);
diff -u --recursive --new-file v2.3.13/linux/drivers/char/lp_intern.c linux/drivers/char/lp_intern.c
--- v2.3.13/linux/drivers/char/lp_intern.c	Mon Aug  9 14:59:20 1999
+++ linux/drivers/char/lp_intern.c	Wed Dec 31 16:00:00 1969
@@ -1,364 +0,0 @@
-
-/*
- * split into mid and low-level for better support of different hardware
- * by Joerg Dorchain (dorchain@mpi-sb.mpg.de)
- *
- * Amiga printer device by Michael Rausch (linux@uni-koblenz.de);
- * Atari support added by Andreas Schwab (schwab@ls5.informatik.uni-dortmund.de);
- * based upon work from
- *
- * Copyright (C) 1992 by Jim Weigand and Linus Torvalds
- * Copyright (C) 1992,1993 by Michael K. Johnson
- * - Thanks much to Gunter Windau for pointing out to me where the error
- *   checking ought to be.
- * Copyright (C) 1993 by Nigel Gamble (added interrupt code)
- */
-
-#include <linux/module.h>
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <asm/irq.h>
-#include <asm/setup.h>
-#ifdef CONFIG_AMIGA
-#include <asm/amigahw.h>
-#include <asm/amigaints.h>
-#endif
-#ifdef CONFIG_ATARI
-#include <linux/delay.h>
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#endif
-#ifdef CONFIG_MVME16x
-#include <asm/mvme16xhw.h>
-#endif
-#ifdef CONFIG_BVME6000
-#include<asm/bvme6000hw.h>
-#endif
-#include <linux/lp_intern.h>
-
-static int minor = -1;
-MODULE_PARM(minor,"i");
-
-static void lp_int_out(int, int);
-static int lp_int_busy(int);
-static int lp_int_pout(int);
-static int lp_int_online(int);
-
-
-static void
-lp_int_out (int c, int dev)
-{
-  switch (m68k_machtype)
-    {
-#ifdef CONFIG_AMIGA
-    case MACH_AMIGA:
-       {
-	int wait = 0;
-	while (wait != lp_table[dev]->wait) wait++;
-	ciaa.prb = c;
-       }
-      break;
-#endif
-#ifdef CONFIG_ATARI
-    case MACH_ATARI:
-       {
-	 int wait = 0;
-	 sound_ym.rd_data_reg_sel = 15;
-	 sound_ym.wd_data = c;
-	 sound_ym.rd_data_reg_sel = 14;
-	 while (wait != lp_table[dev]->wait) wait++;
-	 sound_ym.wd_data = sound_ym.rd_data_reg_sel & ~(1 << 5);
-	 while (wait) wait--;
-	 sound_ym.wd_data = sound_ym.rd_data_reg_sel | (1 << 5);
-	 break;
-       }
-#endif
-#ifdef CONFIG_MVME16x
-    case MACH_MVME16x:
-      {
-	int wait = 0;
-	while (wait != lp_table[dev]->wait) wait++;
-        mvmelp.data = c;
-        break;
-      }
-#endif
-#ifdef CONFIG_BVME6000
-    case MACH_BVME6000:
-      {
-	int wait = 0;
-	while (wait != lp_table[dev]->wait) wait++;
-        bvmepit.padr = c;
-        bvmepit.pacr |= 0x02;
-        break;
-      }
-#endif
-    }
-}
-
-static int
-lp_int_busy (int dev)
-{
-  switch (m68k_machtype)
-    {
-#ifdef CONFIG_AMIGA
-    case MACH_AMIGA:
-      return ciab.pra & 1;
-#endif
-#ifdef CONFIG_ATARI
-    case MACH_ATARI:
-      return mfp.par_dt_reg & 1;
-#endif
-#ifdef CONFIG_MVME16x
-    case MACH_MVME16x:
-      return mvmelp.isr & 1;
-#endif
-#ifdef CONFIG_BVME6000
-    case MACH_BVME6000:
-      return 0 /* !(bvmepit.psr & 0x40) */ ;
-#endif
-    default:
-      return 0;
-    }
-}
-
-static int
-lp_int_pout (int dev)
-{
-  switch (m68k_machtype)
-    {
-#ifdef CONFIG_AMIGA
-    case MACH_AMIGA:
-      return ciab.pra & 2;
-#endif
-#ifdef CONFIG_ATARI
-    case MACH_ATARI:
-      return 0;
-#endif
-#ifdef CONFIG_MVME16x
-    case MACH_MVME16x:
-      return mvmelp.isr & 2;
-#endif
-#ifdef CONFIG_BVME6000
-    case MACH_BVME6000:
-      return 0;
-#endif
-    default:
-      return 0;
-    }
-}
-
-static int
-lp_int_online (int dev)
-{
-  switch (m68k_machtype)
-    {
-#ifdef CONFIG_AMIGA
-    case MACH_AMIGA:
-      return ciab.pra & 4;
-#endif
-#ifdef CONFIG_ATARI
-    case MACH_ATARI:
-      return !(mfp.par_dt_reg & 1);
-#endif
-#ifdef CONFIG_MVME16x
-    case MACH_MVME16x:
-      return mvmelp.isr & 4;
-#endif
-#ifdef CONFIG_BVME6000
-    case MACH_BVME6000:
-      return 1;
-#endif
-    default:
-      return 0;
-    }
-}
-
-static void lp_int_interrupt(int irq, void *data, struct pt_regs *fp)
-{
-#ifdef CONFIG_MVME16x
-  if (MACH_IS_MVME16x)
-    mvmelp.ack_icr |= 0x08;
-#endif
-#ifdef CONFIG_BVME6000
-  if (MACH_IS_BVME6000)
-    bvmepit.pacr &= ~0x02;
-#endif
-  lp_interrupt(minor);
-}
-
-static int lp_int_open(int dev)
-{
-  MOD_INC_USE_COUNT;
-  return 0;
-}
-
-static void lp_int_release(int dev)
-{
-  MOD_DEC_USE_COUNT;
-}
-
-static struct lp_struct tab = {
-	"Builtin parallel port",	/* name */
-	0,				/* irq */
-	lp_int_out,
-	lp_int_busy,
-	lp_int_pout,
-	lp_int_online,
-	0,
-	NULL,				/* ioctl */
-	lp_int_open,
-	lp_int_release,
-	LP_EXIST,
-	LP_INIT_CHAR,
-	LP_INIT_TIME,
-	LP_INIT_WAIT,
-	NULL,
-	NULL,
-};
-
-int __init lp_internal_init(void)
-{
-#ifdef CONFIG_AMIGA
-  if (MACH_IS_AMIGA && AMIGAHW_PRESENT(AMI_PARALLEL))
-    {
-      ciaa.ddrb = 0xff;
-      ciab.ddra &= 0xf8;
-      if (lp_irq)
-        tab.irq = request_irq(IRQ_AMIGA_CIAA_FLG, lp_int_interrupt,
-          0, "builtin printer port", lp_int_interrupt);
-      tab.base = (void *) &ciaa.prb; /* dummy, not used */
-      tab.type = LP_AMIGA;
-    }
-#endif
-#ifdef CONFIG_ATARI
-  if (MACH_IS_ATARI)
-    {
-      unsigned long flags;
-
-      save_flags(flags);
-      cli();
-      sound_ym.rd_data_reg_sel = 7;
-      sound_ym.wd_data = (sound_ym.rd_data_reg_sel & 0x3f) | 0xc0;
-      restore_flags(flags);
-      if (lp_irq)
-        tab.irq = request_irq(IRQ_MFP_BUSY, lp_int_interrupt,
-          IRQ_TYPE_SLOW, "builtin printer port", lp_int_interrupt);
-      tab.base = (void *) &sound_ym.wd_data; /* dummy, not used */
-      tab.type = LP_ATARI;
-    }
-#endif
-#ifdef CONFIG_MAC
-    if (MACH_IS_MAC)
-    	return -ENODEV;
-#endif
-#ifdef CONFIG_MVME16x
-    if (MACH_IS_MVME16x)
-    {
-      unsigned long flags;
-
-      if (!(mvme16x_config & MVME16x_CONFIG_GOT_LP))
-        return -ENODEV;
-
-      save_flags(flags);
-      cli();
-      mvmelp.ack_icr = 0x08;
-      mvmelp.flt_icr = 0x08;
-      mvmelp.sel_icr = 0x08;
-      mvmelp.pe_icr =  0x08;
-      mvmelp.bsy_icr = 0x08;
-      mvmelp.cr =      0x10;
-      mvmelp.ack_icr = 0xd9; /* Int on trailing edge of ACK */
-      restore_flags(flags);
-
-      if (lp_irq)
-        tab.irq = request_irq(MVME167_IRQ_PRN, lp_int_interrupt,
-          0, "builtin printer port", lp_int_interrupt);
-      tab.base = (void *)&mvmelp; /* dummy, not used */
-      tab.type = LP_MVME167;
-    }
-#endif
-#ifdef CONFIG_BVME6000
-    if (MACH_IS_BVME6000)
-    {
-      unsigned long flags;
-
-      save_flags(flags);
-      cli();
-      bvmepit.pgcr =   0x0f;
-      bvmepit.psrr =   0x18;
-      bvmepit.paddr =  0xff;
-      bvmepit.pcdr  =  (bvmepit.pcdr & 0xfc) | 0x02;
-      bvmepit.pcddr |= 0x03;
-      bvmepit.pacr =   0x78;
-      bvmepit.pbcr =   0x00;
-      bvmepit.pivr =   BVME_IRQ_PRN;
-      bvmepit.pgcr =   0x1f;
-      restore_flags(flags);
-
-      if (lp_irq)
-        tab.irq = request_irq(BVME_IRQ_PRN, lp_int_interrupt,
-          0, "builtin printer port", lp_int_interrupt);
-      tab.base = (void *)&bvmepit; /* dummy, not used */
-      tab.type = LP_BVME6000;
-    }
-#endif
-
-
-  if ((minor = register_parallel(&tab, minor)) < 0) {
-    printk("builtin lp init: cant get a minor\n");
-    if (lp_irq) {
-#ifdef CONFIG_AMIGA
-      if (MACH_IS_AMIGA)
-	free_irq(IRQ_AMIGA_CIAA_FLG, lp_int_interrupt);
-#endif
-#ifdef CONFIG_ATARI
-      if (MACH_IS_ATARI)
-	free_irq(IRQ_MFP_BUSY, lp_int_interrupt);
-#endif
-#ifdef CONFIG_MVME16x
-      if (MACH_IS_MVME16x)
-        free_irq(MVME167_IRQ_PRN, lp_int_interrupt);
-#endif
-#ifdef CONFIG_BVME6000
-      if (MACH_IS_BVME6000)
-        free_irq(BVME_IRQ_PRN, lp_int_interrupt);
-#endif
-    }
-    return -ENODEV;
-  }
-  
-  return 0;
-}
-
-#ifdef MODULE
-int init_module(void)
-{
-return lp_internal_init();
-}
-
-void cleanup_module(void)
-{
-if (lp_irq) {
-#ifdef CONFIG_AMIGA
-  if (MACH_IS_AMIGA)
-    free_irq(IRQ_AMIGA_CIAA_FLG, lp_int_interrupt);
-#endif
-#ifdef CONFIG_ATARI
-  if (MACH_IS_ATARI)
-    free_irq(IRQ_MFP_BUSY, lp_int_interrupt);
-#endif
-#ifdef CONFIG_MVME16x
-  if (MACH_IS_MVME16x)
-    free_irq(MVME167_IRQ_PRN, lp_int_interrupt);
-#endif
-#ifdef CONFIG_BVME6000
-  if (MACH_IS_BVME6000)
-    free_irq(BVME_IRQ_PRN, lp_int_interrupt);
-#endif
-}
-unregister_parallel(minor);
-}
-#endif
diff -u --recursive --new-file v2.3.13/linux/drivers/char/lp_m68k.c linux/drivers/char/lp_m68k.c
--- v2.3.13/linux/drivers/char/lp_m68k.c	Mon Aug  9 14:59:20 1999
+++ linux/drivers/char/lp_m68k.c	Wed Dec 31 16:00:00 1969
@@ -1,556 +0,0 @@
-/*
- * split in two parts for better support of different hardware
- * by Joerg Dorchain (dorchain@mpi-sb.mpg.de)
- *
- * Amiga printer device by Michael Rausch (linux@uni-koblenz.de);
- * Atari support added by Andreas Schwab (schwab@ls5.informatik.uni-dortmund.de);
- * based upon work from
- *
- * Copyright (C) 1992 by Jim Weigand and Linus Torvalds
- * Copyright (C) 1992,1993 by Michael K. Johnson
- * - Thanks much to Gunter Windau for pointing out to me where the error
- *   checking ought to be.
- * Copyright (C) 1993 by Nigel Gamble (added interrupt code)
- */
-
-/* 01/17/95: Matthias Welwarsky (dg8y@rs11.hrz.th-darmstadt.de)
- * lp_write(): rewritten from scratch
- * lp_interrupt(): fixed cli()/sti()-bug
- * 
- * 95/05/28: Andreas Schwab (schwab@issan.informatik.uni-dortmund.de)
- * lp_write() fixed to make it work again.
- * 95/08/18: Andreas Schwab
- * lp_write_interrupt: fix race condition
- *
- *  * CAUTION, please do check! *    
- * 
- *  on 68000-based machines sti() must NEVER appear in interrupt driven
- *  code. The 68k-CPU has a priority-based interrupt scheme. while an interrupt
- *  with a certain priority is executed, all requests with lower or same
- *  priority get locked out. executing the sti()-macro allows ANY interrupt
- *  to be served. this really causes BIG trouble!
- *  to protect an interrupt driven routine against being interrupted 
- *  (if absolutely needed!) one should use save_flags();cli()/restore_flags()!
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/kmod.h>
-
-#ifdef CONFIG_AMIGA
-#ifdef CONFIG_MULTIFACE_III_LP
-#include <linux/lp_mfc.h>
-#endif
-#endif
-
-#include <linux/lp_m68k.h>
-#include <linux/lp_intern.h>
-#include <linux/malloc.h>
-#include <linux/interrupt.h>
-
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-
-/*
- *  why bother around with the pio driver when the interrupt works;
- *  so, for "security" reasons only, it's configurable here.
- *  saves some bytes, at least ...
- */
-#define FORCE_POLLING	 0
-#define FORCE_INTERRUPT	 1
-/*
- *  PREFER_INTERRUPT doesn't make much sense on m68k.
- *  it is preserved here in case of joining with the i386 driver
- *
-#define PREFER_INTERRUPT 2
- */
-
-#define WHICH_DRIVER	FORCE_INTERRUPT
-
-struct lp_struct *lp_table[MAX_LP] = {NULL,};
-
-static int max_lp; /* the real number of devices */
-
-/* 
- * All my debugging code assumes that you debug with only one printer at
- * a time. RWWH
- */
-
-#define LP_DEBUG 
-#undef LP_DEBUG 
-
-
-#if WHICH_DRIVER != FORCE_INTERRUPT
-#ifdef LP_DEBUG
-static int lp_max_count = 1;
-#endif
-
-static int lp_char_polled(char lpchar, int dev)
-{
-	unsigned long count  = 0; 
-
-	do {
-		count ++;
-		if (current->need_resched)
-			schedule();
-	} while (lp_table[dev]->lp_is_busy(dev) && count < lp_table[dev]->chars);
-
-	if (count == lp_table[dev]->chars) {
-		return 0;
-		/* we timed out, and the character was /not/ printed */
-	}
-#ifdef LP_DEBUG
-	if (count > lp_max_count) {
-		printk("lp success after %d counts.\n",count);
-		lp_max_count = count;
-	}
-#endif
-	lp_table[dev]->lp_out(lpchar, dev);
-	return 1;
-}
-#endif
-
-
-#ifdef LP_DEBUG
-unsigned int lp_total_chars = 0;
-unsigned int lp_last_call = 0;
-#endif
-
-
-#if WHICH_DRIVER != FORCE_POLLING
-static __inline__ int lp_char_interrupt(char lpchar, int dev)
-{
-	if (!lp_table[dev]->lp_is_busy(dev)) {
-		lp_table[dev]->lp_out(lpchar,dev);
-		return 1;
-	}
-	return 0;
-}
-
-static int lp_error;
-
-void lp_interrupt(int dev)
-{
-    if (dev >= 0 && dev < MAX_LP && lp_table[dev]->do_print)
-    {
-	if (lp_table[dev]->copy_size)
-	{
-    		unsigned long flags;
-		save_flags(flags);
-		cli();
-		if (lp_char_interrupt(lp_table[dev]->lp_buffer[lp_table[dev]->bytes_written], dev)) {
-			--lp_table[dev]->copy_size;
-			++lp_table[dev]->bytes_written;
-			restore_flags(flags);
-		}
-		else
-		{
-			lp_table[dev]->do_print = 0;
-			restore_flags(flags);
-			lp_error = 1;
-			wake_up_interruptible(&lp_table[dev]->lp_wait_q);
-		}
-	}
-	else
-	{
-		lp_table[dev]->do_print = 0;
-		lp_error = 0;
-		wake_up_interruptible(&lp_table[dev]->lp_wait_q);
-	}
-
-    }
-}
-
-#if WHICH_DRIVER == FORCE_INTERRUPT
-static ssize_t lp_write(struct file *file, const char *buf,
-			size_t count, loff_t *ppos)
-#else
-static ssize_t lp_write_interrupt(struct file *file, const char *buf,
-				  size_t count, loff_t *ppos)
-#endif
-{
-  struct inode *inode = file->f_dentry->d_inode;
-  unsigned long total_bytes_written = 0;
-  unsigned int flags;
-  long timeout;
-  int rc;
-  int dev = MINOR(inode->i_rdev);
-
-  do {
-    lp_table[dev]->do_print = 0;		/* disable lp_interrupt()   */
-    lp_table[dev]->bytes_written = 0;	/* init buffer read-pointer */
-    lp_error = 0;
-    lp_table[dev]->copy_size = (count <= LP_BUFFER_SIZE ? count : LP_BUFFER_SIZE);
-    if (copy_from_user(lp_table[dev]->lp_buffer, buf,
-		       lp_table[dev]->copy_size))
-      return -EFAULT;
-    while (lp_table[dev]->copy_size) {
-      save_flags(flags);
-      cli();				/* no interrupts now */
-      lp_table[dev]->do_print = 1;	/* enable lp_interrupt() */
-      if (lp_char_interrupt(lp_table[dev]->lp_buffer[lp_table[dev]->bytes_written], dev)) {
-	++lp_table[dev]->bytes_written;
-	--lp_table[dev]->copy_size;
-	lp_error = 0;
-      } else {				/* something went wrong   */
-	lp_table[dev]->do_print = 0;	/* disable lp_interrupt() */
-	lp_error = 1;			/* printer caused error   */
-      }
-      if (lp_error) {
-
-	  /* something blocked printing, so we don't want to sleep too long,
-	     in case we have to rekick the interrupt */
-
-	  timeout = LP_TIMEOUT_POLLED;
-      } else {
-	  timeout = LP_TIMEOUT_INTERRUPT;
-      }
-  
-      interruptible_sleep_on_timeout(&lp_table[dev]->lp_wait_q, timeout);
-      restore_flags(flags);
-  
-      /* we're up again and running. we first disable lp_interrupt(), then
-	 check what happened meanwhile */
-
-      lp_table[dev]->do_print = 0;
-      rc = total_bytes_written + lp_table[dev]->bytes_written;
-
-      if (signal_pending(current)) {
-	if (rc == 0)
-	  rc = -EINTR;
-	return rc;
-      }
-      if (lp_error) {
-
-	/* an error has occurred, maybe in lp_interrupt().
-	   figure out the type of error, exit on request or if nothing has 
-	   been printed at all. */
-	
-	if (lp_table[dev]->lp_has_pout(dev)) {
-	  printk(KERN_NOTICE "lp%d: paper-out\n",dev);
-	  if (!rc) rc = -ENOSPC;
-	} else if (!lp_table[dev]->lp_is_online(dev)) {
-	  printk(KERN_NOTICE "lp%d: off-line\n",dev);
-	  if (!rc) rc = -EIO;
-	} else if (lp_table[dev]->lp_is_busy(dev)) {
-	  printk(KERN_NOTICE "lp%d: on fire\n",dev);
-	  if (!rc) rc = -EIO;
-	}
-	if (lp_table[dev]->flags & LP_ABORT)
-	  return rc;
-      }
-      /* check if our buffer was completely printed, if not, most likely
-	 an unsolved error blocks the printer. As we can`t do anything
-	 against, we start all over again. Else we set the read-pointer
-	 of the buffer and count the printed characters */
-      
-      if (!lp_table[dev]->copy_size) {
-	total_bytes_written += lp_table[dev]->bytes_written;
-	buf += lp_table[dev]->bytes_written;
-	count -= lp_table[dev]->bytes_written;
-      }
-    }
-  } while (count > 0);
-  return total_bytes_written;
-}
-#else
-void (*lp_interrupt)() = NULL;
-#endif
-
-#if WHICH_DRIVER != FORCE_INTERRUPT
-#if WHICH_DRIVER == FORCE_POLLING
-static ssize_t lp_write(struct file *file, const char *buf,
-			size_t count, loff_t *ppos)
-#else
-static ssize_t lp_write_polled(struct file *file, const char *buf,
-			size_t count, loff_t *ppos)
-#endif
-{
-	struct inode *inode = file->f_dentry->d_inode;
-	char *temp = buf;
-	int dev = MINOR(inode->i_rdev);
-
-#ifdef LP_DEBUG
-	if (time_after(jiffies, lp_last_call + lp_table[dev]->time)) {
-		lp_total_chars = 0;
-		lp_max_count = 1;
-	}
-	lp_last_call = jiffies;
-#endif
-
-	temp = buf;
-	while (count > 0) {
-		int c;
-		if (get_user(c, temp))
-			return -EFAULT;
-		if (lp_char_polled(c, dev)) {
-			/* only update counting vars if character was printed */
-			count--; temp++;
-#ifdef LP_DEBUG
-			lp_total_chars++;
-#endif
-		} else { /* if printer timed out */
-			unsigned long timeout = LP_TIMEOUT_POLLED;
-			int error = 0;
-			if (lp_table[dev]->lp_has_pout(dev)) {
-				printk(KERN_NOTICE "lp%d: out of paper\n",dev);
-				if (lp_table[dev]->flags & LP_ABORT)
-					error = -ENOSPC;
-			} else if (!lp_table[dev]->lp_is_online(dev)) {
-				printk(KERN_NOTICE "lp%d: off-line\n",dev);
-				if (lp_table[dev]->flags & LP_ABORT)
-					error = -EIO;
-			} else
-	                /* not offline or out of paper. on fire? */
-			if (lp_table[dev]->lp_is_busy(dev)) {
-				printk(KERN_NOTICE "lp%d: on fire\n",dev);
-				if (lp_table[dev]->flags & LP_ABORT)
-					error = -EIO;
-			}
-			else
-				timeout = lp_table[dev]->time;
-
-			/* check for signals before going to sleep */
-			if (error == 0 && signal_pending(current))
-				error = -EINTR;
-			if (error) {
-				if (temp != buf)
-					return temp-buf;
-				else
-					return error;
-			}
-
-#ifdef LP_DEBUG
-			printk("lp sleeping at %d characters for %d jiffies\n",
-				lp_total_chars, timeout);
-			lp_total_chars = 0;
-#endif
-			current->state = TASK_INTERRUPTIBLE;
-			schedule_timeout(timeout);
-		}
-	}
-	return temp - buf;
-}
-#endif
-
-unsigned int lp_irq = 0;
-
-#if WHICH_DRIVER == PREFER_INTERRUPT
-static ssize_t lp_write(struct file *file, const char *buf, size_t count,
-			loff_t *ppos)
-{
-	if (lp_irq)
-		return lp_write_interrupt(file, buf, count, ppos);
-	else
-		return lp_write_polled(file, buf, count, ppos);
-}
-#endif
-
-static long long lp_lseek(struct file * file, long long offset, int origin)
-{
-	return -ESPIPE;
-}
-
-static int lp_open(struct inode *inode, struct file *file)
-{
-	int dev = MINOR(inode->i_rdev);
-	int ret;
-
-	MOD_INC_USE_COUNT;
-
-	ret = -ENODEV;
-	if (dev >= MAX_LP)
-		goto out_err;
-
-	if (!lp_table[dev]) {
-		char modname[30];
-
-		sprintf(modname, "char-major-%d-%d", LP_MAJOR, dev);
-		request_module(modname);
-	}
-	if (!lp_table[dev])
-		goto out_err;
-	if (!(lp_table[dev]->flags & LP_EXIST))
-		goto out_err;
-	ret = -EBUSY;
-	if (lp_table[dev]->flags & LP_BUSY)
-		goto out_err;
-
-	lp_table[dev]->flags |= LP_BUSY;
-
-	ret = lp_table[dev]->lp_open(dev);
-	if (ret != 0) {
-		lp_table[dev]->flags &= ~LP_BUSY;
-		goto out_err;
-	}
-	return ret;
-
-out_err:
-	MOD_DEC_USE_COUNT;
-	return ret;
-}
-
-static int lp_release(struct inode *inode, struct file *file)
-{
-	int dev =MINOR(inode->i_rdev);
-
-	lp_table[dev]->flags &= ~LP_BUSY;
-	lp_table[dev]->lp_release(dev);
-	MOD_DEC_USE_COUNT;
-	return 0;
-}
-
-
-static int lp_ioctl(struct inode *inode, struct file *file,
-		    unsigned int cmd, unsigned long arg)
-{
-	unsigned int minor = MINOR(inode->i_rdev);
-	int retval = -ENODEV;
-
-#ifdef LP_DEBUG
-	printk("lp%d ioctl, cmd: 0x%x, arg: 0x%x\n", minor, cmd, arg);
-#endif
-	if (minor >= max_lp)
-		goto out;
-	if (!(lp_table[minor]->flags & LP_EXIST))
-		goto out;
-	retval = 0;
-	switch (cmd) {
-	case LPTIME:
-		lp_table[minor]->time = arg;
-		break;
-	case LPCHAR:
-		lp_table[minor]->chars = arg;
-		break;
-	case LPABORT:
-		if (arg)
-			lp_table[minor]->flags |= LP_ABORT;
-		else
-			lp_table[minor]->flags &= ~LP_ABORT;
-		break;
-	case LPWAIT:
-		lp_table[minor]->wait = arg;
-		break;
-	case LPSETIRQ:
-	case LPGETIRQ:
-	        retval = lp_irq;
-		break;
-	default:
-		retval = -EINVAL;
-		if (lp_table[minor]->lp_ioctl)
-			retval = lp_table[minor]->lp_ioctl(minor, cmd, arg);
-	}
-out:
-	return retval;
-}
-
-
-static struct file_operations lp_fops = {
-	lp_lseek,
-	NULL,		/* lp_read */
-	lp_write,
-	NULL,		/* lp_readdir */
-	NULL,		/* lp_poll */
-	lp_ioctl,
-	NULL,		/* lp_mmap */
-	lp_open,
-	NULL,		/* flush */
-	lp_release
-};
-
-EXPORT_SYMBOL(lp_table);
-EXPORT_SYMBOL(lp_irq);
-EXPORT_SYMBOL(lp_interrupt);
-EXPORT_SYMBOL(register_parallel);
-EXPORT_SYMBOL(unregister_parallel);
-
-int __init lp_m68k_init(void)
-{
-	extern char m68k_debug_device[];
-
-	if (!strcmp( m68k_debug_device, "par" ))
-		return -EBUSY;
-
-	if (register_chrdev(LP_MAJOR,"lp", &lp_fops)) {
-		printk(KERN_ERR "unable to get major %d for line printer\n", LP_MAJOR);
-		return -ENXIO;
-	}
-
-#if WHICH_DRIVER == FORCE_POLLING
-	lp_irq = 0;
-	printk(KERN_INFO "lp_init: lp using polling driver\n");
-#else
-
-	lp_irq = 1;
-	printk(KERN_INFO "lp_init: lp using interrupt driver\n");
-#endif
-
-#ifndef MODULE
-	lp_internal_init();
-#ifdef CONFIG_MULTIFACE_III_LP
-	lp_mfc_init();
-#endif
-#endif
-	return 0;
-}
-
-/*
- * Currently we do not accept any lp-parameters, but that may change.
- */
-void __init lp_setup(char *str, int *ints)
-{	
-}
-
-#ifdef MODULE
-int init_module(void)
-{
-	return lp_m68k_init();
-}
-
-void cleanup_module(void)
-{
-	unregister_chrdev(LP_MAJOR, "lp");
-}
-#endif
-
-/*
- * (un-)register for hardware drivers
- * tab is an inititalised lp_struct, dev the desired minor
- * if dev < 0, let the driver choose the first free minor
- * if successful return the minor, else -1
- */
-int register_parallel(struct lp_struct *tab, int dev)
-{
-if (dev < 0) {
-	dev = 0;
-	while ((dev < MAX_LP) && (lp_table[dev] != NULL))
-		dev++;
-}
-if (dev > MAX_LP)
-	return -1;
-if (lp_table[dev] != NULL)
-	return -1;
-lp_table[dev] = tab;
-printk(KERN_INFO "lp%d: %s at 0x%08lx\n", dev, tab->name, (long)tab->base);
-return dev;
-}
-
-#ifdef CONFIG_MODULES
-void unregister_parallel(int dev)
-{
-if ((dev < 0) || (dev > MAX_LP) || (lp_table[dev] == NULL))
-	printk(KERN_ERR "WARNING: unregister_parallel for non-existant device ignored!\n");
-else
-	lp_table[dev] = NULL;
-}
-#endif
diff -u --recursive --new-file v2.3.13/linux/drivers/char/mem.c linux/drivers/char/mem.c
--- v2.3.13/linux/drivers/char/mem.c	Mon Aug  9 14:59:20 1999
+++ linux/drivers/char/mem.c	Thu Aug 12 10:41:30 1999
@@ -465,17 +465,12 @@
 	return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
 }
 
-static int open_mem(struct inode * inode, struct file * filp)
-{
-	return (capable(CAP_SYS_RAWIO)
-		|| !(filp->f_mode & FMODE_WRITE)) ? 0 : -EPERM;
-}
-
 #define mmap_kmem	mmap_mem
 #define zero_lseek	null_lseek
 #define full_lseek      null_lseek
 #define write_zero	write_null
 #define read_full       read_zero
+#define open_mem	open_port
 #define open_kmem	open_mem
 
 static struct file_operations mem_fops = {
diff -u --recursive --new-file v2.3.13/linux/drivers/char/q40_keyb.c linux/drivers/char/q40_keyb.c
--- v2.3.13/linux/drivers/char/q40_keyb.c	Mon Aug  9 14:59:20 1999
+++ linux/drivers/char/q40_keyb.c	Sun Aug 15 11:48:32 1999
@@ -240,32 +240,15 @@
 
 
 
-int q40kbd_pretranslate(unsigned char scancode, char raw_mode)
-{
-	if (scancode == 0xff) {
-		/* in scancode mode 1, my ESC key generates 0xff */
-		/* the calculator keys on a FOCUS 9000 generate 0xff */
-#ifndef KBD_IS_FOCUS_9000
-#ifdef KBD_REPORT_ERR
-		if (!raw_mode)
-		  printk(KERN_DEBUG "Keyboard error\n");
-#endif
-#endif
-		prev_scancode = 0;
-		return 0;
-	}
 
-	if (scancode == 0xe0 || scancode == 0xe1) {
+int q40kbd_translate(unsigned char scancode, unsigned char *keycode,
+		    char raw_mode)
+{
+  	if (scancode == 0xe0 || scancode == 0xe1) {
 		prev_scancode = scancode;
 		return 0;
  	}
- 	return 1;
-}
 
-int q40kbd_translate(unsigned char scancode, unsigned char *keycode,
-		    char raw_mode)
-{
-  /*printk("translate ...\n");*/
 	if (prev_scancode) {
 	  /*
 	   * usually it will be 0xe0, but a Pause key generates
@@ -376,7 +359,7 @@
 		if (qcode == 0xe0)
 		  {
 		    qprev=0xe0;
-		    handle_scancode(qprev);
+		    handle_scancode(qprev , 1);
 		    goto exit;
 		  }
 		
@@ -394,7 +377,7 @@
 		if (scancode==0xff)  /* SySrq */
 		  scancode=SYSRQ_KEY;
 
-		handle_scancode(scancode | (keyup ? 0200 : 0));
+		handle_scancode(scancode, ! keyup );
 		keyup=0;
 		mark_bh(KEYBOARD_BH);
 
diff -u --recursive --new-file v2.3.13/linux/drivers/i2o/i2o_lan.c linux/drivers/i2o/i2o_lan.c
--- v2.3.13/linux/drivers/i2o/i2o_lan.c	Mon Aug  9 14:59:20 1999
+++ linux/drivers/i2o/i2o_lan.c	Wed Aug 18 11:38:59 1999
@@ -54,7 +54,7 @@
 #endif
 
 #define MAX_LAN_CARDS 4
-static struct device *i2o_landevs[MAX_LAN_CARDS+1];
+static struct net_device *i2o_landevs[MAX_LAN_CARDS+1];
 static int unit = -1; 			/* device unit number */
 
 struct i2o_lan_local {
@@ -63,7 +63,7 @@
 	int reply_flag; 		/* needed by scalar/table queries */
 	u32 packet_tresh;		/* treshold for incoming skb's */	
 	struct fddi_statistics stats;   /* see also struct net_device_stats */ 
-	unsigned short (*type_trans)(struct sk_buff *, struct device *);
+	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
@@ -73,8 +73,8 @@
 };
 
 /* function prototypes */
-static int i2o_lan_receive_post(struct device *dev);
-static int i2o_lan_receive_post_reply(struct device *dev, struct i2o_message *m);
+static int i2o_lan_receive_post(struct net_device *dev);
+static int i2o_lan_receive_post_reply(struct net_device *dev, struct i2o_message *m);
 static void i2o_lan_release_buckets(u32 *msg, struct i2o_lan_local *priv);
 
 /*
@@ -89,7 +89,7 @@
 {  
 	u32 *msg = (u32 *)m;
 	u8 unit  = (u8)(msg[2]>>16); // InitiatorContext
-	struct device *dev = i2o_landevs[unit];
+	struct net_device *dev = i2o_landevs[unit];
 	struct i2o_lan_local *priv; 
 
 	if(dev)
@@ -202,7 +202,7 @@
 static int lan_context;
 
 
-static int i2o_lan_receive_post_reply(struct device *dev, struct i2o_message *m)
+static int i2o_lan_receive_post_reply(struct net_device *dev, struct i2o_message *m)
 {
 	u32 *msg = (u32 *)m;
 	struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
@@ -284,7 +284,7 @@
 /* 
  * i2o_lan_receive_post(): Post buckets to receive packets.
  */
-static int i2o_lan_receive_post(struct device *dev)
+static int i2o_lan_receive_post(struct net_device *dev)
 {	
 	struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;	
 	struct i2o_device *i2o_dev = priv->i2o_dev;
@@ -343,7 +343,7 @@
  * i2o_lan_reset(): Reset the LAN adapter into the operational state and 
  * 	restore it to full operation.
  */
-static int i2o_lan_reset(struct 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;
@@ -367,7 +367,7 @@
  * 	Reply to any LAN class message with status error_no_data_transfer 
  *	/ suspended.
  */
-static int i2o_lan_suspend(struct device *dev)
+static int i2o_lan_suspend(struct net_device *dev)
 {
 	struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;	
 	struct i2o_device *i2o_dev = priv->i2o_dev;
@@ -390,7 +390,7 @@
 /*
  * Set DDM into batch mode.
  */
-static void i2o_set_batch_mode(struct device *dev)
+static void i2o_set_batch_mode(struct net_device *dev)
 {
 
 /* 
@@ -436,7 +436,7 @@
  * i2o_lan_open(): Open the device to send/receive packets via 
  * the network device.	
  */
-static int i2o_lan_open(struct device *dev)
+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;	
@@ -470,7 +470,7 @@
 /*
  * i2o_lan_close(): End the transfering.
  */ 
-static int i2o_lan_close(struct device *dev)
+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;	
@@ -503,7 +503,7 @@
  * 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 device *dev)
+static int i2o_lan_sdu_send(struct sk_buff *skb, struct net_device *dev)
 {	
 #if 0
 /* not yet tested */
@@ -550,7 +550,7 @@
  * 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 device *dev)
+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;	
 	struct i2o_device *i2o_dev = priv->i2o_dev;	
@@ -583,7 +583,7 @@
 	return 0;
 }
 
-static struct net_device_stats *i2o_lan_get_stats(struct device *dev)
+static struct net_device_stats *i2o_lan_get_stats(struct net_device *dev)
 {
 	struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;	
 	struct i2o_device *i2o_dev = priv->i2o_dev;
@@ -709,7 +709,7 @@
  * i2o_lan_set_multicast_list(): Enable a network device to receive packets
  *	not send to the protocol address.
  */
-static void i2o_lan_set_multicast_list(struct device *dev)
+static void i2o_lan_set_multicast_list(struct net_device *dev)
 {
 	struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;	
 	struct i2o_device *i2o_dev = priv->i2o_dev;
@@ -805,13 +805,13 @@
 	return;
 }
 
-struct device *i2o_lan_register_device(struct i2o_device *i2o_dev)
+struct net_device *i2o_lan_register_device(struct i2o_device *i2o_dev)
 {
-	struct device *dev = NULL;
+	struct net_device *dev = NULL;
 	struct i2o_lan_local *priv = NULL;
 	u8 hw_addr[8];
-	unsigned short (*type_trans)(struct sk_buff *, struct device *);
-	void (*unregister_dev)(struct device *dev);
+	unsigned short (*type_trans)(struct sk_buff *, struct net_device *);
+	void (*unregister_dev)(struct net_device *dev);
 
 	switch (i2o_dev->subclass)
 	{
@@ -844,10 +844,10 @@
 #ifdef CONFIG_FDDI
 	case I2O_LAN_FDDI:
 	{
-		int size = sizeof(struct device) + sizeof(struct i2o_lan_local)
+		int size = sizeof(struct net_device) + sizeof(struct i2o_lan_local)
 			   + sizeof("fddi%d ");
 
-        	dev = (struct device *) kmalloc(size, GFP_KERNEL);
+        	dev = (struct net_device *) kmalloc(size, GFP_KERNEL);
         	memset((char *)dev, 0, size);
             	dev->priv = (void *)(dev + 1);
                 dev->name = (char *)(dev + 1) + sizeof(struct i2o_lan_local);
@@ -922,7 +922,7 @@
 
 __init int i2o_lan_init(void)
 {
-	struct device *dev;
+	struct net_device *dev;
 	int i;
 
 	bucketpost = bucketpost - bucketthresh;
@@ -987,7 +987,7 @@
 
 	for (i = 0; i <= unit; i++)
 	{
-		struct device *dev = i2o_landevs[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;	
 
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/Config.in linux/drivers/isdn/Config.in
--- v2.3.13/linux/drivers/isdn/Config.in	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/Config.in	Thu Aug 12 09:42:33 1999
@@ -9,6 +9,10 @@
   fi
 fi
 bool 'Support audio via ISDN' CONFIG_ISDN_AUDIO
+if [ "$CONFIG_ISDN_AUDIO" != "n" ]; then
+  bool 'Support AT-Fax Class 2 commands' CONFIG_ISDN_TTY_FAX
+fi
+bool 'Support isdn diversion services' CONFIG_ISDN_DIVERSION
 if [ "$CONFIG_X25" != "n" ]; then
   bool 'X.25 PLP on top of ISDN (EXPERIMENTAL)' CONFIG_ISDN_X25
 fi
@@ -26,7 +30,6 @@
     bool 'HiSax Support for german 1TR6' CONFIG_HISAX_1TR6
     bool 'HiSax Support for Teles 16.0/8.0' CONFIG_HISAX_16_0
     bool 'HiSax Support for Teles 16.3 or PNP or PCMCIA' CONFIG_HISAX_16_3
-    bool 'HiSax Support for Teles 16.3c' CONFIG_HISAX_TELES3C 
     bool 'HiSax Support for Teles PCI' CONFIG_HISAX_TELESPCI 
     bool 'HiSax Support for Teles S0Box' CONFIG_HISAX_S0BOX 
     bool 'HiSax Support for AVM A1 (Fritz)' CONFIG_HISAX_AVM_A1
@@ -37,24 +40,39 @@
     bool 'HiSax Support for Eicon.Diehl Diva cards' CONFIG_HISAX_DIEHLDIVA
     bool 'HiSax Support for ASUSCOM cards' CONFIG_HISAX_ASUSCOM
     bool 'HiSax Support for TELEINT cards' CONFIG_HISAX_TELEINT
-    bool 'HiSax Support for Sedlbauer speed card/win/star/fax' CONFIG_HISAX_SEDLBAUER
+    bool 'HiSax Support for HFC-S based cards' CONFIG_HISAX_HFCS
+    bool 'HiSax Support for Sedlbauer cards' CONFIG_HISAX_SEDLBAUER
     bool 'HiSax Support for USR Sportster internal TA' CONFIG_HISAX_SPORTSTER
     bool 'HiSax Support for MIC card' CONFIG_HISAX_MIC
     bool 'HiSax Support for NETjet card' CONFIG_HISAX_NETJET
     bool 'HiSax Support for Niccy PnP/PCI card' CONFIG_HISAX_NICCY
+    bool 'HiSax Support for Siemens I-Surf card' CONFIG_HISAX_ISURF
+    bool 'HiSax Support for HST Saphir card' CONFIG_HISAX_HSTSAPHIR
+    bool 'HiSax Support for Telekom A4T card' CONFIG_HISAX_BKM_A4T
+    bool 'HiSax Support for Scitel Quadro card' CONFIG_HISAX_SCT_QUADRO
+    bool 'HiSax Support for Gazel cards' CONFIG_HISAX_GAZEL
     if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
-      if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
-        bool 'HiSax Support for Am7930' CONFIG_HISAX_AMD7930
-      fi
+	bool 'HiSax Support for HFC PCI-Bus cards (EXPERIMENTAL)' CONFIG_HISAX_HFC_PCI
+#	bool 'HiSax Support for TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU
+	if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
+		bool 'HiSax Support for Am7930' CONFIG_HISAX_AMD7930
+	fi
     fi
 fi
 if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
 	dep_tristate 'Spellcaster support (EXPERIMENTAL)' CONFIG_ISDN_DRV_SC $CONFIG_ISDN
 	dep_tristate 'IBM Active 2000 support (EXPERIMENTAL)' CONFIG_ISDN_DRV_ACT2000 $CONFIG_ISDN
-	dep_tristate 'Eicon.Diehl active card support (EXPERIMENTAL)' CONFIG_ISDN_DRV_EICON $CONFIG_ISDN
 fi
-dep_tristate 'AVM-B1 with CAPI2.0 support' CONFIG_ISDN_DRV_AVMB1 $CONFIG_ISDN
+dep_tristate 'Eicon.Diehl active card support' CONFIG_ISDN_DRV_EICON $CONFIG_ISDN
+if [ "$CONFIG_ISDN_DRV_EICON" != "n" ]; then
+    bool 'Eicon S,SX,SCOM,Quadro,S2M support' CONFIG_ISDN_DRV_EICON_ISA
+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 B1/M1/M2 PCMCIA support' CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
     bool 'Verbose reason code reporting (kernel size +=7K)' CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON
 fi
 
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/Makefile linux/drivers/isdn/Makefile
--- v2.3.13/linux/drivers/isdn/Makefile	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/Makefile	Thu Aug 12 09:42:33 1999
@@ -1,6 +1,6 @@
 SUB_DIRS     :=
 MOD_SUB_DIRS :=
-ALL_SUB_DIRS := icn pcbit hisax avmb1 act2000 eicon
+ALL_SUB_DIRS := icn pcbit hisax avmb1 act2000 eicon divert
 
 L_OBJS :=
 LX_OBJS :=
@@ -24,6 +24,9 @@
   endif
   ifdef CONFIG_ISDN_AUDIO
     L_OBJS += isdn_audio.o
+    ifdef CONFIG_ISDN_TTY_FAX
+      L_OBJS += isdn_ttyfax.o
+    endif
   endif
 else
   ifeq ($(CONFIG_ISDN),m)
@@ -41,8 +44,17 @@
     endif  
     ifdef CONFIG_ISDN_AUDIO
       O_OBJS += isdn_audio.o
+      ifdef CONFIG_ISDN_TTY_FAX
+        O_OBJS += isdn_ttyfax.o
+      endif
     endif
   endif
+endif
+
+ifeq ($(CONFIG_ISDN_DIVERSION),y)
+ ifeq ($(CONFIG_MODULES),y)
+    MOD_SUB_DIRS += divert
+ endif
 endif
 
 ifeq ($(CONFIG_ISDN_DRV_HISAX),y)
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/avmb1/Makefile linux/drivers/isdn/avmb1/Makefile
--- v2.3.13/linux/drivers/isdn/avmb1/Makefile	Thu May 29 21:53:05 1997
+++ linux/drivers/isdn/avmb1/Makefile	Thu Aug 12 09:42:33 1999
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile,v 1.4 1997/03/30 17:10:40 calle Exp $
+# $Id: Makefile,v 1.6 1999/07/20 06:41:44 calle Exp $
 #
 # Makefile for the CAPI and AVM-B1 device drivers.
 #
@@ -11,6 +11,26 @@
 # parent makes..
 #
 # $Log: Makefile,v $
+# 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.
+#
+# Revision 1.5  1999/07/01 15:26:20  calle
+# complete new version (I love it):
+# + new hardware independed "capi_driver" interface that will make it easy to:
+#   - support other controllers with CAPI-2.0 (i.e. USB Controller)
+#   - write a CAPI-2.0 for the passive cards
+#   - support serial link CAPI-2.0 boxes.
+# + wrote "capi_driver" for all supported cards.
+# + "capi_driver" (supported cards) now have to be configured with
+#   make menuconfig, in the past all supported cards where included
+#   at once.
+# + new and better informations in /proc/capi/
+# + new ioctl to switch trace of capi messages per controller
+#   using "avmcapictrl trace [contr] on|off|...."
+# + complete testcircle with all supported cards and also the
+#   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+#
 # Revision 1.4  1997/03/30 17:10:40  calle
 # added support for AVM-B1-PCI card.
 #
@@ -56,20 +76,38 @@
 
 ifeq ($(CONFIG_ISDN_DRV_AVMB1),y)
   O_TARGET += avmb1.o
-  O_OBJS   += capi.o b1lli.o
-  OX_OBJS  += capiutil.o b1capi.o capidrv.o
-  ifdef CONFIG_PCI
-  OX_OBJS  += b1pci.o
+  OX_OBJS  += kcapi.o
+  O_OBJS   += capi.o
+  ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA
+  O_OBJS   += b1isa.o
+  endif
+  ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI
+  O_OBJS  += b1pci.o
+  endif
+  ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA
+  O_OBJS   += t1isa.o
+  endif
+  ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
+  OX_OBJS   += b1pcmcia.o
   endif
+  OX_OBJS  += capiutil.o capidrv.o b1.o
 else
   ifeq ($(CONFIG_ISDN_DRV_AVMB1),m)
   O_TARGET += kernelcapi.o
-  O_OBJS   += b1lli.o
-  OX_OBJS  += b1capi.o
+  OX_OBJS  += kcapi.o
   M_OBJS   += capi.o kernelcapi.o
-  MX_OBJS  += capiutil.o capidrv.o
-  ifdef CONFIG_PCI
-  MX_OBJS  += b1pci.o
+  ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA
+  M_OBJS   += b1isa.o
+  endif
+  ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI
+  M_OBJS  += b1pci.o
+  endif
+  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
   endif
 endif
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/avmb1/avmcard.h linux/drivers/isdn/avmb1/avmcard.h
--- v2.3.13/linux/drivers/isdn/avmb1/avmcard.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/avmb1/avmcard.h	Thu Aug 12 09:42:33 1999
@@ -0,0 +1,559 @@
+/*
+ * $Id: avmcard.h,v 1.4 1999/08/04 10:10:08 calle Exp $
+ *
+ * Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
+ *
+ * $Log: avmcard.h,v $
+ * Revision 1.4  1999/08/04 10:10:08  calle
+ * Bugfix: corrected /proc functions, added structure for new AVM cards.
+ *
+ * Revision 1.3  1999/07/23 08:41:47  calle
+ * prepared for new AVM cards.
+ *
+ * Revision 1.2  1999/07/05 15:09:45  calle
+ * - renamed "appl_release" to "appl_released".
+ * - version und profile data now cleared on controller reset
+ * - extended /proc interface, to allow driver and controller specific
+ *   informations to include by driver hackers.
+ *
+ * Revision 1.1  1999/07/01 15:26:22  calle
+ * complete new version (I love it):
+ * + new hardware independed "capi_driver" interface that will make it easy to:
+ *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ *   - write a CAPI-2.0 for the passive cards
+ *   - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ *   make menuconfig, in the past all supported cards where included
+ *   at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ *   using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+ *
+ */
+
+#ifndef _AVMCARD_H_
+#define _AVMCARD_H_
+
+#define	AVMB1_PORTLEN		0x1f
+#define AVM_MAXVERSION		8
+#define AVM_NAPPS		30
+#define AVM_NCCI_PER_CHANNEL	4
+
+/*
+ * Versions
+ */
+
+#define	VER_DRIVER	0
+#define	VER_CARDTYPE	1
+#define	VER_HWID	2
+#define	VER_SERIAL	3
+#define	VER_OPTION	4
+#define	VER_PROTO	5
+#define	VER_PROFILE	6
+#define	VER_CAPI	7
+
+enum avmcardtype {
+	avm_b1isa,
+	avm_b1pci,
+	avm_b1pcmcia,
+	avm_m1,
+	avm_m2,
+	avm_t1isa,
+	avm_t1pci,
+	avm_c4
+};
+
+typedef struct avmcard_dmainfo {
+	__u32 recvlen;   
+	__u8  recvbuf[128+2048];
+	struct sk_buff_head send_queue;
+	__u8  sendbuf[128+2048];
+} avmcard_dmainfo;
+
+typedef struct avmcard {
+	char name[32];
+	unsigned int port;
+	unsigned irq;
+	unsigned long membase;
+	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;
+	avmcard_dmainfo *dma;
+
+	struct capi_ctr *ctrl;
+} avmcard;
+
+extern int b1_irq_table[16];
+
+/*
+ * LLI Messages to the ISDN-ControllerISDN Controller 
+ */
+
+#define	SEND_POLL		0x72	/*
+					   * after load <- RECEIVE_POLL 
+					 */
+#define SEND_INIT		0x11	/*
+					   * first message <- RECEIVE_INIT
+					   * int32 NumApplications  int32
+					   * NumNCCIs int32 BoardNumber 
+					 */
+#define SEND_REGISTER		0x12	/*
+					   * register an application int32
+					   * ApplIDId int32 NumMessages
+					   * int32 NumB3Connections int32
+					   * NumB3Blocks int32 B3Size
+					   * 
+					   * AnzB3Connection != 0 &&
+					   * AnzB3Blocks >= 1 && B3Size >= 1 
+					 */
+#define SEND_RELEASE		0x14	/*
+					   * deregister an application int32 
+					   * ApplID 
+					 */
+#define SEND_MESSAGE		0x15	/*
+					   * send capi-message int32 length
+					   * capi-data ... 
+					 */
+#define SEND_DATA_B3_REQ	0x13	/*
+					   * send capi-data-message int32
+					   * MsgLength capi-data ... int32
+					   * B3Length data .... 
+					 */
+
+#define SEND_CONFIG		0x21    /*
+                                         */
+
+#define SEND_POLLACK		0x73    /* T1 Watchdog */
+
+/*
+ * LLI Messages from the ISDN-ControllerISDN Controller 
+ */
+
+#define RECEIVE_POLL		0x32	/*
+					   * <- after SEND_POLL 
+					 */
+#define RECEIVE_INIT		0x27	/*
+					   * <- after SEND_INIT int32 length
+					   * byte total length b1struct board 
+					   * driver revision b1struct card
+					   * type b1struct reserved b1struct
+					   * serial number b1struct driver
+					   * capability b1struct d-channel
+					   * protocol b1struct CAPI-2.0
+					   * profile b1struct capi version 
+					 */
+#define RECEIVE_MESSAGE		0x21	/*
+					   * <- after SEND_MESSAGE int32
+					   * AppllID int32 Length capi-data
+					   * .... 
+					 */
+#define RECEIVE_DATA_B3_IND	0x22	/*
+					   * received data int32 AppllID
+					   * int32 Length capi-data ...
+					   * int32 B3Length data ... 
+					 */
+#define RECEIVE_START		0x23	/*
+					   * Handshake 
+					 */
+#define RECEIVE_STOP		0x24	/*
+					   * Handshake 
+					 */
+#define RECEIVE_NEW_NCCI	0x25	/*
+					   * int32 AppllID int32 NCCI int32
+					   * WindowSize 
+					 */
+#define RECEIVE_FREE_NCCI	0x26	/*
+					   * int32 AppllID int32 NCCI 
+					 */
+#define RECEIVE_RELEASE		0x26	/*
+					   * int32 AppllID int32 0xffffffff 
+					 */
+#define RECEIVE_TASK_READY	0x31	/*
+					   * int32 tasknr
+					   * int32 Length Taskname ...
+					 */
+#define RECEIVE_DEBUGMSG	0x71	/*
+					   * int32 Length message
+					   * 
+					 */
+#define RECEIVE_POLLDWORD	0x75	/* t1pci in dword mode */
+
+#define WRITE_REGISTER		0x00
+#define READ_REGISTER		0x01
+
+/*
+ * port offsets
+ */
+
+#define B1_READ			0x00
+#define B1_WRITE		0x01
+#define B1_INSTAT		0x02
+#define B1_OUTSTAT		0x03
+#define B1_RESET		0x10
+#define B1_ANALYSE		0x04
+
+
+#define B1_STAT0(cardtype)  ((cardtype) == avm_m1 ? 0x81200000l : 0x80A00000l)
+#define B1_STAT1(cardtype)  (0x80E00000l)
+
+/* ---------------------------------------------------------------- */
+
+static inline unsigned char b1outp(unsigned int base,
+				   unsigned short offset,
+				   unsigned char value)
+{
+	outb(value, base + offset);
+	return inb(base + B1_ANALYSE);
+}
+
+
+static inline int b1_rx_full(unsigned int base)
+{
+	return inb(base + B1_INSTAT) & 0x1;
+}
+
+static inline unsigned char b1_get_byte(unsigned int base)
+{
+	unsigned long stop = jiffies + 1 * HZ;	/* maximum wait time 1 sec */
+	while (!b1_rx_full(base) && time_before(jiffies, stop));
+	if (b1_rx_full(base))
+		return inb(base + B1_READ);
+	printk(KERN_CRIT "b1lli(0x%x): rx not full after 1 second\n", base);
+	return 0;
+}
+
+static inline unsigned int b1_get_word(unsigned int base)
+{
+	unsigned int val = 0;
+	val |= b1_get_byte(base);
+	val |= (b1_get_byte(base) << 8);
+	val |= (b1_get_byte(base) << 16);
+	val |= (b1_get_byte(base) << 24);
+	return val;
+}
+
+static inline int b1_tx_empty(unsigned int base)
+{
+	return inb(base + B1_OUTSTAT) & 0x1;
+}
+
+static inline void b1_put_byte(unsigned int base, unsigned char val)
+{
+	while (!b1_tx_empty(base));
+	b1outp(base, B1_WRITE, val);
+}
+
+static inline int b1_save_put_byte(unsigned int base, unsigned char val)
+{
+	unsigned long stop = jiffies + 2 * HZ;
+	while (!b1_tx_empty(base) && time_before(jiffies,stop));
+	if (!b1_tx_empty(base)) return -1;
+	b1outp(base, B1_WRITE, val);
+	return 0;
+}
+
+static inline void b1_put_word(unsigned int base, unsigned int val)
+{
+	b1_put_byte(base, val & 0xff);
+	b1_put_byte(base, (val >> 8) & 0xff);
+	b1_put_byte(base, (val >> 16) & 0xff);
+	b1_put_byte(base, (val >> 24) & 0xff);
+}
+
+static inline unsigned int b1_get_slice(unsigned int base,
+					unsigned char *dp)
+{
+	unsigned int len, i;
+
+	len = i = b1_get_word(base);
+	while (i-- > 0) *dp++ = b1_get_byte(base);
+	return len;
+}
+
+static inline void b1_put_slice(unsigned int base,
+				unsigned char *dp, unsigned int len)
+{
+	unsigned i = len;
+	b1_put_word(base, i);
+	while (i-- > 0)
+		b1_put_byte(base, *dp++);
+}
+
+static void b1_wr_reg(unsigned int base,
+                      unsigned int reg,
+		      unsigned int value)
+{
+	b1_put_byte(base, WRITE_REGISTER);
+        b1_put_word(base, reg);
+        b1_put_word(base, value);
+}
+
+static inline unsigned int b1_rd_reg(unsigned int base,
+                                     unsigned int reg)
+{
+	b1_put_byte(base, READ_REGISTER);
+        b1_put_word(base, reg);
+        return b1_get_word(base);
+	
+}
+
+static inline void b1_reset(unsigned int base)
+{
+	b1outp(base, B1_RESET, 0);
+	udelay(55 * 2 * 1000);	/* 2 TIC's */
+
+	b1outp(base, B1_RESET, 1);
+	udelay(55 * 2 * 1000);	/* 2 TIC's */
+
+	b1outp(base, B1_RESET, 0);
+	udelay(55 * 2 * 1000);	/* 2 TIC's */
+}
+
+static inline unsigned char b1_disable_irq(unsigned int base)
+{
+	return b1outp(base, B1_INSTAT, 0x00);
+}
+
+/* ---------------------------------------------------------------- */
+
+static inline void b1_set_test_bit(unsigned int base,
+				   enum avmcardtype cardtype,
+				   int onoff)
+{
+    b1_wr_reg(base, B1_STAT0(cardtype), onoff ? 0x21 : 0x20);
+}
+
+static inline int b1_get_test_bit(unsigned int base,
+                                  enum avmcardtype cardtype)
+{
+    return (b1_rd_reg(base, B1_STAT0(cardtype)) & 0x01) != 0;
+}
+
+/* ---------------------------------------------------------------- */
+
+#define T1_FASTLINK		0x00
+#define T1_SLOWLINK		0x08
+
+#define T1_READ			B1_READ
+#define T1_WRITE		B1_WRITE
+#define T1_INSTAT		B1_INSTAT
+#define T1_OUTSTAT		B1_OUTSTAT
+#define T1_IRQENABLE		0x05
+#define T1_FIFOSTAT		0x06
+#define T1_RESETLINK		0x10
+#define T1_ANALYSE		0x11
+#define T1_IRQMASTER		0x12
+#define T1_IDENT		0x17
+#define T1_RESETBOARD		0x1f
+
+#define	T1F_IREADY		0x01
+#define	T1F_IHALF		0x02
+#define	T1F_IFULL		0x04
+#define	T1F_IEMPTY		0x08
+#define	T1F_IFLAGS		0xF0
+
+#define	T1F_OREADY		0x10
+#define	T1F_OHALF		0x20
+#define	T1F_OEMPTY		0x40
+#define	T1F_OFULL		0x80
+#define	T1F_OFLAGS		0xF0
+
+/* there are HEMA cards with 1k and 4k FIFO out */
+#define FIFO_OUTBSIZE		256
+#define FIFO_INPBSIZE		512
+
+#define HEMA_VERSION_ID		0
+#define HEMA_PAL_ID		0
+
+static inline void t1outp(unsigned int base,
+			  unsigned short offset,
+			  unsigned char value)
+{
+	outb(value, base + offset);
+}
+
+static inline unsigned char t1inp(unsigned int base,
+			          unsigned short offset)
+{
+	return inb(base + offset);
+}
+
+static inline int t1_isfastlink(unsigned int base)
+{
+	return (inb(base + T1_IDENT) & ~0x82) == 1;
+}
+
+static inline unsigned char t1_fifostatus(unsigned int base)
+{
+	return inb(base + T1_FIFOSTAT);
+}
+
+static inline unsigned int t1_get_slice(unsigned int base,
+					unsigned char *dp)
+{
+	unsigned int len, i;
+#ifdef FASTLINK_DEBUG
+	unsigned wcnt = 0, bcnt = 0;
+#endif
+
+	len = i = b1_get_word(base);
+        if (t1_isfastlink(base)) {
+		int status;
+		while (i > 0) {
+			status = t1_fifostatus(base) & (T1F_IREADY|T1F_IHALF);
+			if (i >= FIFO_INPBSIZE) status |= T1F_IFULL;
+
+			switch (status) {
+				case T1F_IREADY|T1F_IHALF|T1F_IFULL:
+					insb(base+B1_READ, dp, FIFO_INPBSIZE);
+					dp += FIFO_INPBSIZE;
+					i -= FIFO_INPBSIZE;
+#ifdef FASTLINK_DEBUG
+					wcnt += FIFO_INPBSIZE;
+#endif
+					break;
+				case T1F_IREADY|T1F_IHALF: 
+					insb(base+B1_READ,dp, i);
+#ifdef FASTLINK_DEBUG
+					wcnt += i;
+#endif
+					dp += i;
+					i = 0;
+					if (i == 0)
+						break;
+					/* fall through */
+				default:
+					*dp++ = b1_get_byte(base);
+					i--;
+#ifdef FASTLINK_DEBUG
+					bcnt++;
+#endif
+					break;
+			}
+	    }
+#ifdef FASTLINK_DEBUG
+	    if (wcnt)
+	    printk(KERN_DEBUG "b1lli(0x%x): get_slice l=%d w=%d b=%d\n",
+				base, len, wcnt, bcnt);
+#endif
+	} else {
+		while (i-- > 0)
+			*dp++ = b1_get_byte(base);
+	}
+	return len;
+}
+
+static inline void t1_put_slice(unsigned int base,
+				unsigned char *dp, unsigned int len)
+{
+	unsigned i = len;
+	b1_put_word(base, i);
+        if (t1_isfastlink(base)) {
+		int status;
+		while (i > 0) {
+			status = t1_fifostatus(base) & (T1F_OREADY|T1F_OHALF);
+			if (i >= FIFO_OUTBSIZE) status |= T1F_OEMPTY;
+			switch (status) {
+				case T1F_OREADY|T1F_OHALF|T1F_OEMPTY: 
+					outsb(base+B1_WRITE, dp, FIFO_OUTBSIZE);
+					dp += FIFO_OUTBSIZE;
+					i -= FIFO_OUTBSIZE;
+					break;
+				case T1F_OREADY|T1F_OHALF: 
+					outsb(base+B1_WRITE, dp, i);
+					dp += i;
+					i = 0;
+				        break;
+				default:
+					b1_put_byte(base, *dp++);
+					i--;
+					break;
+			}
+		}
+	} else {
+		while (i-- > 0)
+			b1_put_byte(base, *dp++);
+	}
+}
+
+static inline void t1_disable_irq(unsigned int base)
+{
+      t1outp(base, T1_IRQMASTER, 0x00);
+}
+
+static inline void t1_reset(unsigned int base)
+{
+        /* reset T1 Controller */
+        b1_reset(base);
+        /* disable irq on HEMA */
+        t1outp(base, B1_INSTAT, 0x00);
+        t1outp(base, B1_OUTSTAT, 0x00);
+        t1outp(base, T1_IRQMASTER, 0x00);
+        /* reset HEMA board configuration */
+	t1outp(base, T1_RESETBOARD, 0xf);
+}
+
+static inline void b1_setinterrupt(unsigned int base, unsigned irq,
+				   enum avmcardtype cardtype)
+{
+	switch (cardtype) {
+	   case avm_t1isa:
+              t1outp(base, B1_INSTAT, 0x00);
+              t1outp(base, B1_INSTAT, 0x02);
+	      t1outp(base, T1_IRQMASTER, 0x08);
+	      break;
+	   case avm_b1isa:
+	      b1outp(base, B1_INSTAT, 0x00);
+	      b1outp(base, B1_RESET, b1_irq_table[irq]);
+	      b1outp(base, B1_INSTAT, 0x02);
+	      break;
+	   default:
+	   case avm_m1:
+	   case avm_m2:
+	   case avm_b1pci:
+	      b1outp(base, B1_INSTAT, 0x00);
+	      b1outp(base, B1_RESET, 0xf0);
+	      b1outp(base, B1_INSTAT, 0x02);
+	      break;
+	   case avm_c4:
+	   case avm_t1pci:
+	      b1outp(base, B1_RESET, 0xf0);
+	      break;
+	 }
+}
+
+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_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_handle_interrupt(avmcard * card);
+
+int b1ctl_read_proc(char *page, char **start, off_t off,
+        		int count, int *eof, struct capi_ctr *ctrl);
+
+
+#endif /* _AVMCARD_H_ */
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/avmb1/b1.c linux/drivers/isdn/avmb1/b1.c
--- v2.3.13/linux/drivers/isdn/avmb1/b1.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/avmb1/b1.c	Sun Aug 15 11:49:08 1999
@@ -0,0 +1,687 @@
+/*
+ * $Id: b1.c,v 1.7 1999/08/04 10:10:09 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.7  1999/08/04 10:10:09  calle
+ * Bugfix: corrected /proc functions, added structure for new AVM cards.
+ *
+ * Revision 1.6  1999/07/23 08:51:04  calle
+ * small fix and typo in checkin before.
+ *
+ * Revision 1.5  1999/07/23 08:41:48  calle
+ * prepared for new AVM cards.
+ *
+ * Revision 1.4  1999/07/09 15:05:38  keil
+ * compat.h is now isdn_compat.h
+ *
+ * Revision 1.3  1999/07/06 07:41:59  calle
+ * - changes in /proc interface
+ * - check and changed calls to [dev_]kfree_skb and [dev_]alloc_skb.
+ *
+ * Revision 1.2  1999/07/05 15:09:47  calle
+ * - renamed "appl_release" to "appl_released".
+ * - version und profile data now cleared on controller reset
+ * - extended /proc interface, to allow driver and controller specific
+ *   informations to include by driver hackers.
+ *
+ * Revision 1.1  1999/07/01 15:26:23  calle
+ * complete new version (I love it):
+ * + new hardware independed "capi_driver" interface that will make it easy to:
+ *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ *   - write a CAPI-2.0 for the passive cards
+ *   - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ *   make menuconfig, in the past all supported cards where included
+ *   at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ *   using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+ *
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/capi.h>
+#include <asm/io.h>
+#include <linux/isdn_compat.h>
+#include "capilli.h"
+#include "avmcard.h"
+#include "capicmd.h"
+#include "capiutil.h"
+
+static char *revision = "$Revision: 1.7 $";
+
+/* ------------------------------------------------------------- */
+
+MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
+
+/* ------------------------------------------------------------- */
+
+int b1_irq_table[16] =
+{0,
+ 0,
+ 0,
+ 192,				/* irq 3 */
+ 32,				/* irq 4 */
+ 160,				/* irq 5 */
+ 96,				/* irq 6 */
+ 224,				/* irq 7 */
+ 0,
+ 64,				/* irq 9 */
+ 80,				/* irq 10 */
+ 208,				/* irq 11 */
+ 48,				/* irq 12 */
+ 0,
+ 0,
+ 112,				/* irq 15 */
+};
+
+/* ------------------------------------------------------------- */
+
+int b1_detect(unsigned int base, enum avmcardtype cardtype)
+{
+	int onoff, i;
+
+	/*
+	 * Statusregister 0000 00xx 
+	 */
+	if ((inb(base + B1_INSTAT) & 0xfc)
+	    || (inb(base + B1_OUTSTAT) & 0xfc))
+		return 1;
+	/*
+	 * Statusregister 0000 001x 
+	 */
+	b1outp(base, B1_INSTAT, 0x2);	/* enable irq */
+	/* b1outp(base, B1_OUTSTAT, 0x2); */
+	if ((inb(base + B1_INSTAT) & 0xfe) != 0x2
+	    /* || (inb(base + B1_OUTSTAT) & 0xfe) != 0x2 */)
+		return 2;
+	/*
+	 * Statusregister 0000 000x 
+	 */
+	b1outp(base, B1_INSTAT, 0x0);	/* disable irq */
+	b1outp(base, B1_OUTSTAT, 0x0);
+	if ((inb(base + B1_INSTAT) & 0xfe)
+	    || (inb(base + B1_OUTSTAT) & 0xfe))
+		return 3;
+        
+	for (onoff = !0, i= 0; i < 10 ; i++) {
+		b1_set_test_bit(base, cardtype, onoff);
+		if (b1_get_test_bit(base, cardtype) != onoff)
+		   return 4;
+		onoff = !onoff;
+	}
+
+	if (cardtype == avm_m1)
+	   return 0;
+
+        if ((b1_rd_reg(base, B1_STAT1(cardtype)) & 0x0f) != 0x01)
+	   return 5;
+
+	return 0;
+}
+
+int b1_load_t4file(unsigned int base, capiloaddatapart * t4file)
+{
+	unsigned char buf[256];
+	unsigned char *dp;
+	int i, left, retval;
+
+	dp = t4file->data;
+	left = t4file->len;
+	while (left > sizeof(buf)) {
+		if (t4file->user) {
+			retval = copy_from_user(buf, dp, sizeof(buf));
+			if (retval)
+				return -EFAULT;
+		} else {
+			memcpy(buf, dp, sizeof(buf));
+		}
+		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");
+				return -EIO;
+			}
+		left -= sizeof(buf);
+		dp += sizeof(buf);
+	}
+	if (left) {
+		if (t4file->user) {
+			retval = copy_from_user(buf, dp, left);
+			if (retval)
+				return -EFAULT;
+		} else {
+			memcpy(buf, dp, left);
+		}
+		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");
+				return -EIO;
+			}
+	}
+	return 0;
+}
+
+int b1_load_config(unsigned int base, capiloaddatapart * config)
+{
+	unsigned char buf[256];
+	unsigned char *dp;
+	int i, j, left, retval;
+
+	dp = config->data;
+	left = config->len;
+	if (left) {
+		b1_put_byte(base, SEND_CONFIG);
+        	b1_put_word(base, 1);
+		b1_put_byte(base, SEND_CONFIG);
+        	b1_put_word(base, left);
+	}
+	while (left > sizeof(buf)) {
+		if (config->user) {
+			retval = copy_from_user(buf, dp, sizeof(buf));
+			if (retval)
+				return -EFAULT;
+		} else {
+			memcpy(buf, dp, sizeof(buf));
+		}
+		for (i = 0; i < sizeof(buf); ) {
+			b1_put_byte(base, SEND_CONFIG);
+			for (j=0; j < 4; j++) {
+				b1_put_byte(base, buf[i++]);
+			}
+		}
+		left -= sizeof(buf);
+		dp += sizeof(buf);
+	}
+	if (left) {
+		if (config->user) {
+			retval = copy_from_user(buf, dp, left);
+			if (retval)
+				return -EFAULT;
+		} else {
+			memcpy(buf, dp, left);
+		}
+		for (i = 0; i < left; ) {
+			b1_put_byte(base, SEND_CONFIG);
+			for (j=0; j < 4; j++) {
+				if (i < left)
+					b1_put_byte(base, buf[i++]);
+				else
+					b1_put_byte(base, 0);
+			}
+		}
+	}
+	return 0;
+}
+
+int b1_loaded(unsigned int base)
+{
+	unsigned long stop;
+	unsigned char ans;
+	unsigned long tout = 2;
+
+	for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) {
+		if (b1_tx_empty(base))
+			break;
+	}
+	if (!b1_tx_empty(base)) {
+		printk(KERN_ERR "b1_loaded: tx err, corrupted t4 file ?\n");
+		return 0;
+	}
+	b1_put_byte(base, SEND_POLL);
+	for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) {
+		if (b1_rx_full(base)) {
+			if ((ans = b1_get_byte(base)) == RECEIVE_POLL) {
+				return 1;
+			}
+			printk(KERN_ERR "b1_loaded: got 0x%x, firmware not running\n", ans);
+			return 0;
+		}
+	}
+	printk(KERN_ERR "b1_loaded: firmware not running\n");
+	return 0;
+}
+
+/* ------------------------------------------------------------- */
+
+int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	unsigned int port = card->port;
+	unsigned long flags;
+	int retval;
+
+	b1_reset(port);
+
+	if ((retval = b1_load_t4file(port, &data->firmware))) {
+		b1_reset(port);
+		printk(KERN_ERR "%s: failed to load t4file!!\n",
+					card->name);
+		return retval;
+	}
+
+	b1_disable_irq(port);
+
+	if (data->configuration.len > 0 && data->configuration.data) {
+		if ((retval = b1_load_config(port, &data->configuration))) {
+			b1_reset(port);
+			printk(KERN_ERR "%s: failed to load config!!\n",
+					card->name);
+			return retval;
+		}
+	}
+
+	if (!b1_loaded(port)) {
+		printk(KERN_ERR "%s: failed to load t4file.\n", card->name);
+		return -EIO;
+	}
+
+	save_flags(flags);
+	cli();
+	b1_setinterrupt(port, card->irq, card->cardtype);
+	b1_put_byte(port, SEND_INIT);
+	b1_put_word(port, AVM_NAPPS);
+	b1_put_word(port, AVM_NCCI_PER_CHANNEL*2);
+	b1_put_word(port, ctrl->cnr - 1);
+	restore_flags(flags);
+
+	return 0;
+}
+
+void b1_reset_ctr(struct capi_ctr *ctrl)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	unsigned int port = card->port;
+
+	b1_reset(port);
+	b1_reset(port);
+
+	memset(card->version, 0, sizeof(card->version));
+	ctrl->reseted(ctrl);
+}
+
+void b1_register_appl(struct capi_ctr *ctrl,
+				__u16 appl,
+				capi_register_params *rp)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	unsigned int port = card->port;
+	unsigned long flags;
+	int nconn, want = rp->level3cnt;
+
+	if (want > 0) nconn = want;
+	else nconn = ctrl->profile.nbchannel * -want;
+	if (nconn == 0) nconn = ctrl->profile.nbchannel;
+
+	save_flags(flags);
+	cli();
+	b1_put_byte(port, SEND_REGISTER);
+	b1_put_word(port, appl);
+	b1_put_word(port, 1024 * (nconn+1));
+	b1_put_word(port, nconn);
+	b1_put_word(port, rp->datablkcnt);
+	b1_put_word(port, rp->datablklen);
+	restore_flags(flags);
+
+	ctrl->appl_registered(ctrl, appl);
+}
+
+void b1_release_appl(struct capi_ctr *ctrl, __u16 appl)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	unsigned int port = card->port;
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+	b1_put_byte(port, SEND_RELEASE);
+	b1_put_word(port, appl);
+	restore_flags(flags);
+}
+
+void b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	unsigned int port = card->port;
+	unsigned long flags;
+	__u16 len = CAPIMSG_LEN(skb->data);
+	__u8 cmd = CAPIMSG_COMMAND(skb->data);
+	__u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data);
+
+	save_flags(flags);
+	cli();
+	if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
+		__u16 dlen = CAPIMSG_DATALEN(skb->data);
+		b1_put_byte(port, SEND_DATA_B3_REQ);
+		b1_put_slice(port, skb->data, len);
+		b1_put_slice(port, skb->data + len, dlen);
+	} else {
+		b1_put_byte(port, SEND_MESSAGE);
+		b1_put_slice(port, skb->data, len);
+	}
+	restore_flags(flags);
+	dev_kfree_skb(skb);
+}
+
+/* ------------------------------------------------------------- */
+
+void b1_parse_version(avmcard *card)
+{
+	struct capi_ctr *ctrl = card->ctrl;
+	capi_profile *profp;
+	__u8 *dversion;
+	__u8 flag;
+	int i, j;
+
+	for (j = 0; j < AVM_MAXVERSION; j++)
+		card->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];
+
+	strncpy(ctrl->serial, card->version[VER_SERIAL], CAPI_SERIAL_LEN);
+	memcpy(&ctrl->profile, card->version[VER_PROFILE],sizeof(capi_profile));
+	strncpy(ctrl->manu, "AVM GmbH", CAPI_MANUFACTURER_LEN);
+	dversion = card->version[VER_DRIVER];
+	ctrl->version.majorversion = 2;
+	ctrl->version.minorversion = 0;
+	ctrl->version.majormanuversion = (((dversion[0] - '0') & 0xf) << 4);
+	ctrl->version.majormanuversion |= ((dversion[2] - '0') & 0xf);
+	ctrl->version.minormanuversion = (dversion[3] - '0') << 4;
+	ctrl->version.minormanuversion |=
+			(dversion[5] - '0') * 10 + ((dversion[6] - '0') & 0xf);
+
+	profp = &ctrl->profile;
+
+	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");
+		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;
+        }
+        printk(KERN_NOTICE "%s: card %d \"%s\" ready.\n",
+				card->name, ctrl->cnr, card->cardname);
+
+        flag = ((__u8 *)(profp->manu))[3];
+        if (flag)
+		printk(KERN_NOTICE "b1capi: card %d Protocol:%s%s%s%s%s%s%s\n",
+			ctrl->cnr,
+			(flag & 0x01) ? " DSS1" : "",
+			(flag & 0x02) ? " CT1" : "",
+			(flag & 0x04) ? " VN3" : "",
+			(flag & 0x08) ? " NI1" : "",
+			(flag & 0x10) ? " AUSTEL" : "",
+			(flag & 0x20) ? " ESS" : "",
+			(flag & 0x40) ? " 1TR6" : ""
+			);
+
+        flag = ((__u8 *)(profp->manu))[5];
+	if (flag)
+		printk(KERN_NOTICE "%s: card %d Linetype:%s%s%s%s\n",
+			card->name,
+			ctrl->cnr,
+			(flag & 0x01) ? " point to point" : "",
+			(flag & 0x02) ? " point to multipoint" : "",
+			(flag & 0x08) ? " leased line without D-channel" : "",
+			(flag & 0x04) ? " leased line with D-channel" : ""
+			);
+}
+
+/* ------------------------------------------------------------- */
+
+void b1_handle_interrupt(avmcard * card)
+{
+	struct capi_ctr *ctrl = card->ctrl;
+	unsigned char b1cmd;
+	struct sk_buff *skb;
+
+	unsigned ApplId;
+	unsigned MsgLen;
+	unsigned DataB3Len;
+	unsigned NCCI;
+	unsigned WindowSize;
+
+	if (!b1_rx_full(card->port))
+	   return;
+
+	b1cmd = b1_get_byte(card->port);
+
+	switch (b1cmd) {
+
+	case RECEIVE_DATA_B3_IND:
+
+		ApplId = (unsigned) b1_get_word(card->port);
+		MsgLen = b1_get_slice(card->port, card->msgbuf);
+		DataB3Len = b1_get_slice(card->port, card->databuf);
+
+		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;
+
+	case RECEIVE_MESSAGE:
+
+		ApplId = (unsigned) b1_get_word(card->port);
+		MsgLen = b1_get_slice(card->port, 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 = b1_get_word(card->port);
+		NCCI = b1_get_word(card->port);
+		WindowSize = b1_get_word(card->port);
+
+		ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize);
+
+		break;
+
+	case RECEIVE_FREE_NCCI:
+
+		ApplId = b1_get_word(card->port);
+		NCCI = b1_get_word(card->port);
+
+		if (NCCI != 0xffffffff)
+			ctrl->free_ncci(ctrl, ApplId, NCCI);
+		else ctrl->appl_released(ctrl, ApplId);
+		break;
+
+	case RECEIVE_START:
+	   	/* b1_put_byte(card->port, SEND_POLLACK); */
+		ctrl->resume_output(ctrl);
+		break;
+
+	case RECEIVE_STOP:
+		ctrl->suspend_output(ctrl);
+		break;
+
+	case RECEIVE_INIT:
+
+		card->versionlen = b1_get_slice(card->port, card->versionbuf);
+		b1_parse_version(card);
+		printk(KERN_INFO "%s: %s-card (%s) now active\n",
+		       card->name,
+		       card->version[VER_CARDTYPE],
+		       card->version[VER_DRIVER]);
+		ctrl->ready(ctrl);
+		break;
+
+        case RECEIVE_TASK_READY:
+		ApplId = (unsigned) b1_get_word(card->port);
+		MsgLen = b1_get_slice(card->port, 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 = b1_get_slice(card->port, 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;
+
+	case 0xff:
+		printk(KERN_ERR "%s: card removed ?\n", card->name);
+		return;
+	default:
+		printk(KERN_ERR "%s: b1_interrupt: 0x%x ???\n",
+				card->name, b1cmd);
+		return;
+	}
+}
+
+/* ------------------------------------------------------------- */
+int b1ctl_read_proc(char *page, char **start, off_t off,
+        		int count, int *eof, struct capi_ctr *ctrl)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	__u8 flag;
+	int len = 0;
+	char *s;
+
+	len += sprintf(page+len, "%-16s %s\n", "name", card->name);
+	len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port);
+	len += sprintf(page+len, "%-16s %d\n", "irq", card->irq);
+	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 (card->cardtype == avm_t1isa)
+	   len += sprintf(page+len, "%-16s %d\n", "cardnr", card->cardnr);
+	if ((s = card->version[VER_DRIVER]) != 0)
+	   len += sprintf(page+len, "%-16s %s\n", "ver_driver", s);
+	if ((s = card->version[VER_CARDTYPE]) != 0)
+	   len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s);
+	if ((s = card->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", card->cardname);
+
+	if (off+count >= len)
+	   *eof = 1;
+	if (len < off)
+           return 0;
+	*start = page + off;
+	return ((count < len-off) ? count : len-off);
+}
+
+/* ------------------------------------------------------------- */
+
+EXPORT_SYMBOL(b1_irq_table);
+
+EXPORT_SYMBOL(b1_detect);
+EXPORT_SYMBOL(b1_load_t4file);
+EXPORT_SYMBOL(b1_load_config);
+EXPORT_SYMBOL(b1_loaded);
+EXPORT_SYMBOL(b1_load_firmware);
+EXPORT_SYMBOL(b1_reset_ctr);
+EXPORT_SYMBOL(b1_register_appl);
+EXPORT_SYMBOL(b1_release_appl);
+EXPORT_SYMBOL(b1_send_message);
+
+EXPORT_SYMBOL(b1_parse_version);
+EXPORT_SYMBOL(b1_handle_interrupt);
+
+EXPORT_SYMBOL(b1ctl_read_proc);
+
+#ifdef MODULE
+#define b1_init init_module
+void cleanup_module(void);
+#endif
+
+int b1_init(void)
+{
+	char *p;
+	char rev[10];
+
+	if ((p = strchr(revision, ':'))) {
+		strncpy(rev, p + 1, sizeof(rev));
+		p = strchr(rev, '$');
+		*p = 0;
+	} else
+		strcpy(rev, "1.0");
+
+	printk(KERN_INFO "b1: revision %s\n", rev);
+
+	return 0;
+}
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+}
+#endif
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/avmb1/b1isa.c linux/drivers/isdn/avmb1/b1isa.c
--- v2.3.13/linux/drivers/isdn/avmb1/b1isa.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/avmb1/b1isa.c	Sun Aug 15 11:49:08 1999
@@ -0,0 +1,237 @@
+/*
+ * $Id: b1isa.c,v 1.3 1999/07/09 15:05:40 keil Exp $
+ * 
+ * Module for AVM B1 ISA-card.
+ * 
+ * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
+ * 
+ * $Log: b1isa.c,v $
+ * Revision 1.3  1999/07/09 15:05:40  keil
+ * compat.h is now isdn_compat.h
+ *
+ * Revision 1.2  1999/07/05 15:09:49  calle
+ * - renamed "appl_release" to "appl_released".
+ * - version und profile data now cleared on controller reset
+ * - extended /proc interface, to allow driver and controller specific
+ *   informations to include by driver hackers.
+ *
+ * Revision 1.1  1999/07/01 15:26:27  calle
+ * complete new version (I love it):
+ * + new hardware independed "capi_driver" interface that will make it easy to:
+ *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ *   - write a CAPI-2.0 for the passive cards
+ *   - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ *   make menuconfig, in the past all supported cards where included
+ *   at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ *   using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+ *
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/capi.h>
+#include <asm/io.h>
+#include <linux/isdn_compat.h>
+#include "capicmd.h"
+#include "capiutil.h"
+#include "capilli.h"
+#include "avmcard.h"
+
+static char *revision = "$Revision: 1.3 $";
+
+/* ------------------------------------------------------------- */
+
+MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
+
+/* ------------------------------------------------------------- */
+
+static struct capi_driver_interface *di;
+
+/* ------------------------------------------------------------- */
+
+static void b1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
+{
+	avmcard *card;
+
+	card = (avmcard *) devptr;
+
+	if (!card) {
+		printk(KERN_WARNING "b1_interrupt: wrong device\n");
+		return;
+	}
+	if (card->interrupt) {
+		printk(KERN_ERR "b1_interrupt: reentering interrupt hander (%s)\n", card->name);
+		return;
+	}
+
+	card->interrupt = 1;
+
+	b1_handle_interrupt(card);
+
+	card->interrupt = 0;
+}
+/* ------------------------------------------------------------- */
+
+static void b1isa_remove_ctr(struct capi_ctr *ctrl)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	unsigned int port = card->port;
+
+	b1_reset(port);
+	b1_reset(port);
+
+	di->detach_ctr(ctrl);
+	free_irq(card->irq, card);
+	release_region(card->port, AVMB1_PORTLEN);
+	kfree(card);
+
+	MOD_DEC_USE_COUNT;
+}
+
+/* ------------------------------------------------------------- */
+
+static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p)
+{
+	avmcard *card;
+	int retval;
+
+	card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
+
+	if (!card) {
+		printk(KERN_WARNING "b1isa: no memory.\n");
+		return -ENOMEM;
+	}
+	memset(card, 0, sizeof(avmcard));
+	sprintf(card->name, "b1isa-%x", p->port);
+	card->port = p->port;
+	card->irq = p->irq;
+	card->cardtype = avm_b1isa;
+
+	if (check_region(card->port, AVMB1_PORTLEN)) {
+		printk(KERN_WARNING
+		       "b1isa: ports 0x%03x-0x%03x in use.\n",
+		       card->port, card->port + AVMB1_PORTLEN);
+		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);
+		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);
+		return -EINVAL;
+	}
+	b1_reset(card->port);
+	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);
+		return -EIO;
+	}
+	b1_reset(card->port);
+
+	request_region(p->port, AVMB1_PORTLEN, card->name);
+
+	retval = request_irq(card->irq, b1isa_interrupt, 0, card->name, card);
+	if (retval) {
+		printk(KERN_ERR "b1isa: unable to get IRQ %d.\n", card->irq);
+		release_region(card->port, AVMB1_PORTLEN);
+		kfree(card);
+		return -EBUSY;
+	}
+
+	card->ctrl = di->attach_ctr(driver, card->name, card);
+	if (!card->ctrl) {
+		printk(KERN_ERR "b1isa: attach controller failed.\n");
+		free_irq(card->irq, card);
+		release_region(card->port, AVMB1_PORTLEN);
+		kfree(card);
+		return -EBUSY;
+	}
+
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static char *b1isa_procinfo(struct capi_ctr *ctrl)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	if (!card)
+		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
+		);
+	return card->infobuf;
+}
+
+/* ------------------------------------------------------------- */
+
+static struct capi_driver b1isa_driver = {
+    "b1isa",
+    "0.0",
+    b1_load_firmware,
+    b1_reset_ctr,
+    b1isa_remove_ctr,
+    b1_register_appl,
+    b1_release_appl,
+    b1_send_message,
+
+    b1isa_procinfo,
+    b1ctl_read_proc,
+    0,	/* use standard driver_read_proc */
+
+    b1isa_add_card,
+};
+
+#ifdef MODULE
+#define b1isa_init init_module
+void cleanup_module(void);
+#endif
+
+int b1isa_init(void)
+{
+	struct capi_driver *driver = &b1isa_driver;
+	char *p;
+
+	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;
+	}
+	return 0;
+}
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+    detach_capi_driver(&b1isa_driver);
+}
+#endif
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/avmb1/b1pci.c linux/drivers/isdn/avmb1/b1pci.c
--- v2.3.13/linux/drivers/isdn/avmb1/b1pci.c	Tue Jun  1 23:25:48 1999
+++ linux/drivers/isdn/avmb1/b1pci.c	Thu Aug 12 09:42:33 1999
@@ -1,59 +1,65 @@
 /*
- * $Id: b1pci.c,v 1.9 1999/04/15 19:49:32 calle Exp $
+ * $Id: b1pci.c,v 1.16 1999/08/11 21:01:07 keil Exp $
  * 
  * Module for AVM B1 PCI-card.
  * 
- * (c) Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
+ * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
  * 
  * $Log: b1pci.c,v $
- * Revision 1.9  1999/04/15 19:49:32  calle
- * fix fuer die B1-PCI. Jetzt geht z.B. auch IRQ 17 ...
+ * Revision 1.16  1999/08/11 21:01:07  keil
+ * new PCI codefix
  *
- * Revision 1.8  1998/06/17 19:51:16  he
- * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
- * brute force fix to avoid Ugh's in isdn_tty_write()
- * cleaned up some dead code
- *
- * Revision 1.7  1998/03/29 16:06:02  calle
- * changes from 2.0 tree merged.
- *
- * Revision 1.2.2.2  1998/01/23 16:49:30  calle
- * added functions for pcmcia cards,
- * avmb1_addcard returns now the controller number.
- *
- * Revision 1.6  1998/02/25 09:15:36  fritz
- * apply Martin's pci driver patch to isdn drivers (vgerCVS)
- *
- * Revision 1.5  1998/01/31 11:14:43  calle
- * merged changes to 2.0 tree, prepare 2.1.82 to work.
- *
- * Revision 1.4  1997/12/10 20:00:50  calle
- * get changes from 2.0 version
- *
- * Revision 1.3  1997/10/01 09:21:14  fritz
- * Removed old compatibility stuff for 2.0.X kernels.
- * From now on, this code is for 2.1.X ONLY!
- * Old stuff is still in the separate branch.
- *
- * Revision 1.2  1997/05/18 09:24:13  calle
- * added verbose disconnect reason reporting to avmb1.
- * some fixes in capi20 interface.
- * changed info messages for B1-PCI
+ * Revision 1.15  1999/08/10 16:02:27  calle
+ * struct pci_dev changed in 2.3.13. Made the necessary changes.
+ *
+ * Revision 1.14  1999/07/09 15:05:41  keil
+ * compat.h is now isdn_compat.h
+ *
+ * Revision 1.13  1999/07/05 15:09:50  calle
+ * - renamed "appl_release" to "appl_released".
+ * - version und profile data now cleared on controller reset
+ * - extended /proc interface, to allow driver and controller specific
+ *   informations to include by driver hackers.
+ *
+ * Revision 1.12  1999/07/01 15:26:29  calle
+ * complete new version (I love it):
+ * + new hardware independed "capi_driver" interface that will make it easy to:
+ *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ *   - write a CAPI-2.0 for the passive cards
+ *   - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ *   make menuconfig, in the past all supported cards where included
+ *   at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ *   using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
  *
- * Revision 1.1  1997/03/30 17:10:42  calle
- * added support for AVM-B1-PCI card.
  *
  */
 
 #include <linux/config.h>
-#include <linux/string.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/pci.h>
 #include <linux/skbuff.h>
-#include "compat.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 <linux/b1lli.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 $";
+
+/* ------------------------------------------------------------- */
 
 #ifndef PCI_VENDOR_ID_AVM
 #define PCI_VENDOR_ID_AVM	0x1244
@@ -63,65 +69,213 @@
 #define PCI_DEVICE_ID_AVM_B1	0x700
 #endif
 
-static char *revision = "$Revision: 1.9 $";
-
 /* ------------------------------------------------------------- */
 
 MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
 
 /* ------------------------------------------------------------- */
 
+static struct capi_driver_interface *di;
+
+/* ------------------------------------------------------------- */
+
+static void b1pci_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
+{
+	avmcard *card;
+
+	card = (avmcard *) devptr;
+
+	if (!card) {
+		printk(KERN_WARNING "b1_interrupt: wrong device\n");
+		return;
+	}
+	if (card->interrupt) {
+		printk(KERN_ERR "b1_interrupt: reentering interrupt hander (%s)\n", card->name);
+		return;
+	}
+
+	card->interrupt = 1;
+
+	b1_handle_interrupt(card);
+
+	card->interrupt = 0;
+}
+/* ------------------------------------------------------------- */
+
+static void b1pci_remove_ctr(struct capi_ctr *ctrl)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	unsigned int port = card->port;
+
+	b1_reset(port);
+	b1_reset(port);
+
+	di->detach_ctr(ctrl);
+	free_irq(card->irq, card);
+	release_region(card->port, AVMB1_PORTLEN);
+	ctrl->driverdata = 0;
+	kfree(card);
+
+	MOD_DEC_USE_COUNT;
+}
+
 /* ------------------------------------------------------------- */
-/* -------- Init & Cleanup ------------------------------------- */
+
+static char *b1pci_procinfo(struct capi_ctr *ctrl)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	if (!card)
+		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
+		);
+	return card->infobuf;
+}
+
 /* ------------------------------------------------------------- */
 
-/*
- * init / exit functions
- */
+static int b1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
+{
+	avmcard *card;
+	int retval;
+
+	card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
+
+	if (!card) {
+		printk(KERN_WARNING "b1pci: no memory.\n");
+		return -ENOMEM;
+	}
+	memset(card, 0, sizeof(avmcard));
+	sprintf(card->name, "b1pci-%x", p->port);
+	card->port = p->port;
+	card->irq = p->irq;
+	card->cardtype = avm_b1pci;
+
+	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);
+		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);
+		kfree(card);
+		return -EIO;
+	}
+	b1_reset(card->port);
+
+	request_region(p->port, AVMB1_PORTLEN, card->name);
+
+	retval = request_irq(card->irq, b1pci_interrupt, 0, card->name, card);
+	if (retval) {
+		printk(KERN_ERR "b1pci: unable to get IRQ %d.\n", card->irq);
+		release_region(card->port, AVMB1_PORTLEN);
+		kfree(card);
+		return -EBUSY;
+	}
+
+	card->ctrl = di->attach_ctr(driver, card->name, card);
+	if (!card->ctrl) {
+		printk(KERN_ERR "b1pci: attach controller failed.\n");
+		free_irq(card->irq, card);
+		release_region(card->port, AVMB1_PORTLEN);
+		kfree(card);
+		return -EBUSY;
+	}
+
+	MOD_INC_USE_COUNT;
+
+	return 0;
+}
+
+/* ------------------------------------------------------------- */
+
+static struct capi_driver b1pci_driver = {
+    "b1pci",
+    "0.0",
+    b1_load_firmware,
+    b1_reset_ctr,
+    b1pci_remove_ctr,
+    b1_register_appl,
+    b1_release_appl,
+    b1_send_message,
+
+    b1pci_procinfo,
+    b1ctl_read_proc,
+    0,	/* use standard driver_read_proc */
+
+    0, /* no add_card function */
+};
 
 #ifdef MODULE
 #define b1pci_init init_module
+void cleanup_module(void);
 #endif
 
+static int ncards = 0;
+
 int b1pci_init(void)
 {
-	char *p;
-	char rev[10];
-	int rc;
+	struct capi_driver *driver = &b1pci_driver;
 	struct pci_dev *dev = NULL;
+	char *p;
+	int retval;
 
 	if ((p = strchr(revision, ':'))) {
-		strcpy(rev, p + 1);
-		p = strchr(rev, '$');
+		strncpy(driver->revision, p + 1, sizeof(driver->revision));
+		p = strchr(driver->revision, '$');
 		*p = 0;
-	} else
-		strcpy(rev, " ??? ");
+	}
 
+	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 "b1pci: no PCI bus present\n");
+		printk(KERN_ERR "%s: no PCI bus present\n", driver->name);
+    		detach_capi_driver(driver);
 		return -EIO;
 	}
 
-	printk(KERN_INFO "b1pci: revision %s\n", rev);
-
 	while ((dev = pci_find_device(PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_B1, dev))) {
-		unsigned int ioaddr = dev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK;
-		unsigned int irq = dev->irq;
+		struct capicardparams param;
+
+		param.port = get_pcibase(dev, 1) & PCI_BASE_ADDRESS_IO_MASK;
+		param.irq = dev->irq;
 		printk(KERN_INFO
-			"b1pci: PCI BIOS reports AVM-B1 at i/o %#x, irq %d\n",
-			ioaddr, irq);
-		if ((rc = avmb1_probecard(ioaddr, irq, AVM_CARDTYPE_B1PCI)) != 0) {
+			"%s: PCI BIOS reports AVM-B1 at i/o %#x, irq %d\n",
+			driver->name, param.port, param.irq);
+		retval = b1pci_add_card(driver, &param);
+		if (retval != 0) {
 		        printk(KERN_ERR
-			"b1pci: no AVM-B1 at i/o %#x, irq %d detected\n",
-			ioaddr, irq);
-			return rc;
+			"%s: no AVM-B1 at i/o %#x, irq %d detected\n",
+			driver->name, param.port, param.irq);
+#ifdef MODULE
+			cleanup_module();
+#endif
+			return retval;
 		}
-		if ((rc = avmb1_addcard(ioaddr, irq, AVM_CARDTYPE_B1PCI)) < 0)
-			return rc;
+		ncards++;
 	}
-	return 0;
+	if (ncards) {
+		printk(KERN_INFO "%s: %d B1-PCI card(s) detected\n",
+				driver->name, ncards);
+		return 0;
+	}
+	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");
 	return -EIO;
@@ -131,5 +285,6 @@
 #ifdef MODULE
 void cleanup_module(void)
 {
+    detach_capi_driver(&b1pci_driver);
 }
 #endif
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/avmb1/b1pcmcia.c linux/drivers/isdn/avmb1/b1pcmcia.c
--- v2.3.13/linux/drivers/isdn/avmb1/b1pcmcia.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/avmb1/b1pcmcia.c	Sun Aug 15 11:49:08 1999
@@ -0,0 +1,266 @@
+/*
+ * $Id: b1pcmcia.c,v 1.3 1999/07/09 15:05:41 keil 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.3  1999/07/09 15:05:41  keil
+ * compat.h is now isdn_compat.h
+ *
+ * Revision 1.2  1999/07/05 15:09:51  calle
+ * - renamed "appl_release" to "appl_released".
+ * - version und profile data now cleared on controller reset
+ * - extended /proc interface, to allow driver and controller specific
+ *   informations to include by driver hackers.
+ *
+ * Revision 1.1  1999/07/01 15:26:30  calle
+ * complete new version (I love it):
+ * + new hardware independed "capi_driver" interface that will make it easy to:
+ *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ *   - write a CAPI-2.0 for the passive cards
+ *   - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ *   make menuconfig, in the past all supported cards where included
+ *   at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ *   using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+ *
+ *
+ */
+
+#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 <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.3 $";
+
+/* ------------------------------------------------------------- */
+
+MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
+
+/* ------------------------------------------------------------- */
+
+static struct capi_driver_interface *di;
+
+/* ------------------------------------------------------------- */
+
+static void b1pcmcia_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
+{
+	avmcard *card;
+
+	card = (avmcard *) devptr;
+
+	if (!card) {
+		printk(KERN_WARNING "b1_interrupt: wrong device\n");
+		return;
+	}
+	if (card->interrupt) {
+		printk(KERN_ERR "b1_interrupt: reentering interrupt hander (%s)\n", card->name);
+		return;
+	}
+
+	card->interrupt = 1;
+
+	b1_handle_interrupt(card);
+
+	card->interrupt = 0;
+}
+/* ------------------------------------------------------------- */
+
+static void b1pcmcia_remove_ctr(struct capi_ctr *ctrl)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	unsigned int port = card->port;
+
+	b1_reset(port);
+	b1_reset(port);
+
+	di->detach_ctr(ctrl);
+	free_irq(card->irq, card);
+	/* io addrsses managent by CardServices 
+	 * release_region(card->port, AVMB1_PORTLEN);
+	 */
+	kfree(card);
+
+	MOD_DEC_USE_COUNT;
+}
+
+/* ------------------------------------------------------------- */
+
+static int b1pcmcia_add_card(struct capi_driver *driver,
+				unsigned int port,
+				unsigned irq,
+				enum avmcardtype cardtype)
+{
+	avmcard *card;
+	int retval;
+
+	card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
+
+	if (!card) {
+		printk(KERN_WARNING "b1pcmcia: no memory.\n");
+		return -ENOMEM;
+	}
+	memset(card, 0, sizeof(avmcard));
+	switch (cardtype) {
+		case avm_m1: sprintf(card->name, "m1-%x", port); break;
+		case avm_m2: sprintf(card->name, "m2-%x", port); break;
+		default: sprintf(card->name, "b1pcmcia-%x", port); break;
+	}
+	card->port = port;
+	card->irq = irq;
+	card->cardtype = cardtype;
+
+	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);
+		kfree(card);
+		return -EIO;
+	}
+	b1_reset(card->port);
+
+	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);
+		kfree(card);
+		return -EBUSY;
+	}
+
+	card->ctrl = di->attach_ctr(driver, card->name, card);
+	if (!card->ctrl) {
+		printk(KERN_ERR "b1pcmcia: attach controller failed.\n");
+		free_irq(card->irq, card);
+		kfree(card);
+		return -EBUSY;
+	}
+
+	MOD_INC_USE_COUNT;
+	return card->ctrl->cnr;
+}
+
+/* ------------------------------------------------------------- */
+
+static char *b1pcmcia_procinfo(struct capi_ctr *ctrl)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	if (!card)
+		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
+		);
+	return card->infobuf;
+}
+
+/* ------------------------------------------------------------- */
+
+static struct capi_driver b1pcmcia_driver = {
+    "b1pcmcia",
+    "0.0",
+    b1_load_firmware,
+    b1_reset_ctr,
+    b1pcmcia_remove_ctr,
+    b1_register_appl,
+    b1_release_appl,
+    b1_send_message,
+
+    b1pcmcia_procinfo,
+    b1ctl_read_proc,
+    0,	/* use standard driver_read_proc */
+
+    0,
+};
+
+/* ------------------------------------------------------------- */
+
+int b1pcmcia_addcard_b1(unsigned int port, unsigned irq)
+{
+	return b1pcmcia_add_card(&b1pcmcia_driver, port, irq, avm_b1pcmcia);
+}
+
+int b1pcmcia_addcard_m1(unsigned int port, unsigned irq)
+{
+	return b1pcmcia_add_card(&b1pcmcia_driver, port, irq, avm_m1);
+}
+
+int b1pcmcia_addcard_m2(unsigned int port, unsigned irq)
+{
+	return b1pcmcia_add_card(&b1pcmcia_driver, port, irq, avm_m2);
+}
+
+int b1pcmcia_delcard(unsigned int port, unsigned irq)
+{
+	struct capi_ctr *ctrl;
+	avmcard *card;
+
+	for (ctrl = b1pcmcia_driver.controller; ctrl; ctrl = ctrl->next) {
+		card = (avmcard *)(ctrl->driverdata);
+		if (card->port == port && card->irq == irq) {
+			b1pcmcia_remove_ctr(ctrl);
+			return 0;
+		}
+	}
+	return -ESRCH;
+}
+
+EXPORT_SYMBOL(b1pcmcia_addcard_b1);
+EXPORT_SYMBOL(b1pcmcia_addcard_m1);
+EXPORT_SYMBOL(b1pcmcia_addcard_m2);
+EXPORT_SYMBOL(b1pcmcia_delcard);
+
+/* ------------------------------------------------------------- */
+
+#ifdef MODULE
+#define b1pcmcia_init init_module
+void cleanup_module(void);
+#endif
+
+int b1pcmcia_init(void)
+{
+	struct capi_driver *driver = &b1pcmcia_driver;
+	char *p;
+
+	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;
+	}
+	return 0;
+}
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+    detach_capi_driver(&b1pcmcia_driver);
+}
+#endif
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/avmb1/capi.c linux/drivers/isdn/avmb1/capi.c
--- v2.3.13/linux/drivers/isdn/avmb1/capi.c	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/avmb1/capi.c	Thu Aug 12 09:42:33 1999
@@ -1,11 +1,43 @@
 /*
- * $Id: capi.c,v 1.13 1998/08/28 04:32:25 calle Exp $
+ * $Id: capi.c,v 1.19 1999/07/09 15:05:42 keil Exp $
  *
  * CAPI 2.0 Interface for Linux
  *
  * Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de)
  *
  * $Log: capi.c,v $
+ * Revision 1.19  1999/07/09 15:05:42  keil
+ * compat.h is now isdn_compat.h
+ *
+ * Revision 1.18  1999/07/06 07:42:01  calle
+ * - changes in /proc interface
+ * - check and changed calls to [dev_]kfree_skb and [dev_]alloc_skb.
+ *
+ * Revision 1.17  1999/07/01 15:26:30  calle
+ * complete new version (I love it):
+ * + new hardware independed "capi_driver" interface that will make it easy to:
+ *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ *   - write a CAPI-2.0 for the passive cards
+ *   - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ *   make menuconfig, in the past all supported cards where included
+ *   at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ *   using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+ *
+ * Revision 1.16  1999/07/01 08:22:57  keil
+ * compatibility macros now in <linux/isdn_compat.h>
+ *
+ * Revision 1.15  1999/06/21 15:24:11  calle
+ * extend information in /proc.
+ *
+ * Revision 1.14  1999/06/10 16:51:03  calle
+ * Bugfix: open/release of control device was not handled correct.
+ *
  * Revision 1.13  1998/08/28 04:32:25  calle
  * Added patch send by Michael.Mueller4@post.rwth-aachen.de, to get AVM B1
  * driver running with 2.1.118.
@@ -80,11 +112,12 @@
 #include <linux/timer.h>
 #include <linux/wait.h>
 #include <linux/skbuff.h>
+#include <linux/proc_fs.h>
 #include <linux/poll.h>
 #include <linux/capi.h>
 #include <linux/kernelcapi.h>
 
-#include "compat.h"
+#include <linux/isdn_compat.h>
 #include "capiutil.h"
 #include "capicmd.h"
 #include "capidev.h"
@@ -178,7 +211,10 @@
 	}
 	copied = skb->len;
 
-
+	if (CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3
+	    && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND)
+		cdev->nrecvdatapkt++;
+        else cdev->nrecvctlpkt++;
 	kfree_skb(skb);
 
 	return copied;
@@ -207,7 +243,7 @@
 	skb = alloc_skb(count, GFP_USER);
 
 	if ((retval = copy_from_user(skb_put(skb, count), buf, count))) {
-		dev_kfree_skb(skb);
+		kfree_skb(skb);
 		return retval;
 	}
 	cmd = CAPIMSG_COMMAND(skb->data);
@@ -216,11 +252,11 @@
 	if (cmd == CAPI_DATA_B3 && subcmd == CAPI_REQ) {
 		__u16 dlen = CAPIMSG_DATALEN(skb->data);
 		if (mlen + dlen != count) {
-			dev_kfree_skb(skb);
+			kfree_skb(skb);
 			return -EINVAL;
 		}
 	} else if (mlen != count) {
-		dev_kfree_skb(skb);
+		kfree_skb(skb);
 		return -EINVAL;
 	}
 	CAPIMSG_SETAPPID(skb->data, cdev->applid);
@@ -228,9 +264,12 @@
 	cdev->errcode = (*capifuncs->capi_put_message) (cdev->applid, skb);
 
 	if (cdev->errcode) {
-		dev_kfree_skb(skb);
+		kfree_skb(skb);
 		return -EIO;
 	}
+	if (cmd == CAPI_DATA_B3 && subcmd == CAPI_REQ)
+		cdev->nsentdatapkt++;
+	else cdev->nsentctlpkt++;
 	return count;
 }
 
@@ -426,16 +465,13 @@
 		capidevs[minor].is_open = 1;
 		skb_queue_head_init(&capidevs[minor].recv_queue);
 		MOD_INC_USE_COUNT;
+		capidevs[minor].nopen++;
 
 	} else {
-
-		if (!capidevs[minor].is_open) {
-			capidevs[minor].is_open = 1;
-			MOD_INC_USE_COUNT;
-		}
+		capidevs[minor].is_open++;
+		MOD_INC_USE_COUNT;
 	}
 
-
 	return 0;
 }
 
@@ -460,10 +496,13 @@
 		cdev->is_registered = 0;
 		cdev->applid = 0;
 
-		while ((skb = skb_dequeue(&cdev->recv_queue)) != 0)
+		while ((skb = skb_dequeue(&cdev->recv_queue)) != 0) {
 			kfree_skb(skb);
+		}
+		cdev->is_open = 0;
+	} else {
+		cdev->is_open--;
 	}
-	cdev->is_open = 0;
 
 	MOD_DEC_USE_COUNT;
 	return 0;
@@ -487,7 +526,82 @@
 	NULL,			/* capi_fasync */
 };
 
+/* -------- /proc functions ----------------------------------- */
 
+/*
+ * /proc/capi/capi20:
+ *  minor opencount nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt
+ */
+static int proc_capidev_read_proc(char *page, char **start, off_t off,
+                                       int count, int *eof, void *data)
+{
+        struct capidev *cp;
+	int i;
+	int len = 0;
+	off_t begin = 0;
+
+	for (i=0; i < CAPI_MAXMINOR; i++) {
+		cp = &capidevs[i+1];
+		if (cp->nopen == 0) continue;
+		len += sprintf(page+len, "%d %lu %lu %lu %lu %lu\n",
+			i+1,
+			cp->nopen,
+			cp->nrecvctlpkt,
+			cp->nrecvdatapkt,
+			cp->nsentctlpkt,
+			cp->nsentdatapkt);
+		if (len+begin > off+count)
+			goto endloop;
+		if (len+begin < off) {
+			begin += len;
+			len = 0;
+		}
+	}
+endloop:
+	if (i >= CAPI_MAXMINOR)
+		*eof = 1;
+	if (off >= len+begin)
+		return 0;
+	*start = page + (begin-off);
+	return ((count < begin+len-off) ? count : begin+len-off);
+}
+
+static struct procfsentries {
+  char *name;
+  mode_t mode;
+  int (*read_proc)(char *page, char **start, off_t off,
+                                       int count, int *eof, void *data);
+  struct proc_dir_entry *procent;
+} procfsentries[] = {
+   /* { "capi",		  S_IFDIR, 0 }, */
+   { "capi/capi20", 	  0	 , proc_capidev_read_proc },
+};
+
+static void proc_init(void)
+{
+    int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
+    int i;
+
+    for (i=0; i < nelem; i++) {
+        struct procfsentries *p = procfsentries + i;
+	p->procent = create_proc_entry(p->name, p->mode, 0);
+	if (p->procent) p->procent->read_proc = p->read_proc;
+    }
+}
+
+static void proc_exit(void)
+{
+    int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
+    int i;
+
+    for (i=nelem-1; i >= 0; i--) {
+        struct procfsentries *p = procfsentries + i;
+	if (p->procent) {
+	   remove_proc_entry(p->name, 0);
+	   p->procent = 0;
+	}
+    }
+}
 /* -------- init function and module interface ---------------------- */
 
 #ifdef MODULE
@@ -501,12 +615,12 @@
 
 int capi_init(void)
 {
-#if LINUX_VERSION_CODE >= 131841
+#ifdef COMPAT_HAS_NEW_WAITQ
 	int j;
 #endif
 	
 	memset(capidevs, 0, sizeof(capidevs));
-#if LINUX_VERSION_CODE >= 131841
+#ifdef COMPAT_HAS_NEW_WAITQ
 	for ( j = 0; j < CAPI_MAXMINOR+1; j++ ) {
 		init_waitqueue_head(&capidevs[j].recv_wait);
 	}
@@ -522,13 +636,14 @@
 		unregister_chrdev(capi_major, "capi20");
 		return -EIO;
 	}
-	
+	(void)proc_init();
 	return 0;
 }
 
 #ifdef MODULE
 void cleanup_module(void)
 {
+	(void)proc_exit();
 	unregister_chrdev(capi_major, "capi20");
 	(void) detach_capi_interface(&cuser);
 }
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/avmb1/capidev.h linux/drivers/isdn/avmb1/capidev.h
--- v2.3.13/linux/drivers/isdn/avmb1/capidev.h	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/avmb1/capidev.h	Thu Aug 12 09:42:33 1999
@@ -1,11 +1,33 @@
 /*
- * $Id: capidev.h,v 1.1 1997/03/04 21:50:30 calle Exp $
+ * $Id: capidev.h,v 1.4 1999/07/01 15:26:32 calle Exp $
  *
  * CAPI 2.0 Interface for Linux
  *
  * (c) Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de)
  *
  * $Log: capidev.h,v $
+ * Revision 1.4  1999/07/01 15:26:32  calle
+ * complete new version (I love it):
+ * + new hardware independed "capi_driver" interface that will make it easy to:
+ *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ *   - write a CAPI-2.0 for the passive cards
+ *   - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ *   make menuconfig, in the past all supported cards where included
+ *   at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ *   using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+ *
+ * Revision 1.3  1999/07/01 08:22:58  keil
+ * compatibility macros now in <linux/isdn_compat.h>
+ *
+ * Revision 1.2  1999/06/21 15:24:13  calle
+ * extend information in /proc.
+ *
  * Revision 1.1  1997/03/04 21:50:30  calle
  * Frirst version in isdn4linux
  *
@@ -22,12 +44,18 @@
 	int is_registered;
 	__u16 applid;
 	struct sk_buff_head recv_queue;
-#if LINUX_VERSION_CODE < 131841
-	struct wait_queue *recv_wait;
-#else
+#ifdef COMPAT_HAS_NEW_WAITQ
 	wait_queue_head_t recv_wait;
+#else
+	struct wait_queue *recv_wait;
 #endif
 	__u16 errcode;
+	/* Statistic */
+	unsigned long nopen;
+	unsigned long nrecvctlpkt;
+	unsigned long nrecvdatapkt;
+	unsigned long nsentctlpkt;
+	unsigned long nsentdatapkt;
 };
 
 #define CAPI_MAXMINOR	CAPI_MAXAPPL
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/avmb1/capidrv.c linux/drivers/isdn/avmb1/capidrv.c
--- v2.3.13/linux/drivers/isdn/avmb1/capidrv.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/isdn/avmb1/capidrv.c	Thu Aug 12 09:42:33 1999
@@ -1,11 +1,67 @@
 /*
- * $Id: capidrv.c,v 1.13 1998/06/26 15:12:55 fritz Exp $
+ * $Id: capidrv.c,v 1.26 1999/08/06 07:41:16 calle Exp $
  *
  * ISDN4Linux Driver, using capi20 interface (kernelcapi)
  *
  * Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
  *
  * $Log: capidrv.c,v $
+ * Revision 1.26  1999/08/06 07:41:16  calle
+ * Added the "vbox patch". if (si1 == 1) si2 = 0;
+ *
+ * Revision 1.25  1999/08/04 10:10:11  calle
+ * Bugfix: corrected /proc functions, added structure for new AVM cards.
+ *
+ * Revision 1.24  1999/07/20 06:48:02  calle
+ * Bugfix: firmware version check for D2 trace was too restrictiv.
+ *
+ * Revision 1.23  1999/07/09 15:05:44  keil
+ * compat.h is now isdn_compat.h
+ *
+ * Revision 1.22  1999/07/06 07:24:14  calle
+ * Bugfix: call to kfree_skb in capidrv_signal was too early,
+ *         thanks to Lars Heete <hel@admin.de>.
+ *
+ * Revision 1.21  1999/07/01 15:26:34  calle
+ * complete new version (I love it):
+ * + new hardware independed "capi_driver" interface that will make it easy to:
+ *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ *   - write a CAPI-2.0 for the passive cards
+ *   - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ *   make menuconfig, in the past all supported cards where included
+ *   at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ *   using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+ *
+ * Revision 1.20  1999/07/01 08:22:59  keil
+ * compatibility macros now in <linux/isdn_compat.h>
+ *
+ * Revision 1.19  1999/06/29 16:16:54  calle
+ * Let ISDN_CMD_UNLOAD work with open isdn devices without crash again.
+ * Also right unlocking (ISDN_CMD_UNLOCK) is done now.
+ * isdnlog should check returncode of read(2) calls.
+ *
+ * Revision 1.18  1999/06/21 15:24:15  calle
+ * extend information in /proc.
+ *
+ * Revision 1.17  1999/06/10 16:53:55  calle
+ * Removing of module b1pci will now remove card from lower level.
+ *
+ * Revision 1.16  1999/05/31 11:50:33  calle
+ * Bugfix: In if_sendbuf, skb_push'ed DATA_B3 header was not skb_pull'ed
+ *         on failure, result in data block with DATA_B3 header transmitted
+ *
+ * Revision 1.15  1999/05/25 21:26:16  calle
+ * Include CAPI-Channelallocation (leased lines) from the 2.0 tree.
+ *
+ * Revision 1.14  1999/05/22 07:55:06  calle
+ * Added *V110* to AVM B1 driver.
+ *
  * Revision 1.13  1998/06/26 15:12:55  fritz
  * Added handling of STAT_ICALL with incomplete CPN.
  * Added AT&L for ttyI emulator.
@@ -96,15 +152,18 @@
 #include <linux/skbuff.h>
 #include <linux/isdn.h>
 #include <linux/isdnif.h>
+#include <linux/proc_fs.h>
 #include <linux/capi.h>
 #include <linux/kernelcapi.h>
+#include <linux/ctype.h>
+#include <asm/segment.h>
 
-#include "compat.h"
+#include <linux/isdn_compat.h>
 #include "capiutil.h"
 #include "capicmd.h"
 #include "capidrv.h"
 
-static char *revision = "$Revision: 1.13 $";
+static char *revision = "$Revision: 1.26 $";
 int debugmode = 0;
 
 MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
@@ -160,6 +219,7 @@
 			__u16 msgid;	/* to identfy CONNECT_CONF */
 			int chan;
 			int state;
+			int leasedline;
 			struct capidrv_ncci {
 				struct capidrv_ncci *next;
 				struct capidrv_plci *plcip;
@@ -194,6 +254,12 @@
 	__u16 appid;
 	int ncontr;
 	struct capidrv_contr *contr_list;
+
+        /* statistic */
+	unsigned long nrecvctlpkt;
+	unsigned long nrecvdatapkt;
+	unsigned long nsentctlpkt;
+	unsigned long nsentdatapkt;
 };
 
 typedef struct capidrv_plci capidrv_plci;
@@ -224,6 +290,12 @@
 		return 0;
 	case ISDN_PROTO_L2_TRANS:
 		return 1;
+        case ISDN_PROTO_L2_V11096:
+        case ISDN_PROTO_L2_V11019:
+        case ISDN_PROTO_L2_V11038:
+		return 2;
+        case ISDN_PROTO_L2_FAX:
+		return 4;
 	}
 }
 
@@ -237,7 +309,12 @@
 		return 0;
 	case ISDN_PROTO_L2_HDLC:
 	case ISDN_PROTO_L2_TRANS:
+        case ISDN_PROTO_L2_V11096:
+        case ISDN_PROTO_L2_V11019:
+        case ISDN_PROTO_L2_V11038:
 		return 1;
+        case ISDN_PROTO_L2_FAX:
+		return 4;
 	}
 }
 
@@ -249,8 +326,45 @@
 	case ISDN_PROTO_L2_X75BUI:
 	case ISDN_PROTO_L2_HDLC:
 	case ISDN_PROTO_L2_TRANS:
+        case ISDN_PROTO_L2_V11096:
+        case ISDN_PROTO_L2_V11019:
+        case ISDN_PROTO_L2_V11038:
 	default:
 		return 0;
+        case ISDN_PROTO_L2_FAX:
+		return 4;
+	}
+}
+
+static _cstruct b1config_sync_v110(__u16 rate)
+{
+	/* CAPI-Spec "B1 Configuration" */
+	static unsigned char buf[9];
+	buf[0] = 8; /* len */
+	/* maximum bitrate */
+	buf[1] = rate & 0xff; buf[2] = (rate >> 8) & 0xff;
+	buf[3] = buf[4] = 0; /* reserved, bits per character */
+	buf[5] = buf[6] = 0; /* reserved, parity */
+	buf[7] = buf[9] = 0; /* reserved, stop bits */
+	return buf;
+}
+
+static _cstruct b1config(int l2, int l3)
+{
+	switch (l2) {
+	case ISDN_PROTO_L2_X75I:
+	case ISDN_PROTO_L2_X75UI:
+	case ISDN_PROTO_L2_X75BUI:
+	case ISDN_PROTO_L2_HDLC:
+	case ISDN_PROTO_L2_TRANS:
+	default:
+		return 0;
+        case ISDN_PROTO_L2_V11096:
+	    return b1config_sync_v110(9600);
+        case ISDN_PROTO_L2_V11019:
+	    return b1config_sync_v110(19200);
+        case ISDN_PROTO_L2_V11038:
+	    return b1config_sync_v110(38400);
 	}
 }
 
@@ -522,9 +636,10 @@
 	size_t len;
 	capi_cmsg2message(cmsg, cmsg->buf);
 	len = CAPIMSG_LEN(cmsg->buf);
-	skb = dev_alloc_skb(len);
+	skb = alloc_skb(len, GFP_ATOMIC);
 	memcpy(skb_put(skb, len), cmsg->buf, len);
 	(*capifuncs->capi_put_message) (global.appid, skb);
+	global.nsentctlpkt++;
 }
 
 /* -------- state machine -------------------------------------------- */
@@ -917,6 +1032,13 @@
 			cmd.parm.setup.si2,
 			cmd.parm.setup.eazmsn);
 
+	if (cmd.parm.setup.si1 == 1 && cmd.parm.setup.si2 != 0) {
+		printk(KERN_INFO "capidrv-%d: patching si2=%d to 0 for VBOX\n", 
+			card->contrnr,
+			cmd.parm.setup.si2);
+		cmd.parm.setup.si2 = 0;
+	}
+
 	switch (card->interface.statcallb(&cmd)) {
 	case 0:
 	case 3:
@@ -1353,6 +1475,7 @@
 		printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n",
 		       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 		       cmsg->adr.adrController & 0x7f);
+		kfree_skb(skb);
 		return;
 	}
 	if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI))) {
@@ -1377,13 +1500,14 @@
 
 	while ((*capifuncs->capi_get_message) (global.appid, &skb) == CAPI_NOERROR) {
 		capi_message2cmsg(&s_cmsg, skb->data);
-		if (debugmode > 1)
+		if (debugmode > 2)
 			printk(KERN_DEBUG "capidrv_signal: applid=%d %s\n",
 					applid, capi_cmsg2str(&s_cmsg));
 
 		if (s_cmsg.Command == CAPI_DATA_B3
 		    && s_cmsg.Subcommand == CAPI_IND) {
 			handle_data(&s_cmsg, skb);
+			global.nrecvdatapkt++;
 			continue;
 		}
 		if ((s_cmsg.adr.adrController & 0xffffff00) == 0)
@@ -1392,8 +1516,13 @@
 			handle_plci(&s_cmsg);
 		else
 			handle_ncci(&s_cmsg);
-
+		/*
+		 * data of skb used in s_cmsg,
+		 * free data when s_cmsg is not used again
+		 * thanks to Lars Heete <hel@admin.de>
+		 */
 		kfree_skb(skb);
+		global.nrecvctlpkt++;
 	}
 }
 
@@ -1459,6 +1588,11 @@
 static int capidrv_ioctl(isdn_ctrl * c, capidrv_contr * card)
 {
 	switch (c->arg) {
+	case 1:
+		debugmode = (int)(*((unsigned int *)c->parm.num));
+		printk(KERN_DEBUG "capidrv-%d: debugmode=%d\n",
+				card->contrnr, debugmode);
+		return 0;
 	default:
 		printk(KERN_DEBUG "capidrv-%d: capidrv_ioctl(%ld) called ??\n",
 				card->contrnr, c->arg);
@@ -1467,11 +1601,103 @@
 	return -EINVAL;
 }
 
+/*
+ * Handle leased lines (CAPI-Bundling)
+ */
+
+struct internal_bchannelinfo {
+   unsigned short channelalloc;
+   unsigned short operation;
+   unsigned char  cmask[31];
+};
+
+static int decodeFVteln(char *teln, unsigned long *bmaskp, int *activep)
+{
+	unsigned long bmask = 0;
+	int active = !0;
+	char *s;
+	int i;
+
+	if (strncmp(teln, "FV:", 3) != 0)
+		return 1;
+	s = teln + 3;
+	while (*s && *s == ' ') s++;
+	if (!*s) return -2;
+	if (*s == 'p' || *s == 'P') {
+		active = 0;
+		s++;
+	}
+	if (*s == 'a' || *s == 'A') {
+		active = !0;
+		s++;
+	}
+	while (*s) {
+		int digit1 = 0;
+		int digit2 = 0;
+		if (!isdigit(*s)) return -3;
+		while (isdigit(*s)) { digit1 = digit1*10 + (*s - '0'); s++; }
+		if (digit1 <= 0 && digit1 > 30) return -4;
+		if (*s == 0 || *s == ',' || *s == ' ') {
+			bmask |= (1 << digit1);
+			digit1 = 0;
+			if (*s) s++;
+			continue;
+		}
+		if (*s != '-') return -5;
+		s++;
+		if (!isdigit(*s)) return -3;
+		while (isdigit(*s)) { digit2 = digit2*10 + (*s - '0'); s++; }
+		if (digit2 <= 0 && digit2 > 30) return -4;
+		if (*s == 0 || *s == ',' || *s == ' ') {
+			if (digit1 > digit2)
+				for (i = digit2; i <= digit1 ; i++)
+					bmask |= (1 << i);
+			else 
+				for (i = digit1; i <= digit2 ; i++)
+					bmask |= (1 << i);
+			digit1 = digit2 = 0;
+			if (*s) s++;
+			continue;
+		}
+		return -6;
+	}
+	if (activep) *activep = active;
+	if (bmaskp) *bmaskp = bmask;
+	return 0;
+}
+
+static int FVteln2capi20(char *teln, __u8 AdditionalInfo[1+2+2+31])
+{
+	unsigned long bmask;
+	int active;
+	int rc, i;
+   
+	rc = decodeFVteln(teln, &bmask, &active);
+	if (rc) return rc;
+	/* Length */
+	AdditionalInfo[0] = 2+2+31;
+        /* Channel: 3 => use channel allocation */
+        AdditionalInfo[1] = 3; AdditionalInfo[2] = 0;
+	/* Operation: 0 => DTE mode, 1 => DCE mode */
+        if (active) {
+   		AdditionalInfo[3] = 0; AdditionalInfo[4] = 0;
+   	} else {
+   		AdditionalInfo[3] = 1; AdditionalInfo[4] = 0;
+	}
+	/* Channel mask array */
+	AdditionalInfo[5] = 0; /* no D-Channel */
+	for (i=1; i <= 30; i++)
+		AdditionalInfo[5+i] = (bmask & (1 << i)) ? 0xff : 0;
+	return 0;
+}
+
 static int capidrv_command(isdn_ctrl * c, capidrv_contr * card)
 {
 	isdn_ctrl cmd;
 	struct capidrv_bchan *bchan;
 	struct capidrv_plci *plcip;
+	__u8 AdditionalInfo[1+2+2+31];
+        int rc, isleasedline = 0;
 
 	if (c->command == ISDN_CMD_IOCTL)
 		return capidrv_ioctl(c, card);
@@ -1508,15 +1734,25 @@
 
 			strncpy(bchan->num, c->parm.setup.phone, sizeof(bchan->num));
 			strncpy(bchan->mynum, c->parm.setup.eazmsn, sizeof(bchan->mynum));
-
-			calling[0] = strlen(bchan->mynum) + 2;
-			calling[1] = 0;
-			calling[2] = 0x80;
-			strncpy(calling + 3, bchan->mynum, ISDN_MSNLEN);
-
-			called[0] = strlen(bchan->num) + 1;
-			called[1] = 0x80;
-			strncpy(called + 2, bchan->num, ISDN_MSNLEN);
+                        rc = FVteln2capi20(bchan->num, AdditionalInfo);
+			isleasedline = (rc == 0);
+			if (rc < 0)
+				printk(KERN_ERR "capidrv-%d: WARNING: illegal leased linedefinition \"%s\"\n", card->contrnr, bchan->num);
+
+			if (isleasedline) {
+				calling[0] = 0;
+				called[0] = 0;
+			        if (debugmode)
+					printk(KERN_DEBUG "capidrv-%d: connecting leased line\n", card->contrnr);
+			} else {
+		        	calling[0] = strlen(bchan->mynum) + 2;
+		        	calling[1] = 0;
+		     		calling[2] = 0x80;
+			   	strncpy(calling + 3, bchan->mynum, ISDN_MSNLEN);
+				called[0] = strlen(bchan->num) + 1;
+				called[1] = 0x80;
+				strncpy(called + 2, bchan->num, ISDN_MSNLEN);
+			}
 
 			capi_fill_CONNECT_REQ(&cmdcmsg,
 					      global.appid,
@@ -1530,13 +1766,14 @@
 					    b1prot(bchan->l2, bchan->l3),	/* B1protocol */
 					    b2prot(bchan->l2, bchan->l3),	/* B2protocol */
 					    b3prot(bchan->l2, bchan->l3),	/* B3protocol */
-					      0,	/* B1configuration */
+					    b1config(bchan->l2, bchan->l3),	/* B1configuration */
 					      0,	/* B2configuration */
 					      0,	/* B3configuration */
 					      0,	/* BC */
 					      0,	/* LLC */
 					      0,	/* HLC */
-					      0,	/* BChannelinformation */
+					      /* BChannelinformation */
+					      isleasedline ? AdditionalInfo : 0,
 					      0,	/* Keypadfacility */
 					      0,	/* Useruserdata */
 					      0		/* Facilitydataarray */
@@ -1549,6 +1786,7 @@
 				return -1;
 			}
 			plcip->msgid = cmdcmsg.Messagenumber;
+			plcip->leasedline = isleasedline;
 			plci_change_state(card, plcip, EV_PLCI_CONNECT_REQ);
 			send_message(card, &cmdcmsg);
 			return 0;
@@ -1570,7 +1808,7 @@
 				       b1prot(bchan->l2, bchan->l3),	/* B1protocol */
 				       b2prot(bchan->l2, bchan->l3),	/* B2protocol */
 				       b3prot(bchan->l2, bchan->l3),	/* B3protocol */
-				       0,	/* B1configuration */
+				       b1config(bchan->l2, bchan->l3),	/* B1configuration */
 				       0,	/* B2configuration */
 				       0,	/* B3configuration */
 				       0,	/* ConnectedNumber */
@@ -1752,6 +1990,9 @@
 		       card->contrnr, id);
 		return 0;
 	}
+	if (debugmode > 1)
+		printk(KERN_DEBUG "capidrv-%d: sendbuf len=%d skb=%p doack=%d\n",
+					card->contrnr, len, skb, doack);
 	bchan = &card->bchans[channel % card->nbchan];
 	nccip = bchan->nccip;
 	if (!nccip || nccip->state != ST_NCCI_ACTIVE) {
@@ -1774,23 +2015,23 @@
 	capi_cmsg2message(&sendcmsg, sendcmsg.buf);
 	msglen = CAPIMSG_LEN(sendcmsg.buf);
 	if (skb_headroom(skb) < msglen) {
-		struct sk_buff *nskb = dev_alloc_skb(msglen + skb->len);
+		struct sk_buff *nskb = skb_realloc_headroom(skb, msglen);
 		if (!nskb) {
 			printk(KERN_ERR "capidrv-%d: if_sendbuf: no memory\n",
 				card->contrnr);
 		        (void)capidrv_del_ack(nccip, datahandle);
 			return 0;
 		}
-#if 0
-		printk(KERN_DEBUG "capidrv-%d: only %d bytes headroom\n",
-		       card->contrnr, skb_headroom(skb));
+#if 1
+		printk(KERN_DEBUG "capidrv-%d: only %d bytes headroom, need %d\n",
+		       card->contrnr, skb_headroom(skb), msglen);
 #endif
-		memcpy(skb_put(nskb, msglen), sendcmsg.buf, msglen);
-		memcpy(skb_put(nskb, skb->len), skb->data, skb->len);
+		memcpy(skb_push(nskb, msglen), sendcmsg.buf, msglen);
 		errcode = (*capifuncs->capi_put_message) (global.appid, nskb);
 		if (errcode == CAPI_NOERROR) {
 			dev_kfree_skb(skb);
 			nccip->datahandle++;
+			global.nsentdatapkt++;
 			return len;
 		}
 	        (void)capidrv_del_ack(nccip, datahandle);
@@ -1801,8 +2042,10 @@
 		errcode = (*capifuncs->capi_put_message) (global.appid, skb);
 		if (errcode == CAPI_NOERROR) {
 			nccip->datahandle++;
+			global.nsentdatapkt++;
 			return len;
 		}
+		skb_pull(skb, msglen);
 	        (void)capidrv_del_ack(nccip, datahandle);
 		return errcode == CAPI_SENDQUEUEFULL ? 0 : -1;
 	}
@@ -1847,8 +2090,8 @@
 	   return;
 	}
 	if (strstr(manufacturer, "AVM") == 0) {
-	   printk(KERN_ERR "%s: not from AVM, no d-channel trace possible\n",
-			card->name);
+	   printk(KERN_ERR "%s: not from AVM, no d-channel trace possible (%s)\n",
+			card->name, manufacturer);
 	   return;
 	}
         errcode = (*capifuncs->capi_get_version)(contr, &version);
@@ -1862,7 +2105,7 @@
 	avmversion[1] |= (version.minormanuversion >> 4) & 0x0f;
 	avmversion[2] |= version.minormanuversion & 0x0f;
 
-        if (avmversion[0] > 3 || (avmversion[0] == 3 && avmversion[1] > 6)) {
+        if (avmversion[0] > 3 || (avmversion[0] == 3 && avmversion[1] > 5)) {
 		printk(KERN_INFO "%s: D2 trace enabled\n", card->name);
 		capi_fill_MANUFACTURER_REQ(&cmdcmsg, global.appid,
 					   card->msgid++,
@@ -1884,6 +2127,51 @@
 	send_message(card, &cmdcmsg);
 }
 
+static void disable_dchannel_trace(capidrv_contr *card)
+{
+        __u8 manufacturer[CAPI_MANUFACTURER_LEN];
+        capi_version version;
+	__u16 contr = card->contrnr;
+	__u16 errcode;
+	__u16 avmversion[3];
+
+        errcode = (*capifuncs->capi_get_manufacturer)(contr, manufacturer);
+        if (errcode != CAPI_NOERROR) {
+	   printk(KERN_ERR "%s: can't get manufacturer (0x%x)\n",
+			card->name, errcode);
+	   return;
+	}
+	if (strstr(manufacturer, "AVM") == 0) {
+	   printk(KERN_ERR "%s: not from AVM, no d-channel trace possible (%s)\n",
+			card->name, manufacturer);
+	   return;
+	}
+        errcode = (*capifuncs->capi_get_version)(contr, &version);
+        if (errcode != CAPI_NOERROR) {
+	   printk(KERN_ERR "%s: can't get version (0x%x)\n",
+			card->name, errcode);
+	   return;
+	}
+	avmversion[0] = (version.majormanuversion >> 4) & 0x0f;
+	avmversion[1] = (version.majormanuversion << 4) & 0xf0;
+	avmversion[1] |= (version.minormanuversion >> 4) & 0x0f;
+	avmversion[2] |= version.minormanuversion & 0x0f;
+
+        if (avmversion[0] > 3 || (avmversion[0] == 3 && avmversion[1] > 5)) {
+		printk(KERN_INFO "%s: D2 trace disabled\n", card->name);
+	} else {
+		printk(KERN_INFO "%s: D3 trace disabled\n", card->name);
+	}
+	capi_fill_MANUFACTURER_REQ(&cmdcmsg, global.appid,
+				   card->msgid++,
+				   contr,
+				   0x214D5641,  /* ManuID */
+				   0,           /* Class */
+				   1,           /* Function */
+				   (_cstruct)"\004\000\000\000\000");
+	send_message(card, &cmdcmsg);
+}
+
 static int capidrv_addcontr(__u16 contr, struct capi_profile *profp)
 {
 	capidrv_contr *card;
@@ -1920,6 +2208,13 @@
 	    ISDN_FEATURE_L2_HDLC |
 	    ISDN_FEATURE_L2_TRANS |
 	    ISDN_FEATURE_L3_TRANS |
+	    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);
@@ -1964,8 +2259,7 @@
 	printk(KERN_INFO "%s: now up (%d B channels)\n",
 		card->name, card->nbchan);
 
-        if (card->nbchan == 2)  /* no T1 */
-        	enable_dchannel_trace(card);
+	enable_dchannel_trace(card);
 
 	return 0;
 }
@@ -1985,6 +2279,15 @@
 		return -1;
 	}
 	card = *pp;
+
+	if (debugmode)
+		printk(KERN_DEBUG "capidrv-%d: id=%d unloading\n",
+					card->contrnr, card->myid);
+
+	cmd.command = ISDN_STAT_UNLOAD;
+	cmd.driver = card->myid;
+	card->interface.statcallb(&cmd);
+
 	*pp = (*pp)->next;
 	global.ncontr--;
 
@@ -1998,10 +2301,6 @@
 	}
 	kfree(card->bchans);
 
-	cmd.command = ISDN_STAT_UNLOAD;
-	cmd.driver = card->myid;
-	card->interface.statcallb(&cmd);
-
 	printk(KERN_INFO "%s: now down.\n", card->name);
 
 	kfree(card);
@@ -2012,16 +2311,78 @@
 
 static void lower_callback(unsigned int cmd, __u16 contr, void *data)
 {
+
 	switch (cmd) {
 	case KCI_CONTRUP:
+		printk(KERN_INFO "capidrv: controller %hu up\n", contr);
 		(void) capidrv_addcontr(contr, (capi_profile *) data);
 		break;
 	case KCI_CONTRDOWN:
+		printk(KERN_INFO "capidrv: controller %hu down\n", contr);
 		(void) capidrv_delcontr(contr);
 		break;
 	}
 }
 
+/*
+ * /proc/capi/capidrv:
+ * nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt
+ */
+static int proc_capidrv_read_proc(char *page, char **start, off_t off,
+                                       int count, int *eof, void *data)
+{
+	int len = 0;
+
+	len += sprintf(page+len, "%lu %lu %lu %lu\n",
+			global.nrecvctlpkt,
+			global.nrecvdatapkt,
+			global.nsentctlpkt,
+			global.nsentdatapkt);
+	if (off+count >= len)
+	   *eof = 1;
+	if (len < off)
+           return 0;
+	*start = page + off;
+	return ((count < len-off) ? count : len-off);
+}
+
+static struct procfsentries {
+  char *name;
+  mode_t mode;
+  int (*read_proc)(char *page, char **start, off_t off,
+                                       int count, int *eof, void *data);
+  struct proc_dir_entry *procent;
+} procfsentries[] = {
+   /* { "capi",		  S_IFDIR, 0 }, */
+   { "capi/capidrv", 	  0	 , proc_capidrv_read_proc },
+};
+
+static void proc_init(void)
+{
+    int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
+    int i;
+
+    for (i=0; i < nelem; i++) {
+        struct procfsentries *p = procfsentries + i;
+	p->procent = create_proc_entry(p->name, p->mode, 0);
+	if (p->procent) p->procent->read_proc = p->read_proc;
+    }
+}
+
+static void proc_exit(void)
+{
+    int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
+    int i;
+
+    for (i=nelem-1; i >= 0; i--) {
+        struct procfsentries *p = procfsentries + i;
+	if (p->procent) {
+	   remove_proc_entry(p->name, 0);
+	   p->procent = 0;
+	}
+    }
+}
+
 static struct capi_interface_user cuser = {
 	"capidrv",
 	lower_callback
@@ -2077,6 +2438,7 @@
 			continue;
 		(void) capidrv_addcontr(contr, &profile);
 	}
+	proc_init();
 
 	return 0;
 }
@@ -2098,11 +2460,13 @@
 
 	for (card = global.contr_list; card; card = next) {
 		next = card->next;
+		disable_dchannel_trace(card);
 		capidrv_delcontr(card->contrnr);
 	}
 
 	(void) (*capifuncs->capi_release) (global.appid);
 	detach_capi_interface(&cuser);
+	proc_exit();
 
 	printk(KERN_NOTICE "capidrv: Rev%s: unloaded\n", rev);
 }
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/avmb1/capilli.h linux/drivers/isdn/avmb1/capilli.h
--- v2.3.13/linux/drivers/isdn/avmb1/capilli.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/avmb1/capilli.h	Thu Aug 12 09:42:33 1999
@@ -0,0 +1,110 @@
+/*
+ * $Id: capilli.h,v 1.4 1999/07/23 08:51:05 calle Exp $
+ * 
+ * Kernel CAPI 2.0 Driver Interface for Linux
+ * 
+ * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
+ * 
+ */
+#ifndef __CAPILLI_H__
+#define __CAPILLI_H__
+
+typedef struct capiloaddatapart {
+	int user;		/* data in userspace ? */
+	int len;
+	unsigned char *data;
+} capiloaddatapart;
+
+typedef struct capiloaddata {
+	capiloaddatapart firmware;
+	capiloaddatapart configuration;
+} capiloaddata;
+
+typedef struct capicardparams {
+	unsigned int port;
+	unsigned irq;
+	int cardtype;
+	int cardnr;
+	unsigned int membase;
+} capicardparams;
+
+struct capi_driver;
+
+struct capi_ctr {
+        struct capi_ctr *next;			/* next ctr of same driver */
+        struct capi_driver *driver;
+	int cnr;				/* controller number */
+	char name[32];				/* name of controller */
+	volatile unsigned short cardstate;	/* controller state */
+	volatile int blocked;			/* output blocked */
+	int traceflag;				/* capi trace */
+
+	void *driverdata;			/* driver specific */
+
+	/* filled before calling ready callback */
+	__u8 manu[CAPI_MANUFACTURER_LEN];	/* CAPI_GET_MANUFACTURER */
+	capi_version version;			/* CAPI_GET_VERSION */
+	capi_profile profile;			/* CAPI_GET_PROFILE */
+	__u8 serial[CAPI_SERIAL_LEN];		/* CAPI_GET_SERIAL */
+
+	/* functions */
+        void (*ready)(struct capi_ctr * card);
+        void (*reseted)(struct capi_ctr * card);
+        void (*suspend_output)(struct capi_ctr * card);
+        void (*resume_output)(struct capi_ctr * card);
+        void (*handle_capimsg)(struct capi_ctr * card,
+			   	__u16 appl, struct sk_buff *skb);
+	void (*appl_registered)(struct capi_ctr * card, __u16 appl);
+	void (*appl_released)(struct capi_ctr * card, __u16 appl);
+
+        void (*new_ncci)(struct capi_ctr * card,
+			   	__u16 appl, __u32 ncci, __u32 winsize);
+        void (*free_ncci)(struct capi_ctr * card, __u16 appl, __u32 ncci);
+
+	/* management information for kcapi */
+
+	unsigned long nrecvctlpkt;
+	unsigned long nrecvdatapkt;
+	unsigned long nsentctlpkt;
+	unsigned long nsentdatapkt;
+
+	struct proc_dir_entry *procent;
+        char procfn[128];
+};
+
+struct capi_driver_interface {
+    struct capi_ctr *(*attach_ctr)(struct capi_driver *driver, char *name, void *data);
+    int (*detach_ctr)(struct capi_ctr *);
+};
+
+struct capi_driver {
+     char name[32];				/* driver name */
+     char revision[32];
+     int (*load_firmware)(struct capi_ctr *, capiloaddata *);
+     void (*reset_ctr)(struct capi_ctr *);
+     void (*remove_ctr)(struct capi_ctr *);
+     void (*register_appl)(struct capi_ctr *, __u16 appl,
+						capi_register_params *);
+     void (*release_appl)(struct capi_ctr *, __u16 appl);
+     void (*send_message)(struct capi_ctr *, struct sk_buff *skb);
+
+     char *(*procinfo)(struct capi_ctr *);
+     int (*ctr_read_proc)(char *page, char **start, off_t off,
+			       int count, int *eof, struct capi_ctr *card);
+     int (*driver_read_proc)(char *page, char **start, off_t off,
+		               int count, int *eof, struct capi_driver *driver);
+
+     int (*add_card)(struct capi_driver *driver, capicardparams *data);
+
+     /* intitialized by kcapi */
+     struct capi_ctr	*controller;		/* list of controllers */
+     struct capi_driver *next;
+     int ncontroller;
+     struct proc_dir_entry *procent;
+     char procfn[128];
+};
+
+struct capi_driver_interface *attach_capi_driver(struct capi_driver *driver);
+void detach_capi_driver(struct capi_driver *driver);
+
+#endif				/* __CAPILLI_H__ */
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/avmb1/capiutil.c linux/drivers/isdn/avmb1/capiutil.c
--- v2.3.13/linux/drivers/isdn/avmb1/capiutil.c	Wed Apr  1 16:20:57 1998
+++ linux/drivers/isdn/avmb1/capiutil.c	Thu Aug 12 09:42:33 1999
@@ -1,5 +1,5 @@
 /*
- * $Id: capiutil.c,v 1.6 1997/11/04 06:12:12 calle Exp $
+ * $Id: capiutil.c,v 1.9 1999/07/09 15:05:46 keil Exp $
  *
  * CAPI 2.0 convert capi message to capi message struct
  *
@@ -7,6 +7,28 @@
  * Rewritten for Linux 1996 by Carsten Paeth (calle@calle.in-berlin.de)
  *
  * $Log: capiutil.c,v $
+ * Revision 1.9  1999/07/09 15:05:46  keil
+ * compat.h is now isdn_compat.h
+ *
+ * Revision 1.8  1999/07/01 15:26:37  calle
+ * complete new version (I love it):
+ * + new hardware independed "capi_driver" interface that will make it easy to:
+ *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ *   - write a CAPI-2.0 for the passive cards
+ *   - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ *   make menuconfig, in the past all supported cards where included
+ *   at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ *   using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+ *
+ * Revision 1.7  1999/07/01 08:23:01  keil
+ * compatibility macros now in <linux/isdn_compat.h>
+ *
  * Revision 1.6  1997/11/04 06:12:12  calle
  * capi.c: new read/write in file_ops since 2.1.60
  * capidrv.c: prepared isdnlog interface for d2-trace in newer firmware.
@@ -48,7 +70,7 @@
 #include <asm/segment.h>
 #include <linux/config.h>
 
-#include "compat.h"
+#include <linux/isdn_compat.h>
 #include "capiutil.h"
 
 /* from CAPI2.0 DDK AVM Berlin GmbH */
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/avmb1/kcapi.c linux/drivers/isdn/avmb1/kcapi.c
--- v2.3.13/linux/drivers/isdn/avmb1/kcapi.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/avmb1/kcapi.c	Thu Aug 12 09:42:33 1999
@@ -0,0 +1,1553 @@
+/*
+ * $Id: kcapi.c,v 1.6 1999/07/20 06:41:49 calle Exp $
+ * 
+ * Kernel CAPI 2.0 Module
+ * 
+ * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
+ * 
+ * $Log: kcapi.c,v $
+ * 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.
+ *
+ * Revision 1.5  1999/07/09 15:05:48  keil
+ * compat.h is now isdn_compat.h
+ *
+ * Revision 1.4  1999/07/08 14:15:17  calle
+ * Forgot to count down ncards in drivercb_detach_ctr.
+ *
+ * Revision 1.3  1999/07/06 07:42:02  calle
+ * - changes in /proc interface
+ * - check and changed calls to [dev_]kfree_skb and [dev_]alloc_skb.
+ *
+ * Revision 1.2  1999/07/05 15:09:52  calle
+ * - renamed "appl_release" to "appl_released".
+ * - version und profile data now cleared on controller reset
+ * - extended /proc interface, to allow driver and controller specific
+ *   informations to include by driver hackers.
+ *
+ * Revision 1.1  1999/07/01 15:26:42  calle
+ * complete new version (I love it):
+ * + new hardware independed "capi_driver" interface that will make it easy to:
+ *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ *   - write a CAPI-2.0 for the passive cards
+ *   - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ *   make menuconfig, in the past all supported cards where included
+ *   at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ *   using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+ *
+ */
+#define CONFIG_AVMB1_COMPAT
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <asm/segment.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <linux/tqueue.h>
+#include <linux/capi.h>
+#include <linux/kernelcapi.h>
+#include <linux/isdn_compat.h>
+#include "capicmd.h"
+#include "capiutil.h"
+#include "capilli.h"
+#ifdef CONFIG_AVMB1_COMPAT
+#include <linux/b1lli.h>
+#endif
+
+static char *revision = "$Revision: 1.6 $";
+
+/* ------------------------------------------------------------- */
+
+#define CARD_FREE	0
+#define CARD_DETECTED	1
+#define CARD_LOADING	2
+#define CARD_RUNNING	3
+
+/* ------------------------------------------------------------- */
+
+int showcapimsgs = 0;
+
+MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
+MODULE_PARM(showcapimsgs, "0-4i");
+
+/* ------------------------------------------------------------- */
+
+struct msgidqueue {
+	struct msgidqueue *next;
+	__u16 msgid;
+};
+
+struct capi_ncci {
+	struct capi_ncci *next;
+	__u16 applid;
+	__u32 ncci;
+	__u32 winsize;
+	int   nmsg;
+	struct msgidqueue *msgidqueue;
+	struct msgidqueue *msgidlast;
+	struct msgidqueue *msgidfree;
+	struct msgidqueue msgidpool[CAPI_MAXDATAWINDOW];
+};
+
+struct capi_appl {
+	__u16 applid;
+	capi_register_params rparam;
+	int releasing;
+	__u32 param;
+	void (*signal) (__u16 applid, __u32 param);
+	struct sk_buff_head recv_queue;
+	int nncci;
+	struct capi_ncci *nccilist;
+
+	unsigned long nrecvctlpkt;
+	unsigned long nrecvdatapkt;
+	unsigned long nsentctlpkt;
+	unsigned long nsentdatapkt;
+};
+
+/* ------------------------------------------------------------- */
+
+static struct capi_version driver_version = {2, 0, 1, 1<<4};
+static char driver_serial[CAPI_SERIAL_LEN] = "4711";
+static char capi_manufakturer[64] = "AVM Berlin";
+
+#define APPL(a)		   (&applications[(a)-1])
+#define	VALID_APPLID(a)	   ((a) && (a) <= CAPI_MAXAPPL && APPL(a)->applid == a)
+#define APPL_IS_FREE(a)    (APPL(a)->applid == 0)
+#define APPL_MARK_FREE(a)  do{ APPL(a)->applid=0; MOD_DEC_USE_COUNT; }while(0);
+#define APPL_MARK_USED(a)  do{ APPL(a)->applid=(a); MOD_INC_USE_COUNT; }while(0);
+
+#define NCCI2CTRL(ncci)    (((ncci) >> 24) & 0x7f)
+
+#define VALID_CARD(c)	   ((c) > 0 && (c) <= CAPI_MAXCONTR)
+#define CARD(c)		   (&cards[(c)-1])
+#define CARDNR(cp)	   (((cp)-cards)+1)
+
+static struct capi_appl applications[CAPI_MAXAPPL];
+static struct capi_ctr cards[CAPI_MAXCONTR];
+static int ncards = 0;
+static struct sk_buff_head recv_queue;
+static struct capi_interface_user *capi_users = 0;
+static struct capi_driver *drivers;
+#ifdef CONFIG_AVMB1_COMPAT
+static struct capi_driver *b1isa_driver;
+static struct capi_driver *t1isa_driver;
+#endif
+static long notify_up_set = 0;
+static long notify_down_set = 0;
+
+static struct tq_struct tq_state_notify;
+static struct tq_struct tq_recv_notify;
+
+/* -------- util functions ------------------------------------ */
+
+static char *cardstate2str(unsigned short cardstate)
+{
+	switch (cardstate) {
+        	default:
+		case CARD_FREE:		return "free";
+		case CARD_DETECTED:	return "detected";
+		case CARD_LOADING:	return "loading";
+		case CARD_RUNNING:	return "running";
+	}
+}
+
+static inline int capi_cmd_valid(__u8 cmd)
+{
+	switch (cmd) {
+	case CAPI_ALERT:
+	case CAPI_CONNECT:
+	case CAPI_CONNECT_ACTIVE:
+	case CAPI_CONNECT_B3_ACTIVE:
+	case CAPI_CONNECT_B3:
+	case CAPI_CONNECT_B3_T90_ACTIVE:
+	case CAPI_DATA_B3:
+	case CAPI_DISCONNECT_B3:
+	case CAPI_DISCONNECT:
+	case CAPI_FACILITY:
+	case CAPI_INFO:
+	case CAPI_LISTEN:
+	case CAPI_MANUFACTURER:
+	case CAPI_RESET_B3:
+	case CAPI_SELECT_B_PROTOCOL:
+		return 1;
+	}
+	return 0;
+}
+
+static inline int capi_subcmd_valid(__u8 subcmd)
+{
+	switch (subcmd) {
+	case CAPI_REQ:
+	case CAPI_CONF:
+	case CAPI_IND:
+	case CAPI_RESP:
+		return 1;
+	}
+	return 0;
+}
+
+/* -------- /proc functions ----------------------------------- */
+/*
+ * /proc/capi/applications:
+ *      applid l3cnt dblkcnt dblklen #ncci recvqueuelen
+ */
+static int proc_applications_read_proc(char *page, char **start, off_t off,
+                                       int count, int *eof, void *data)
+{
+	struct capi_appl *ap;
+	int i;
+	int len = 0;
+	off_t begin = 0;
+
+	for (i=0; i < CAPI_MAXAPPL; i++) {
+		ap = &applications[i];
+		if (ap->applid == 0) continue;
+		len += sprintf(page+len, "%u %d %d %d %d %d\n",
+			ap->applid,
+			ap->rparam.level3cnt,
+			ap->rparam.datablkcnt,
+			ap->rparam.datablklen,
+			ap->nncci,
+                        skb_queue_len(&ap->recv_queue));
+		if (len+begin > off+count)
+			goto endloop;
+		if (len+begin < off) {
+			begin += len;
+			len = 0;
+		}
+	}
+endloop:
+	if (i >= CAPI_MAXAPPL)
+		*eof = 1;
+	if (off >= len+begin)
+		return 0;
+	*start = page + (begin-off);
+	return ((count < begin+len-off) ? count : begin+len-off);
+}
+
+/*
+ * /proc/capi/ncci:
+ *	applid ncci winsize nblk
+ */
+static int proc_ncci_read_proc(char *page, char **start, off_t off,
+                                       int count, int *eof, void *data)
+{
+	struct capi_appl *ap;
+	struct capi_ncci *np;
+	int i;
+	int len = 0;
+	off_t begin = 0;
+
+	for (i=0; i < CAPI_MAXAPPL; i++) {
+		ap = &applications[i];
+		if (ap->applid == 0) continue;
+		for (np = ap->nccilist; np; np = np->next) {
+			len += sprintf(page+len, "%d 0x%x %d %d\n",
+				np->applid,
+				np->ncci,
+				np->winsize,
+				np->nmsg);
+			if (len+begin > off+count)
+				goto endloop;
+			if (len+begin < off) {
+				begin += len;
+				len = 0;
+			}
+		}
+	}
+endloop:
+	if (i >= CAPI_MAXAPPL)
+		*eof = 1;
+	if (off >= len+begin)
+		return 0;
+	*start = page + (begin-off);
+	return ((count < begin+len-off) ? count : begin+len-off);
+}
+
+/*
+ * /proc/capi/driver:
+ *	driver ncontroller
+ */
+static int proc_driver_read_proc(char *page, char **start, off_t off,
+                                       int count, int *eof, void *data)
+{
+	struct capi_driver *driver;
+	int len = 0;
+	off_t begin = 0;
+
+	for (driver = drivers; driver; driver = driver->next) {
+		len += sprintf(page+len, "%-32s %d %s\n",
+					driver->name,
+					driver->ncontroller,
+					driver->revision);
+		if (len+begin > off+count)
+			goto endloop;
+		if (len+begin < off) {
+			begin += len;
+			len = 0;
+		}
+	}
+endloop:
+	if (!driver)
+		*eof = 1;
+	if (off >= len+begin)
+		return 0;
+	*start = page + (begin-off);
+	return ((count < begin+len-off) ? count : begin+len-off);
+}
+
+/*
+ * /proc/capi/users:
+ *	name
+ */
+static int proc_users_read_proc(char *page, char **start, off_t off,
+                                       int count, int *eof, void *data)
+{
+        struct capi_interface_user *cp;
+	int len = 0;
+	off_t begin = 0;
+
+        for (cp = capi_users; cp ; cp = cp->next) {
+		len += sprintf(page+len, "%s\n", cp->name);
+		if (len+begin > off+count)
+			goto endloop;
+		if (len+begin < off) {
+			begin += len;
+			len = 0;
+		}
+	}
+endloop:
+	if (cp == 0)
+		*eof = 1;
+	if (off >= len+begin)
+		return 0;
+	*start = page + (begin-off);
+	return ((count < begin+len-off) ? count : begin+len-off);
+}
+
+/*
+ * /proc/capi/controller:
+ *	cnr driver cardstate name driverinfo
+ */
+static int proc_controller_read_proc(char *page, char **start, off_t off,
+                                       int count, int *eof, void *data)
+{
+	struct capi_ctr *cp;
+	int i;
+	int len = 0;
+	off_t begin = 0;
+
+	for (i=0; i < CAPI_MAXCONTR; i++) {
+		cp = &cards[i];
+		if (cp->cardstate == CARD_FREE) continue;
+		len += sprintf(page+len, "%d %-10s %-8s %-16s %s\n",
+			cp->cnr, cp->driver->name, 
+			cardstate2str(cp->cardstate),
+			cp->name,
+			cp->driver->procinfo ?  cp->driver->procinfo(cp) : ""
+			);
+		if (len+begin > off+count)
+			goto endloop;
+		if (len+begin < off) {
+			begin += len;
+			len = 0;
+		}
+	}
+endloop:
+	if (i >= CAPI_MAXCONTR)
+		*eof = 1;
+	if (off >= len+begin)
+		return 0;
+	*start = page + (begin-off);
+	return ((count < begin+len-off) ? count : begin+len-off);
+}
+
+/*
+ * /proc/capi/applstats:
+ *	applid nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt
+ */
+static int proc_applstats_read_proc(char *page, char **start, off_t off,
+                                       int count, int *eof, void *data)
+{
+	struct capi_appl *ap;
+	int i;
+	int len = 0;
+	off_t begin = 0;
+
+	for (i=0; i < CAPI_MAXAPPL; i++) {
+		ap = &applications[i];
+		if (ap->applid == 0) continue;
+		len += sprintf(page+len, "%u %lu %lu %lu %lu\n",
+			ap->applid,
+			ap->nrecvctlpkt,
+			ap->nrecvdatapkt,
+			ap->nsentctlpkt,
+			ap->nsentdatapkt);
+		if (len+begin > off+count)
+			goto endloop;
+		if (len+begin < off) {
+			begin += len;
+			len = 0;
+		}
+	}
+endloop:
+	if (i >= CAPI_MAXAPPL)
+		*eof = 1;
+	if (off >= len+begin)
+		return 0;
+	*start = page + (begin-off);
+	return ((count < begin+len-off) ? count : begin+len-off);
+}
+
+/*
+ * /proc/capi/contrstats:
+ *	cnr nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt
+ */
+static int proc_contrstats_read_proc(char *page, char **start, off_t off,
+                                       int count, int *eof, void *data)
+{
+	struct capi_ctr *cp;
+	int i;
+	int len = 0;
+	off_t begin = 0;
+
+	for (i=0; i < CAPI_MAXCONTR; i++) {
+		cp = &cards[i];
+		if (cp->cardstate == CARD_FREE) continue;
+		len += sprintf(page+len, "%d %lu %lu %lu %lu\n",
+			cp->cnr, 
+			cp->nrecvctlpkt,
+			cp->nrecvdatapkt,
+			cp->nsentctlpkt,
+			cp->nsentdatapkt);
+		if (len+begin > off+count)
+			goto endloop;
+		if (len+begin < off) {
+			begin += len;
+			len = 0;
+		}
+	}
+endloop:
+	if (i >= CAPI_MAXCONTR)
+		*eof = 1;
+	if (off >= len+begin)
+		return 0;
+	*start = page + (begin-off);
+	return ((count < begin+len-off) ? count : begin+len-off);
+}
+
+static struct procfsentries {
+  char *name;
+  mode_t mode;
+  int (*read_proc)(char *page, char **start, off_t off,
+                                       int count, int *eof, void *data);
+  struct proc_dir_entry *procent;
+} procfsentries[] = {
+   { "capi",		  S_IFDIR, 0 },
+   { "capi/applications", 0	 , proc_applications_read_proc },
+   { "capi/ncci", 	  0	 , proc_ncci_read_proc },
+   { "capi/driver",       0	 , proc_driver_read_proc },
+   { "capi/users", 	  0	 , proc_users_read_proc },
+   { "capi/controller",   0	 , proc_controller_read_proc },
+   { "capi/applstats",    0	 , proc_applstats_read_proc },
+   { "capi/contrstats",   0	 , proc_contrstats_read_proc },
+   { "capi/drivers",	  S_IFDIR, 0 },
+   { "capi/controllers",  S_IFDIR, 0 },
+};
+
+static void proc_capi_init(void)
+{
+    int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
+    int i;
+
+    for (i=0; i < nelem; i++) {
+        struct procfsentries *p = procfsentries + i;
+	p->procent = create_proc_entry(p->name, p->mode, 0);
+	if (p->procent) p->procent->read_proc = p->read_proc;
+    }
+}
+
+static void proc_capi_exit(void)
+{
+    int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
+    int i;
+
+    for (i=nelem-1; i >= 0; i--) {
+        struct procfsentries *p = procfsentries + i;
+	if (p->procent) {
+	   remove_proc_entry(p->name, 0);
+	   p->procent = 0;
+	}
+    }
+}
+
+/* -------- NCCI Handling ------------------------------------- */
+
+static inline void mq_init(struct capi_ncci * np)
+{
+	int i;
+	np->msgidqueue = 0;
+	np->msgidlast = 0;
+	np->nmsg = 0;
+	memset(np->msgidpool, 0, sizeof(np->msgidpool));
+	np->msgidfree = &np->msgidpool[0];
+	for (i = 1; i < np->winsize; i++) {
+		np->msgidpool[i].next = np->msgidfree;
+		np->msgidfree = &np->msgidpool[i];
+	}
+}
+
+static inline int mq_enqueue(struct capi_ncci * np, __u16 msgid)
+{
+	struct msgidqueue *mq;
+	if ((mq = np->msgidfree) == 0)
+		return 0;
+	np->msgidfree = mq->next;
+	mq->msgid = msgid;
+	mq->next = 0;
+	if (np->msgidlast)
+		np->msgidlast->next = mq;
+	np->msgidlast = mq;
+	if (!np->msgidqueue)
+		np->msgidqueue = mq;
+	np->nmsg++;
+	return 1;
+}
+
+static inline int mq_dequeue(struct capi_ncci * np, __u16 msgid)
+{
+	struct msgidqueue **pp;
+	for (pp = &np->msgidqueue; *pp; pp = &(*pp)->next) {
+		if ((*pp)->msgid == msgid) {
+			struct msgidqueue *mq = *pp;
+			*pp = mq->next;
+			if (mq == np->msgidlast)
+				np->msgidlast = 0;
+			mq->next = np->msgidfree;
+			np->msgidfree = mq;
+			np->nmsg--;
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static void controllercb_appl_registered(struct capi_ctr * card, __u16 appl)
+{
+}
+
+static void controllercb_appl_released(struct capi_ctr * card, __u16 appl)
+{
+	struct capi_ncci **pp, **nextpp;
+	for (pp = &APPL(appl)->nccilist; *pp; pp = nextpp) {
+		if (NCCI2CTRL((*pp)->ncci) == card->cnr) {
+			struct capi_ncci *np = *pp;
+			*pp = np->next;
+			printk(KERN_INFO "kcapi: appl %d ncci 0x%x down!\n", appl, np->ncci);
+			kfree(np);
+			APPL(appl)->nncci--;
+			nextpp = pp;
+		} else {
+			nextpp = &(*pp)->next;
+		}
+	}
+	APPL(appl)->releasing--;
+	if (APPL(appl)->releasing <= 0) {
+		APPL(appl)->signal = 0;
+		APPL_MARK_FREE(appl);
+		printk(KERN_INFO "kcapi: appl %d down\n", appl);
+	}
+}
+/*
+ * ncci managment
+ */
+
+static void controllercb_new_ncci(struct capi_ctr * card,
+					__u16 appl, __u32 ncci, __u32 winsize)
+{
+	struct capi_ncci *np;
+	if (!VALID_APPLID(appl)) {
+		printk(KERN_ERR "avmb1_handle_new_ncci: illegal appl %d\n", appl);
+		return;
+	}
+	if ((np = (struct capi_ncci *) kmalloc(sizeof(struct capi_ncci), GFP_ATOMIC)) == 0) {
+		printk(KERN_ERR "capi_new_ncci: alloc failed ncci 0x%x\n", ncci);
+		return;
+	}
+	if (winsize > CAPI_MAXDATAWINDOW) {
+		printk(KERN_ERR "capi_new_ncci: winsize %d too big, set to %d\n",
+		       winsize, CAPI_MAXDATAWINDOW);
+		winsize = CAPI_MAXDATAWINDOW;
+	}
+	np->applid = appl;
+	np->ncci = ncci;
+	np->winsize = winsize;
+	mq_init(np);
+	np->next = APPL(appl)->nccilist;
+	APPL(appl)->nccilist = np;
+	APPL(appl)->nncci++;
+	printk(KERN_INFO "kcapi: appl %d ncci 0x%x up\n", appl, ncci);
+
+}
+
+static void controllercb_free_ncci(struct capi_ctr * card,
+				__u16 appl, __u32 ncci)
+{
+	struct capi_ncci **pp;
+	if (!VALID_APPLID(appl)) {
+		printk(KERN_ERR "free_ncci: illegal appl %d\n", appl);
+		return;
+	}
+	for (pp = &APPL(appl)->nccilist; *pp; pp = &(*pp)->next) {
+		if ((*pp)->ncci == ncci) {
+			struct capi_ncci *np = *pp;
+			*pp = np->next;
+			kfree(np);
+			APPL(appl)->nncci--;
+			printk(KERN_INFO "kcapi: appl %d ncci 0x%x down\n", appl, ncci);
+			return;
+		}
+	}
+	printk(KERN_ERR "free_ncci: ncci 0x%x not found\n", ncci);
+}
+
+
+static struct capi_ncci *find_ncci(struct capi_appl * app, __u32 ncci)
+{
+	struct capi_ncci *np;
+	for (np = app->nccilist; np; np = np->next) {
+		if (np->ncci == ncci)
+			return np;
+	}
+	return 0;
+}
+
+/* -------- Receiver ------------------------------------------ */
+
+static void recv_handler(void *dummy)
+{
+	struct sk_buff *skb;
+
+	while ((skb = skb_dequeue(&recv_queue)) != 0) {
+		__u16 appl = CAPIMSG_APPID(skb->data);
+		struct capi_ncci *np;
+		if (!VALID_APPLID(appl)) {
+			printk(KERN_ERR "kcapi: recv_handler: applid %d ? (%s)\n",
+			       appl, capi_message2str(skb->data));
+			kfree_skb(skb);
+			continue;
+		}
+		if (APPL(appl)->signal == 0) {
+			printk(KERN_ERR "kcapi: recv_handler: applid %d has no signal function\n",
+			       appl);
+			kfree_skb(skb);
+			continue;
+		}
+		if (   CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3
+		    && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_CONF
+	            && (np = find_ncci(APPL(appl), CAPIMSG_NCCI(skb->data))) != 0
+		    && mq_dequeue(np, CAPIMSG_MSGID(skb->data)) == 0) {
+			printk(KERN_ERR "kcapi: msgid %hu ncci 0x%x not on queue\n",
+				CAPIMSG_MSGID(skb->data), np->ncci);
+		}
+		if (   CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3
+		    && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) {
+			APPL(appl)->nrecvdatapkt++;
+		} else {
+			APPL(appl)->nrecvctlpkt++;
+		}
+		skb_queue_tail(&APPL(appl)->recv_queue, skb);
+		(APPL(appl)->signal) (APPL(appl)->applid, APPL(appl)->param);
+	}
+}
+
+static void controllercb_handle_capimsg(struct capi_ctr * card,
+				__u16 appl, struct sk_buff *skb)
+{
+	int showctl = 0;
+	__u8 cmd, subcmd;
+
+	if (card->cardstate != CARD_RUNNING) {
+		printk(KERN_INFO "kcapi: controller %d not active, got: %s",
+		       card->cnr, capi_message2str(skb->data));
+		goto error;
+	}
+	cmd = CAPIMSG_COMMAND(skb->data);
+        subcmd = CAPIMSG_SUBCOMMAND(skb->data);
+	if (cmd == CAPI_DATA_B3 && subcmd == CAPI_IND) {
+		card->nrecvdatapkt++;
+	        if (card->traceflag > 2) showctl |= 2;
+	        if (card->traceflag) showctl |= 2;
+	} else {
+		card->nrecvctlpkt++;
+	}
+	showctl |= (card->traceflag & 1);
+	if (showctl & 2) {
+		if (showctl & 1) {
+			printk(KERN_DEBUG "kcapi: got [0x%lx] id#%d %s len=%u\n",
+			       (unsigned long) card->cnr,
+			       CAPIMSG_APPID(skb->data),
+			       capi_cmd2str(cmd, subcmd),
+			       CAPIMSG_LEN(skb->data));
+		} else {
+			printk(KERN_DEBUG "kcapi: got [0x%lx] %s\n",
+					(unsigned long) card->cnr,
+					capi_message2str(skb->data));
+		}
+
+	}
+	skb_queue_tail(&recv_queue, skb);
+	queue_task(&tq_recv_notify, &tq_immediate);
+	mark_bh(IMMEDIATE_BH);
+	return;
+
+error:
+	kfree_skb(skb);
+}
+
+/* -------- Notifier ------------------------------------------ */
+
+static void notify_up(__u16 contr)
+{
+	struct capi_interface_user *p;
+
+        printk(KERN_NOTICE "kcapi: notify up contr %d\n", contr);
+	for (p = capi_users; p; p = p->next) {
+		if (!p->callback) continue;
+		(*p->callback) (KCI_CONTRUP, contr, &CARD(contr)->profile);
+	}
+}
+
+static void notify_down(__u16 contr)
+{
+	struct capi_interface_user *p;
+        printk(KERN_NOTICE "kcapi: notify down contr %d\n", contr);
+	for (p = capi_users; p; p = p->next) {
+		if (!p->callback) continue;
+		(*p->callback) (KCI_CONTRDOWN, contr, 0);
+	}
+}
+
+static void notify_handler(void *dummy)
+{
+	__u16 contr;
+
+	for (contr=1; VALID_CARD(contr); contr++)
+		 if (test_and_clear_bit(contr, &notify_up_set))
+			 notify_up(contr);
+	for (contr=1; VALID_CARD(contr); contr++)
+		 if (test_and_clear_bit(contr, &notify_down_set))
+			 notify_down(contr);
+}
+
+
+static void controllercb_ready(struct capi_ctr * card)
+{
+	__u16 appl;
+
+	card->cardstate = CARD_RUNNING;
+
+	for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
+		if (!VALID_APPLID(appl)) continue;
+		if (APPL(appl)->releasing) continue;
+		card->driver->register_appl(card, appl, &APPL(appl)->rparam);
+	}
+
+        set_bit(CARDNR(card), &notify_up_set);
+        queue_task(&tq_state_notify, &tq_scheduler);
+
+        printk(KERN_NOTICE "kcapi: card %d \"%s\" ready.\n",
+		CARDNR(card), card->name);
+}
+
+static void controllercb_reseted(struct capi_ctr * card)
+{
+	__u16 appl;
+
+        if (card->cardstate == CARD_FREE)
+		return;
+        if (card->cardstate == CARD_DETECTED)
+		return;
+
+        card->cardstate = CARD_DETECTED;
+
+	memset(card->manu, 0, sizeof(card->manu));
+	memset(&card->version, 0, sizeof(card->version));
+	memset(&card->profile, 0, sizeof(card->profile));
+	memset(card->serial, 0, sizeof(card->serial));
+
+	for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
+		struct capi_ncci **pp, **nextpp;
+		for (pp = &APPL(appl)->nccilist; *pp; pp = nextpp) {
+			if (NCCI2CTRL((*pp)->ncci) == card->cnr) {
+				struct capi_ncci *np = *pp;
+				*pp = np->next;
+				printk(KERN_INFO "kcapi: appl %d ncci 0x%x forced down!\n", appl, np->ncci);
+				kfree(np);
+				nextpp = pp;
+			} else {
+				nextpp = &(*pp)->next;
+			}
+		}
+	}
+	set_bit(CARDNR(card), &notify_down_set);
+	queue_task(&tq_state_notify, &tq_scheduler);
+	printk(KERN_NOTICE "kcapi: card %d down.\n", CARDNR(card));
+}
+
+static void controllercb_suspend_output(struct capi_ctr *card)
+{
+	if (!card->blocked) {
+		printk(KERN_DEBUG "kcapi: card %d suspend\n", CARDNR(card));
+		card->blocked = 1;
+	}
+}
+
+static void controllercb_resume_output(struct capi_ctr *card)
+{
+	if (card->blocked) {
+		printk(KERN_DEBUG "kcapi: card %d resume\n", CARDNR(card));
+		card->blocked = 0;
+	}
+}
+
+/* ------------------------------------------------------------- */
+
+
+struct capi_ctr *
+drivercb_attach_ctr(struct capi_driver *driver, char *name, void *driverdata)
+{
+	struct capi_ctr *card, **pp;
+	int i;
+
+	for (i=0; i < CAPI_MAXCONTR && cards[i].cardstate != CARD_FREE; i++) ;
+   
+	if (i == CAPI_MAXCONTR) {
+		printk(KERN_ERR "kcapi: out of controller slots\n");
+	   	return 0;
+	}
+	card = &cards[i];
+	memset(card, 0, sizeof(struct capi_ctr));
+	card->driver = driver;
+	card->cnr = CARDNR(card);
+	strncpy(card->name, name, sizeof(card->name));
+	card->cardstate = CARD_DETECTED;
+	card->blocked = 0;
+	card->driverdata = driverdata;
+	card->traceflag = showcapimsgs;
+
+        card->ready = controllercb_ready; 
+        card->reseted = controllercb_reseted; 
+        card->suspend_output = controllercb_suspend_output;
+        card->resume_output = controllercb_resume_output;
+        card->handle_capimsg = controllercb_handle_capimsg;
+	card->appl_registered = controllercb_appl_registered;
+	card->appl_released = controllercb_appl_released;
+        card->new_ncci = controllercb_new_ncci;
+        card->free_ncci = controllercb_free_ncci;
+
+	for (pp = &driver->controller; *pp; pp = &(*pp)->next) ;
+	card->next = 0;
+	*pp = card;
+	driver->ncontroller++;
+	sprintf(card->procfn, "capi/controllers/%d", card->cnr);
+	card->procent = create_proc_entry(card->procfn, 0, 0);
+	if (card->procent) {
+	   card->procent->read_proc = 
+		(int (*)(char *,char **,off_t,int,int *,void *))
+			driver->ctr_read_proc;
+	   card->procent->data = card;
+	}
+
+	ncards++;
+	printk(KERN_NOTICE "kcapi: Controller %d: %s attached\n",
+			card->cnr, card->name);
+	return card;
+}
+
+static int drivercb_detach_ctr(struct capi_ctr *card)
+{
+	struct capi_driver *driver = card->driver;
+	struct capi_ctr **pp;
+
+        if (card->cardstate == CARD_FREE)
+		return 0;
+        if (card->cardstate != CARD_DETECTED)
+		controllercb_reseted(card);
+	for (pp = &driver->controller; *pp ; pp = &(*pp)->next) {
+        	if (*pp == card) {
+	        	*pp = card->next;
+			driver->ncontroller--;
+			ncards--;
+	        	break;
+		}
+	}
+	if (card->procent) {
+	   remove_proc_entry(card->procfn, 0);
+	   card->procent = 0;
+	}
+	card->cardstate = CARD_FREE;
+	printk(KERN_NOTICE "kcapi: Controller %d: %s unregistered\n",
+			card->cnr, card->name);
+	return 0;
+}
+
+/* ------------------------------------------------------------- */
+
+/* fallback if no driver read_proc function defined by driver */
+
+static int driver_read_proc(char *page, char **start, off_t off,
+        		int count, int *eof, void *data)
+{
+	struct capi_driver *driver = (struct capi_driver *)data;
+	int len = 0;
+
+	len += sprintf(page+len, "%-16s %s\n", "name", driver->name);
+	len += sprintf(page+len, "%-16s %s\n", "revision", driver->revision);
+
+	if (len < off) 
+           return 0;
+	*eof = 1;
+	*start = page - off;
+	return ((count < len-off) ? count : len-off);
+}
+
+/* ------------------------------------------------------------- */
+
+static struct capi_driver_interface di = {
+    drivercb_attach_ctr,
+    drivercb_detach_ctr,
+};
+
+struct capi_driver_interface *attach_capi_driver(struct capi_driver *driver)
+{
+	struct capi_driver **pp;
+
+	for (pp = &drivers; *pp; pp = &(*pp)->next) ;
+	driver->next = 0;
+	*pp = driver;
+	printk(KERN_NOTICE "kcapi: driver %s attached\n", driver->name);
+#ifdef CONFIG_AVMB1_COMPAT
+        if (strcmp(driver->name, "b1isa") == 0 && driver->add_card)
+		b1isa_driver = driver;
+        if (strcmp(driver->name, "t1isa") == 0 && driver->add_card)
+		t1isa_driver = driver;
+#endif
+	sprintf(driver->procfn, "capi/drivers/%s", driver->name);
+	driver->procent = create_proc_entry(driver->procfn, 0, 0);
+	if (driver->procent) {
+	   if (driver->driver_read_proc) {
+		   driver->procent->read_proc = 
+	       		(int (*)(char *,char **,off_t,int,int *,void *))
+					driver->driver_read_proc;
+	   } else {
+		   driver->procent->read_proc = driver_read_proc;
+	   }
+	   driver->procent->data = driver;
+	}
+	return &di;
+}
+
+void detach_capi_driver(struct capi_driver *driver)
+{
+	struct capi_driver **pp;
+	for (pp = &drivers; *pp && *pp != driver; pp = &(*pp)->next) ;
+	if (*pp) {
+		*pp = (*pp)->next;
+#ifdef CONFIG_AVMB1_COMPAT
+		if (driver == b1isa_driver) b1isa_driver = 0;
+		if (driver == t1isa_driver) t1isa_driver = 0;
+#endif
+		printk(KERN_NOTICE "kcapi: driver %s detached\n", driver->name);
+	} else {
+		printk(KERN_ERR "kcapi: driver %s double detach ?\n", driver->name);
+	}
+	if (driver->procent) {
+	   remove_proc_entry(driver->procfn, 0);
+	   driver->procent = 0;
+	}
+}
+
+/* ------------------------------------------------------------- */
+/* -------- CAPI2.0 Interface ---------------------------------- */
+/* ------------------------------------------------------------- */
+
+static int capi_installed(void)
+{
+	int i;
+	for (i = 0; i < CAPI_MAXCONTR; i++) {
+		if (cards[i].cardstate == CARD_RUNNING)
+			return 1;
+	}
+	return 0;
+}
+
+static __u16 capi_register(capi_register_params * rparam, __u16 * applidp)
+{
+	int appl;
+	int i;
+
+	if (rparam->datablklen < 128)
+		return CAPI_LOGBLKSIZETOSMALL;
+
+	for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
+		if (APPL_IS_FREE(appl))
+			break;
+	}
+	if (appl > CAPI_MAXAPPL)
+		return CAPI_TOOMANYAPPLS;
+
+	APPL_MARK_USED(appl);
+	skb_queue_head_init(&APPL(appl)->recv_queue);
+	APPL(appl)->nncci = 0;
+
+	memcpy(&APPL(appl)->rparam, rparam, sizeof(capi_register_params));
+
+	for (i = 0; i < CAPI_MAXCONTR; i++) {
+		if (cards[i].cardstate != CARD_RUNNING)
+			continue;
+		cards[i].driver->register_appl(&cards[i], appl,
+						&APPL(appl)->rparam);
+	}
+	*applidp = appl;
+	printk(KERN_INFO "kcapi: appl %d up\n", appl);
+
+	return CAPI_NOERROR;
+}
+
+static __u16 capi_release(__u16 applid)
+{
+	struct sk_buff *skb;
+	int i;
+
+	if (!VALID_APPLID(applid) || APPL(applid)->releasing)
+		return CAPI_ILLAPPNR;
+	while ((skb = skb_dequeue(&APPL(applid)->recv_queue)) != 0)
+		kfree_skb(skb);
+	for (i = 0; i < CAPI_MAXCONTR; i++) {
+		if (cards[i].cardstate != CARD_RUNNING)
+			continue;
+		APPL(applid)->releasing++;
+		cards[i].driver->release_appl(&cards[i], applid);
+	}
+	if (APPL(applid)->releasing <= 0) {
+	        APPL(applid)->signal = 0;
+		APPL_MARK_FREE(applid);
+		printk(KERN_INFO "kcapi: appl %d down\n", applid);
+	}
+	return CAPI_NOERROR;
+}
+
+static __u16 capi_put_message(__u16 applid, struct sk_buff *skb)
+{
+	struct capi_ncci *np;
+	int contr;
+	int showctl = 0;
+	__u8 cmd, subcmd;
+
+	if (ncards == 0)
+		return CAPI_REGNOTINSTALLED;
+	if (!VALID_APPLID(applid))
+		return CAPI_ILLAPPNR;
+	if (skb->len < 12
+	    || !capi_cmd_valid(CAPIMSG_COMMAND(skb->data))
+	    || !capi_subcmd_valid(CAPIMSG_SUBCOMMAND(skb->data)))
+		return CAPI_ILLCMDORSUBCMDORMSGTOSMALL;
+	contr = CAPIMSG_CONTROLLER(skb->data);
+	if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) {
+		contr = 1;
+	        if (CARD(contr)->cardstate != CARD_RUNNING) 
+			return CAPI_REGNOTINSTALLED;
+	}
+	if (CARD(contr)->blocked)
+		return CAPI_SENDQUEUEFULL;
+
+	cmd = CAPIMSG_COMMAND(skb->data);
+        subcmd = CAPIMSG_SUBCOMMAND(skb->data);
+
+	if (cmd == CAPI_DATA_B3 && subcmd== CAPI_REQ) {
+	    	if ((np = find_ncci(APPL(applid), CAPIMSG_NCCI(skb->data))) != 0
+	            && mq_enqueue(np, CAPIMSG_MSGID(skb->data)) == 0)
+			return CAPI_SENDQUEUEFULL;
+		CARD(contr)->nsentdatapkt++;
+		APPL(applid)->nsentdatapkt++;
+	        if (CARD(contr)->traceflag > 2) showctl |= 2;
+	} else {
+		CARD(contr)->nsentctlpkt++;
+		APPL(applid)->nsentctlpkt++;
+	        if (CARD(contr)->traceflag) showctl |= 2;
+	}
+	showctl |= (CARD(contr)->traceflag & 1);
+	if (showctl & 2) {
+		if (showctl & 1) {
+			printk(KERN_DEBUG "kcapi: put [0x%lx] id#%d %s len=%u\n",
+			       (unsigned long) contr,
+			       CAPIMSG_APPID(skb->data),
+			       capi_cmd2str(cmd, subcmd),
+			       CAPIMSG_LEN(skb->data));
+		} else {
+			printk(KERN_DEBUG "kcapi: put [0x%lx] %s\n",
+					(unsigned long) contr,
+					capi_message2str(skb->data));
+		}
+
+	}
+	CARD(contr)->driver->send_message(CARD(contr), skb);
+	return CAPI_NOERROR;
+}
+
+static __u16 capi_get_message(__u16 applid, struct sk_buff **msgp)
+{
+	struct sk_buff *skb;
+
+	if (!VALID_APPLID(applid))
+		return CAPI_ILLAPPNR;
+	if ((skb = skb_dequeue(&APPL(applid)->recv_queue)) == 0)
+		return CAPI_RECEIVEQUEUEEMPTY;
+	*msgp = skb;
+	return CAPI_NOERROR;
+}
+
+static __u16 capi_set_signal(__u16 applid,
+			     void (*signal) (__u16 applid, __u32 param),
+			     __u32 param)
+{
+	if (!VALID_APPLID(applid))
+		return CAPI_ILLAPPNR;
+	APPL(applid)->signal = signal;
+	APPL(applid)->param = param;
+	return CAPI_NOERROR;
+}
+
+static __u16 capi_get_manufacturer(__u16 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;
+
+	strncpy(buf, CARD(contr)->manu, CAPI_MANUFACTURER_LEN);
+	return CAPI_NOERROR;
+}
+
+static __u16 capi_get_version(__u16 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;
+
+	memcpy((void *) verp, &CARD(contr)->version, sizeof(capi_version));
+	return CAPI_NOERROR;
+}
+
+static __u16 capi_get_serial(__u16 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;
+
+	strncpy((void *) serial, CARD(contr)->serial, CAPI_SERIAL_LEN);
+	return CAPI_NOERROR;
+}
+
+static __u16 capi_get_profile(__u16 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;
+
+	memcpy((void *) profp, &CARD(contr)->profile,
+			sizeof(struct capi_profile));
+	return CAPI_NOERROR;
+}
+
+#ifdef CONFIG_AVMB1_COMPAT
+static int old_capi_manufacturer(unsigned int cmd, void *data)
+{
+	avmb1_loadandconfigdef ldef;
+	avmb1_extcarddef cdef;
+	avmb1_resetdef rdef;
+	avmb1_getdef gdef;
+	struct capi_driver *driver;
+	struct capi_ctr *card;
+	capicardparams cparams;
+	capiloaddata ldata;
+	int retval;
+
+	switch (cmd) {
+	case AVMB1_ADDCARD:
+	case AVMB1_ADDCARD_WITH_TYPE:
+		if (cmd == AVMB1_ADDCARD) {
+		   if ((retval = copy_from_user((void *) &cdef, data,
+					    sizeof(avmb1_carddef))))
+			   return retval;
+		   cdef.cardtype = AVM_CARDTYPE_B1;
+		} else {
+		   if ((retval = copy_from_user((void *) &cdef, data,
+					    sizeof(avmb1_extcarddef))))
+			   return retval;
+		}
+		cparams.port = cdef.port;
+		cparams.irq = cdef.irq;
+		cparams.cardnr = cdef.cardnr;
+
+                switch (cdef.cardtype) {
+			case AVM_CARDTYPE_B1: driver = b1isa_driver; break;
+			case AVM_CARDTYPE_T1: driver = t1isa_driver; break;
+			default: driver = 0;
+		}
+		if (!driver || !driver->add_card) {
+			return -EIO;
+		}
+
+		return driver->add_card(driver, &cparams);
+
+	case AVMB1_LOAD:
+	case AVMB1_LOAD_AND_CONFIG:
+
+		if (cmd == AVMB1_LOAD) {
+			if ((retval = copy_from_user((void *) &ldef, data,
+						sizeof(avmb1_loaddef))))
+				return retval;
+			ldef.t4config.len = 0;
+			ldef.t4config.data = 0;
+		} else {
+			if ((retval = copy_from_user((void *) &ldef, data,
+					    	sizeof(avmb1_loadandconfigdef))))
+				return retval;
+		}
+		if (!VALID_CARD(ldef.contr))
+			return -ESRCH;
+
+		card = CARD(ldef.contr);
+		if (card->cardstate == CARD_FREE)
+			return -ESRCH;
+
+		if (ldef.t4file.len <= 0) {
+			printk(KERN_DEBUG "kcapi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len);
+			return -EINVAL;
+		}
+		if (ldef.t4file.data == 0) {
+			printk(KERN_DEBUG "kcapi: load: invalid parameter: dataptr is 0\n");
+			return -EINVAL;
+		}
+
+		ldata.firmware.user = 1;
+		ldata.firmware.data = ldef.t4file.data;
+		ldata.firmware.len = ldef.t4file.len;
+		ldata.configuration.user = 1;
+		ldata.configuration.data = ldef.t4config.data;
+		ldata.configuration.len = ldef.t4config.len;
+
+		if (card->cardstate != CARD_DETECTED) {
+			printk(KERN_INFO "kcapi: load: contr=%d not in detect state\n", ldef.contr);
+			return -EBUSY;
+		}
+		card->cardstate = CARD_LOADING;
+
+		retval = card->driver->load_firmware(card, &ldata);
+
+		if (retval) {
+			card->cardstate = CARD_DETECTED;
+			return retval;
+		}
+
+		while (card->cardstate != CARD_RUNNING) {
+
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout(HZ/10);	/* 0.1 sec */
+
+			if (signal_pending(current))
+				return -EINTR;
+		}
+		return 0;
+
+	case AVMB1_RESETCARD:
+		if ((retval = copy_from_user((void *) &rdef, data,
+					 sizeof(avmb1_resetdef))))
+			return retval;
+		if (!VALID_CARD(rdef.contr))
+			return -ESRCH;
+		card = CARD(rdef.contr);
+
+		if (card->cardstate == CARD_FREE)
+			return -ESRCH;
+		if (card->cardstate == CARD_DETECTED)
+			return 0;
+
+		card->driver->reset_ctr(card);
+
+		while (card->cardstate > CARD_DETECTED) {
+
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout(HZ/10);	/* 0.1 sec */
+
+			if (signal_pending(current))
+				return -EINTR;
+		}
+		return 0;
+
+	case AVMB1_GET_CARDINFO:
+		if ((retval = copy_from_user((void *) &gdef, data,
+					 sizeof(avmb1_getdef))))
+			return retval;
+
+		if (!VALID_CARD(gdef.contr))
+			return -ESRCH;
+
+		card = CARD(gdef.contr);
+
+		if (card->cardstate == CARD_FREE)
+			return -ESRCH;
+
+		gdef.cardstate = card->cardstate;
+		if (card->driver == b1isa_driver)
+			gdef.cardtype = AVM_CARDTYPE_B1;
+		else if (card->driver == t1isa_driver)
+			gdef.cardtype = AVM_CARDTYPE_T1;
+		else gdef.cardtype = AVM_CARDTYPE_B1;
+
+		if ((retval = copy_to_user(data, (void *) &gdef,
+					 sizeof(avmb1_getdef))))
+			return retval;
+
+		return 0;
+
+	case AVMB1_REMOVECARD:
+		if ((retval = copy_from_user((void *) &rdef, data,
+					 sizeof(avmb1_resetdef))))
+			return retval;
+
+		if (!VALID_CARD(rdef.contr))
+			return -ESRCH;
+		card = CARD(rdef.contr);
+
+		if (card->cardstate == CARD_FREE)
+			return -ESRCH;
+
+		if (card->cardstate != CARD_DETECTED)
+			return -EBUSY;
+
+		card->driver->remove_ctr(card);
+
+		while (card->cardstate != CARD_FREE) {
+
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout(HZ/10);	/* 0.1 sec */
+
+			if (signal_pending(current))
+				return -EINTR;
+		}
+		return 0;
+	}
+	return -EINVAL;
+}
+#endif
+
+static int capi_manufacturer(unsigned int cmd, void *data)
+{
+        struct capi_ctr *card;
+	kcapi_flagdef fdef;
+	int retval;
+
+	switch (cmd) {
+#ifdef CONFIG_AVMB1_COMPAT
+	case AVMB1_ADDCARD:
+	case AVMB1_ADDCARD_WITH_TYPE:
+	case AVMB1_LOAD:
+	case AVMB1_LOAD_AND_CONFIG:
+	case AVMB1_RESETCARD:
+	case AVMB1_GET_CARDINFO:
+	case AVMB1_REMOVECARD:
+		return old_capi_manufacturer(cmd, data);
+#endif
+	case KCAPI_CMD_TRACE:
+		if ((retval = copy_from_user((void *) &fdef, data,
+					 sizeof(kcapi_flagdef))))
+			return retval;
+
+		if (!VALID_CARD(fdef.contr))
+			return -ESRCH;
+		card = CARD(fdef.contr);
+		if (card->cardstate == CARD_FREE)
+			return -ESRCH;
+		card->traceflag = fdef.flag;
+		printk(KERN_INFO "kcapi: contr %d set trace=%d\n",
+			card->cnr, card->traceflag);
+		return 0;
+	}
+	return -EINVAL;
+}
+
+struct capi_interface avmb1_interface =
+{
+	capi_installed,
+	capi_register,
+	capi_release,
+	capi_put_message,
+	capi_get_message,
+	capi_set_signal,
+	capi_get_manufacturer,
+	capi_get_version,
+	capi_get_serial,
+	capi_get_profile,
+	capi_manufacturer
+};
+
+/* ------------------------------------------------------------- */
+/* -------- Exported Functions --------------------------------- */
+/* ------------------------------------------------------------- */
+
+struct capi_interface *attach_capi_interface(struct capi_interface_user *userp)
+{
+	struct capi_interface_user *p;
+
+	for (p = capi_users; p; p = p->next) {
+		if (p == userp) {
+			printk(KERN_ERR "kcapi: double attach from %s\n",
+			       userp->name);
+			return 0;
+		}
+	}
+	userp->next = capi_users;
+	capi_users = userp;
+	MOD_INC_USE_COUNT;
+	printk(KERN_NOTICE "kcapi: %s attached\n", userp->name);
+
+	return &avmb1_interface;
+}
+
+int detach_capi_interface(struct capi_interface_user *userp)
+{
+	struct capi_interface_user **pp;
+
+	for (pp = &capi_users; *pp; pp = &(*pp)->next) {
+		if (*pp == userp) {
+			*pp = userp->next;
+			userp->next = 0;
+			MOD_DEC_USE_COUNT;
+			printk(KERN_NOTICE "kcapi: %s detached\n", userp->name);
+			return 0;
+		}
+	}
+	printk(KERN_ERR "kcapi: double detach from %s\n", userp->name);
+	return -1;
+}
+
+/* ------------------------------------------------------------- */
+/* -------- Init & Cleanup ------------------------------------- */
+/* ------------------------------------------------------------- */
+
+EXPORT_SYMBOL(attach_capi_interface);
+EXPORT_SYMBOL(detach_capi_interface);
+EXPORT_SYMBOL(attach_capi_driver);
+EXPORT_SYMBOL(detach_capi_driver);
+
+#ifndef MODULE
+#ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA
+extern int b1isa_init(void);
+#endif
+#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI
+extern int b1pci_init(void);
+#endif
+#ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA
+extern int t1isa_init(void);
+#endif
+#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
+extern int b1pcmcia_init(void);
+#endif
+#endif
+
+/*
+ * init / exit functions
+ */
+
+#ifdef MODULE
+#define kcapi_init init_module
+#endif
+
+int kcapi_init(void)
+{
+	char *p;
+	char rev[10];
+
+	skb_queue_head_init(&recv_queue);
+	/* init_bh(CAPI_BH, do_capi_bh); */
+
+	tq_state_notify.routine = notify_handler;
+	tq_state_notify.data = 0;
+
+	tq_recv_notify.routine = recv_handler;
+	tq_recv_notify.data = 0;
+
+        proc_capi_init();
+
+	if ((p = strchr(revision, ':'))) {
+		strcpy(rev, p + 1);
+		p = strchr(rev, '$');
+		*p = 0;
+	} else
+		strcpy(rev, "1.0");
+
+#ifdef MODULE
+        printk(KERN_NOTICE "CAPI-driver Rev%s: loaded\n", rev);
+#else
+	printk(KERN_NOTICE "CAPI-driver Rev%s: started\n", rev);
+#ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA
+	(void)b1isa_init();
+#endif
+#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI
+	(void)b1pci_init();
+#endif
+#ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA
+	(void)t1isa_init();
+#endif
+#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
+	(void)b1pcmcia_init();
+#endif
+#endif
+	return 0;
+}
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+	char rev[10];
+	char *p;
+
+	if ((p = strchr(revision, ':'))) {
+		strcpy(rev, p + 1);
+		p = strchr(rev, '$');
+		*p = 0;
+	} else {
+		strcpy(rev, "1.0");
+	}
+
+	schedule(); /* execute queued tasks .... */
+        proc_capi_exit();
+	printk(KERN_NOTICE "CAPI-driver Rev%s: unloaded\n", rev);
+}
+#endif
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/avmb1/t1isa.c linux/drivers/isdn/avmb1/t1isa.c
--- v2.3.13/linux/drivers/isdn/avmb1/t1isa.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/avmb1/t1isa.c	Sun Aug 15 11:49:08 1999
@@ -0,0 +1,544 @@
+/*
+ * $Id: t1isa.c,v 1.4 1999/07/09 15:05:50 keil Exp $
+ * 
+ * Module for AVM T1 HEMA-card.
+ * 
+ * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
+ * 
+ * $Log: t1isa.c,v $
+ * Revision 1.4  1999/07/09 15:05:50  keil
+ * compat.h is now isdn_compat.h
+ *
+ * Revision 1.3  1999/07/06 07:42:04  calle
+ * - changes in /proc interface
+ * - check and changed calls to [dev_]kfree_skb and [dev_]alloc_skb.
+ *
+ * Revision 1.2  1999/07/05 15:09:54  calle
+ * - renamed "appl_release" to "appl_released".
+ * - version und profile data now cleared on controller reset
+ * - extended /proc interface, to allow driver and controller specific
+ *   informations to include by driver hackers.
+ *
+ * Revision 1.1  1999/07/01 15:26:44  calle
+ * complete new version (I love it):
+ * + new hardware independed "capi_driver" interface that will make it easy to:
+ *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ *   - write a CAPI-2.0 for the passive cards
+ *   - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ *   make menuconfig, in the past all supported cards where included
+ *   at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ *   using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+ *
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/capi.h>
+#include <asm/io.h>
+#include <linux/isdn_compat.h>
+#include "capicmd.h"
+#include "capiutil.h"
+#include "capilli.h"
+#include "avmcard.h"
+
+static char *revision = "$Revision: 1.4 $";
+
+/* ------------------------------------------------------------- */
+
+MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
+
+/* ------------------------------------------------------------- */
+
+static struct capi_driver_interface *di;
+
+/* ------------------------------------------------------------- */
+
+static int hema_irq_table[16] =
+{0,
+ 0,
+ 0,
+ 0x80,				/* irq 3 */
+ 0,
+ 0x90,				/* irq 5 */
+ 0,
+ 0xA0,				/* irq 7 */
+ 0,
+ 0xB0,				/* irq 9 */
+ 0xC0,				/* irq 10 */
+ 0xD0,				/* irq 11 */
+ 0xE0,				/* irq 12 */
+ 0,
+ 0,
+ 0xF0,				/* irq 15 */
+};
+
+static int t1_detectandinit(unsigned int base, unsigned irq, int cardnr)
+{
+	unsigned char cregs[8];
+	unsigned char reverse_cardnr;
+	unsigned long flags;
+	unsigned char dummy;
+	int i;
+
+	reverse_cardnr =   ((cardnr & 0x01) << 3) | ((cardnr & 0x02) << 1)
+		         | ((cardnr & 0x04) >> 1) | ((cardnr & 0x08) >> 3);
+	cregs[0] = (HEMA_VERSION_ID << 4) | (reverse_cardnr & 0xf);
+	cregs[1] = 0x00; /* fast & slow link connected to CON1 */
+	cregs[2] = 0x05; /* fast link 20MBit, slow link 20 MBit */
+	cregs[3] = 0;
+	cregs[4] = 0x11; /* zero wait state */
+	cregs[5] = hema_irq_table[irq & 0xf];
+	cregs[6] = 0;
+	cregs[7] = 0;
+
+	save_flags(flags);
+	cli();
+	/* board reset */
+	t1outp(base, T1_RESETBOARD, 0xf);
+	udelay(100 * 1000);
+	dummy = t1inp(base, T1_FASTLINK+T1_OUTSTAT); /* first read */
+
+	/* write config */
+	dummy = (base >> 4) & 0xff;
+	for (i=1;i<=0xf;i++) t1outp(base, i, dummy);
+	t1outp(base, HEMA_PAL_ID & 0xf, dummy);
+	t1outp(base, HEMA_PAL_ID >> 4, cregs[0]);
+	for(i=1;i<7;i++) t1outp(base, 0, cregs[i]);
+	t1outp(base, ((base >> 4)) & 0x3, cregs[7]);
+	restore_flags(flags);
+
+	udelay(100 * 1000);
+	t1outp(base, T1_FASTLINK+T1_RESETLINK, 0);
+	t1outp(base, T1_SLOWLINK+T1_RESETLINK, 0);
+	udelay(10 * 1000);
+	t1outp(base, T1_FASTLINK+T1_RESETLINK, 1);
+	t1outp(base, T1_SLOWLINK+T1_RESETLINK, 1);
+	udelay(100 * 1000);
+	t1outp(base, T1_FASTLINK+T1_RESETLINK, 0);
+	t1outp(base, T1_SLOWLINK+T1_RESETLINK, 0);
+	udelay(10 * 1000);
+	t1outp(base, T1_FASTLINK+T1_ANALYSE, 0);
+	udelay(5 * 1000);
+	t1outp(base, T1_SLOWLINK+T1_ANALYSE, 0);
+
+	if (t1inp(base, T1_FASTLINK+T1_OUTSTAT) != 0x1) /* tx empty */
+		return 1;
+	if (t1inp(base, T1_FASTLINK+T1_INSTAT) != 0x0) /* rx empty */
+		return 2;
+	if (t1inp(base, T1_FASTLINK+T1_IRQENABLE) != 0x0)
+		return 3;
+	if ((t1inp(base, T1_FASTLINK+T1_FIFOSTAT) & 0xf0) != 0x70)
+		return 4;
+	if ((t1inp(base, T1_FASTLINK+T1_IRQMASTER) & 0x0e) != 0)
+		return 5;
+	if ((t1inp(base, T1_FASTLINK+T1_IDENT) & 0x7d) != 1)
+		return 6;
+	if (t1inp(base, T1_SLOWLINK+T1_OUTSTAT) != 0x1) /* tx empty */
+		return 7;
+	if ((t1inp(base, T1_SLOWLINK+T1_IRQMASTER) & 0x0e) != 0)
+		return 8;
+	if ((t1inp(base, T1_SLOWLINK+T1_IDENT) & 0x7d) != 0)
+		return 9;
+        return 0;
+}
+
+static void t1_handle_interrupt(avmcard * card)
+{
+	struct capi_ctr *ctrl = card->ctrl;
+	unsigned char b1cmd;
+	struct sk_buff *skb;
+
+	unsigned ApplId;
+	unsigned MsgLen;
+	unsigned DataB3Len;
+	unsigned NCCI;
+	unsigned WindowSize;
+
+	while (b1_rx_full(card->port)) {
+
+		b1cmd = b1_get_byte(card->port);
+
+		switch (b1cmd) {
+
+		case RECEIVE_DATA_B3_IND:
+
+			ApplId = (unsigned) b1_get_word(card->port);
+			MsgLen = t1_get_slice(card->port, card->msgbuf);
+			DataB3Len = t1_get_slice(card->port, card->databuf);
+
+			if (!(skb = alloc_skb(DataB3Len+MsgLen, GFP_ATOMIC))) {
+				printk(KERN_ERR "t1isa: incoming packet dropped\n");
+			} 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;
+
+		case RECEIVE_MESSAGE:
+
+			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");
+			} else {
+				memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
+				ctrl->handle_capimsg(ctrl, ApplId, skb);
+			}
+			break;
+
+		case RECEIVE_NEW_NCCI:
+
+			ApplId = b1_get_word(card->port);
+			NCCI = b1_get_word(card->port);
+			WindowSize = b1_get_word(card->port);
+
+			ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize);
+
+			break;
+
+		case RECEIVE_FREE_NCCI:
+
+			ApplId = b1_get_word(card->port);
+			NCCI = b1_get_word(card->port);
+
+			if (NCCI != 0xffffffff)
+				ctrl->free_ncci(ctrl, ApplId, NCCI);
+			else ctrl->appl_released(ctrl, ApplId);
+			break;
+
+		case RECEIVE_START:
+			b1_put_byte(card->port, SEND_POLLACK);
+			ctrl->resume_output(ctrl);
+			break;
+
+		case RECEIVE_STOP:
+			ctrl->suspend_output(ctrl);
+			break;
+
+		case RECEIVE_INIT:
+
+			card->versionlen = t1_get_slice(card->port, card->versionbuf);
+			b1_parse_version(card);
+			printk(KERN_INFO "%s: %s-card (%s) now active\n",
+			       card->name,
+			       card->version[VER_CARDTYPE],
+			       card->version[VER_DRIVER]);
+			ctrl->ready(ctrl);
+			break;
+
+		case RECEIVE_TASK_READY:
+			ApplId = (unsigned) b1_get_word(card->port);
+			MsgLen = t1_get_slice(card->port, 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 = t1_get_slice(card->port, 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;
+
+		case 0xff:
+			printk(KERN_ERR "%s: card reseted ?\n", card->name);
+			return;
+		default:
+			printk(KERN_ERR "%s: b1_interrupt: 0x%x ???\n",
+					card->name, b1cmd);
+			return;
+		}
+	}
+}
+
+/* ------------------------------------------------------------- */
+
+static void t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
+{
+	avmcard *card;
+
+	card = (avmcard *) devptr;
+
+	if (!card) {
+		printk(KERN_WARNING "t1_interrupt: wrong device\n");
+		return;
+	}
+	if (card->interrupt) {
+		printk(KERN_ERR "t1_interrupt: reentering interrupt hander (%s)\n", card->name);
+		return;
+	}
+
+	card->interrupt = 1;
+
+	t1_handle_interrupt(card);
+
+	card->interrupt = 0;
+}
+/* ------------------------------------------------------------- */
+
+static int t1isa_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	unsigned int port = card->port;
+	unsigned long flags;
+	int retval;
+
+	t1_disable_irq(port);
+	b1_reset(port);
+
+	if ((retval = b1_load_t4file(port, &data->firmware))) {
+		b1_reset(port);
+		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(port, &data->configuration))) {
+			b1_reset(port);
+			printk(KERN_ERR "%s: failed to load config!!\n",
+					card->name);
+			return retval;
+		}
+	}
+
+	if (!b1_loaded(port)) {
+		printk(KERN_ERR "%s: failed to load t4file.\n", card->name);
+		return -EIO;
+	}
+
+	save_flags(flags);
+	cli();
+	b1_setinterrupt(port, card->irq, card->cardtype);
+	b1_put_byte(port, SEND_INIT);
+	b1_put_word(port, AVM_NAPPS);
+	b1_put_word(port, AVM_NCCI_PER_CHANNEL*30);
+	b1_put_word(port, ctrl->cnr - 1);
+	restore_flags(flags);
+
+	return 0;
+}
+
+void t1isa_reset_ctr(struct capi_ctr *ctrl)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	unsigned int port = card->port;
+
+	t1_disable_irq(port);
+	b1_reset(port);
+	b1_reset(port);
+
+	memset(card->version, 0, sizeof(card->version));
+	ctrl->reseted(ctrl);
+}
+
+static void t1isa_remove_ctr(struct capi_ctr *ctrl)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	unsigned int port = card->port;
+
+	t1_disable_irq(port);
+	b1_reset(port);
+	b1_reset(port);
+	t1_reset(port);
+
+	di->detach_ctr(ctrl);
+	free_irq(card->irq, card);
+	release_region(card->port, AVMB1_PORTLEN);
+	kfree(card);
+
+	MOD_DEC_USE_COUNT;
+}
+
+/* ------------------------------------------------------------- */
+
+static int t1isa_add_card(struct capi_driver *driver, struct capicardparams *p)
+{
+	struct capi_ctr *ctrl;
+	avmcard *card;
+	int retval;
+
+	card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
+
+	if (!card) {
+		printk(KERN_WARNING "t1isa: no memory.\n");
+		return -ENOMEM;
+	}
+	memset(card, 0, sizeof(avmcard));
+	sprintf(card->name, "t1isa-%x", p->port);
+	card->port = p->port;
+	card->irq = p->irq;
+	card->cardtype = avm_t1isa;
+	card->cardnr = p->cardnr;
+
+	if (!(((card->port & 0x7) == 0) && ((card->port & 0x30) != 0x30))) {
+		printk(KERN_WARNING "t1isa: illegal port 0x%x.\n", card->port);
+		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);
+		kfree(card);
+		return -EBUSY;
+	}
+	if (hema_irq_table[card->irq & 0xf] == 0) {
+		printk(KERN_WARNING "t1isa: irq %d not valid.\n", card->irq);
+		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);
+			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);
+		kfree(card);
+		return -EIO;
+	}
+	t1_disable_irq(card->port);
+	b1_reset(card->port);
+
+	request_region(p->port, AVMB1_PORTLEN, card->name);
+
+	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);
+		release_region(card->port, AVMB1_PORTLEN);
+		kfree(card);
+		return -EBUSY;
+	}
+
+	card->ctrl = di->attach_ctr(driver, card->name, card);
+	if (!card->ctrl) {
+		printk(KERN_ERR "t1isa: attach controller failed.\n");
+		free_irq(card->irq, card);
+		release_region(card->port, AVMB1_PORTLEN);
+		kfree(card);
+		return -EBUSY;
+	}
+
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static void t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	unsigned int port = card->port;
+	unsigned long flags;
+	__u16 len = CAPIMSG_LEN(skb->data);
+	__u8 cmd = CAPIMSG_COMMAND(skb->data);
+	__u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data);
+
+	save_flags(flags);
+	cli();
+	if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
+		__u16 dlen = CAPIMSG_DATALEN(skb->data);
+		b1_put_byte(port, SEND_DATA_B3_REQ);
+		t1_put_slice(port, skb->data, len);
+		t1_put_slice(port, skb->data + len, dlen);
+	} else {
+		b1_put_byte(port, SEND_MESSAGE);
+		t1_put_slice(port, skb->data, len);
+	}
+	restore_flags(flags);
+	dev_kfree_skb(skb);
+}
+/* ------------------------------------------------------------- */
+
+static char *t1isa_procinfo(struct capi_ctr *ctrl)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	if (!card)
+		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
+		);
+	return card->infobuf;
+}
+
+
+/* ------------------------------------------------------------- */
+
+static struct capi_driver t1isa_driver = {
+    "t1isa",
+    "0.0",
+    t1isa_load_firmware,
+    t1isa_reset_ctr,
+    t1isa_remove_ctr,
+    b1_register_appl,
+    b1_release_appl,
+    t1isa_send_message,
+
+    t1isa_procinfo,
+    b1ctl_read_proc,
+    0,	/* use standard driver_read_proc */
+
+    t1isa_add_card,
+};
+
+#ifdef MODULE
+#define t1isa_init init_module
+void cleanup_module(void);
+#endif
+
+int t1isa_init(void)
+{
+	struct capi_driver *driver = &t1isa_driver;
+	char *p;
+
+	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;
+	}
+	return 0;
+}
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+    detach_capi_driver(&t1isa_driver);
+}
+#endif
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/divert/Makefile linux/drivers/isdn/divert/Makefile
--- v2.3.13/linux/drivers/isdn/divert/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/divert/Makefile	Thu Aug 12 09:42:33 1999
@@ -0,0 +1,21 @@
+L_OBJS :=
+LX_OBJS :=
+M_OBJS :=
+MX_OBJS :=
+O_OBJS :=
+OX_OBJS :=
+L_TARGET :=
+O_TARGET :=
+
+O_OBJS += isdn_divert.o divert_procfs.o
+O_TARGET := dss1_divert.o
+M_OBJS += dss1_divert.o
+OX_OBJS += divert_init.o
+
+include $(TOPDIR)/Rules.make
+
+
+
+
+
+
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/divert/divert_init.c linux/drivers/isdn/divert/divert_init.c
--- v2.3.13/linux/drivers/isdn/divert/divert_init.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/divert/divert_init.c	Sun Aug 15 11:49:08 1999
@@ -0,0 +1,104 @@
+/* 
+ * $Id: divert_init.c,v 1.3 1999/07/05 20:21:39 werner Exp $
+ *
+ * Module init for DSS1 diversion services for i4l.
+ *
+ * Copyright 1999       by Werner Cornelius (werner@isdn4linux.de)
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ * $Log: divert_init.c,v $
+ * Revision 1.3  1999/07/05 20:21:39  werner
+ * changes to use diversion sources for all kernel versions.
+ * removed static device, only proc filesystem used
+ *
+ * Revision 1.2  1999/07/04 21:37:30  werner
+ * Ported from kernel version 2.0
+ *
+ *
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include "isdn_divert.h"
+
+/********************/
+/* needed externals */
+/********************/
+extern int printk(const char *fmt,...);
+
+/****************************************/
+/* structure containing interface to hl */
+/****************************************/
+isdn_divert_if divert_if =
+  { DIVERT_IF_MAGIC,  /* magic value */
+    DIVERT_CMD_REG,   /* register cmd */
+    ll_callback,      /* callback routine from ll */
+    NULL,             /* command still not specified */
+    NULL,             /* drv_to_name */
+    NULL,             /* name_to_drv */
+  };
+
+/*************************/
+/* Module interface code */
+/* no cmd line parms     */
+/*************************/
+int init_module(void)
+{ int i;
+
+  if (divert_dev_init())
+   { printk(KERN_WARNING "dss1_divert: cannot install device, not loaded\n");
+     return(-EIO);
+   }
+  if ((i = DIVERT_REG_NAME(&divert_if)) != DIVERT_NO_ERR)
+   { divert_dev_deinit();
+     printk(KERN_WARNING "dss1_divert: error %d registering module, not loaded\n",i);
+     return(-EIO);
+   } 
+#if (LINUX_VERSION_CODE < 0x020111)
+  register_symtab(0);
+#endif
+  printk(KERN_INFO "dss1_divert module successfully installed\n");
+  return(0);
+} /* init_module */
+
+/**********************/
+/* Module deinit code */
+/**********************/
+void cleanup_module(void)
+{ int flags;
+  int i;
+
+  save_flags(flags);
+  cli();
+  divert_if.cmd = DIVERT_CMD_REL; /* release */
+  if ((i = DIVERT_REG_NAME(&divert_if)) != DIVERT_NO_ERR)
+   { printk(KERN_WARNING "dss1_divert: error %d releasing module\n",i);
+     restore_flags(flags);
+     return;
+   } 
+  if (divert_dev_deinit()) 
+   { printk(KERN_WARNING "dss1_divert: device busy, remove cancelled\n");
+     restore_flags(flags);
+     return;
+   }
+  restore_flags(flags);
+  deleterule(-1); /* delete all rules and free mem */
+  deleteprocs();
+  printk(KERN_INFO "dss1_divert module successfully removed \n");
+} /* cleanup_module */
+
+
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/divert/divert_procfs.c linux/drivers/isdn/divert/divert_procfs.c
--- v2.3.13/linux/drivers/isdn/divert/divert_procfs.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/divert/divert_procfs.c	Thu Aug 12 09:42:33 1999
@@ -0,0 +1,456 @@
+/* 
+ * $Id: divert_procfs.c,v 1.4 1999/08/06 07:42:48 calle Exp $
+ *
+ * Filesystem handling for the diversion supplementary services.
+ *
+ * Copyright 1998       by Werner Cornelius (werner@isdn4linux.de)
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ * $Log: divert_procfs.c,v $
+ * Revision 1.4  1999/08/06 07:42:48  calle
+ * Added COMPAT_HAS_NEW_WAITQ for rd_queue for newer kernels.
+ *
+ * Revision 1.3  1999/07/05 20:21:41  werner
+ * changes to use diversion sources for all kernel versions.
+ * removed static device, only proc filesystem used
+ *
+ * Revision 1.2  1999/07/04 21:37:31  werner
+ * Ported from kernel version 2.0
+ *
+ *
+ *
+ */
+
+#include <linux/config.h>
+#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"
+
+/*********************************/
+/* Variables for interface queue */
+/*********************************/
+ulong if_used = 0; /* number of interface users */
+static struct divert_info *divert_info_head = NULL; /* head of queue */
+static struct divert_info *divert_info_tail = NULL; /* pointer to last entry */
+#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 */
+/*********************************/
+void put_info_buffer(char *cp)
+{ struct divert_info *ib;
+  int flags; 
+  
+  if (if_used <= 0) return;
+  if (!cp) return;
+  if (!*cp) return; 
+  if (!(ib = (struct divert_info *) kmalloc(sizeof(struct divert_info)+strlen(cp), GFP_ATOMIC))) return; /* no memory */
+  strcpy(ib->info_start,cp); /* set output string */
+  ib->next = NULL;
+  save_flags(flags);
+  cli();
+  ib->usage_cnt = if_used; 
+  if (!divert_info_head) 
+    divert_info_head = ib; /* new head */
+  else
+    divert_info_tail->next = ib; /* follows existing messages */
+  divert_info_tail = ib; /* new tail */   
+  restore_flags(flags);
+
+  /* delete old entrys */
+  while (divert_info_head->next)
+   { if ((divert_info_head->usage_cnt <= 0) &&
+         (divert_info_head->next->usage_cnt <= 0))
+       { ib = divert_info_head;
+         divert_info_head = divert_info_head->next;
+         kfree(ib);
+       }
+     else break;
+   } /* divert_info_head->next */  
+  wake_up_interruptible(&(rd_queue));
+} /* put_info_buffer */
+
+/**********************************/
+/* deflection device read routine */
+/**********************************/
+#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;
+	
+  if (!*((struct divert_info **)file->private_data))
+    { if (file->f_flags & O_NONBLOCK)
+	return -EAGAIN;
+      interruptible_sleep_on(&(rd_queue));
+    }
+  if (!(inf = *((struct divert_info **)file->private_data))) return(0);
+  
+  inf->usage_cnt--; /* new usage count */
+  (struct divert_info **)file->private_data = &inf->next; /* next structure */
+  if ((len = strlen(inf->info_start)) <= count) 
+    { if (copy_to_user(buf, inf->info_start, len))
+	return -EFAULT;
+      file->f_pos += len;
+      return(len);
+    }
+  return(0);
+} /* isdn_divert_read */
+
+/**********************************/
+/* deflection device write routine */
+/**********************************/
+#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 */
+
+
+/***************************************/
+/* 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;
+
+  poll_wait(file, &(rd_queue), wait);
+  /* mask = POLLOUT | POLLWRNORM; */
+  if (*((struct divert_info **)file->private_data)) 
+    { mask |= POLLIN | POLLRDNORM;
+    }
+  return mask;
+} /* isdn_divert_poll */
+#endif
+
+/****************/
+/* Open routine */
+/****************/
+static int isdn_divert_open(struct inode *ino, struct file *filep)
+{ int flags;
+
+  MOD_INC_USE_COUNT;
+  save_flags(flags);
+  cli();
+  if_used++;
+  if (divert_info_head)
+    (struct divert_info **)filep->private_data = &(divert_info_tail->next);
+   else
+    (struct divert_info **)filep->private_data = &divert_info_head; 
+  restore_flags(flags);
+  /*  start_divert(); */
+  return(0);
+} /* isdn_divert_open */
+
+/*******************/
+/* 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;
+
+  save_flags(flags);
+  cli();
+  if_used--;
+  inf = *((struct divert_info **)filep->private_data);
+  while (inf)
+   { inf->usage_cnt--;
+     inf = inf->next;
+   } 
+  restore_flags(flags);
+  if (if_used <= 0)
+   while (divert_info_head)
+    { inf = divert_info_head;
+      divert_info_head = divert_info_head->next;
+      kfree(inf);
+    }
+  MOD_DEC_USE_COUNT;
+#if (LINUX_VERSION_CODE < 0x020117)
+#else
+  return(0);
+#endif
+} /* isdn_divert_close */
+
+/*********/
+/* IOCTL */
+/*********/
+static int isdn_divert_ioctl(struct inode *inode, struct file *file, 
+                             uint cmd, ulong arg)
+{ divert_ioctl dioctl;
+  int i, flags;
+  divert_rule *rulep;
+  char *cp;
+
+  if ((i = copy_from_user(&dioctl,(char *) arg, sizeof(dioctl))))
+    return(i); 
+ 
+  switch (cmd)
+   { 
+     case IIOCGETVER:
+       dioctl.drv_version = DIVERT_IIOC_VERSION ; /* set version */
+       break;
+
+     case IIOCGETDRV:
+       if ((dioctl.getid.drvid = divert_if.name_to_drv(dioctl.getid.drvnam)) < 0)
+         return(-EINVAL);  
+       break;
+
+     case IIOCGETNAM:
+       cp = divert_if.drv_to_name(dioctl.getid.drvid);
+       if (!cp) return(-EINVAL);
+       if (!*cp) return(-EINVAL);
+       strcpy(dioctl.getid.drvnam,cp);  
+       break;
+
+     case IIOCGETRULE:
+       if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx)))
+         return(-EINVAL);  
+       dioctl.getsetrule.rule = *rulep; /* copy data */
+       break;
+
+     case IIOCMODRULE:
+       if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx)))
+         return(-EINVAL);  
+       save_flags(flags);
+       cli();
+       *rulep = dioctl.getsetrule.rule; /* copy data */
+       restore_flags(flags);
+       return(0); /* no copy required */
+       break;
+
+     case IIOCINSRULE:
+       return(insertrule(dioctl.getsetrule.ruleidx,&dioctl.getsetrule.rule));
+       break;
+
+     case IIOCDELRULE:
+       return(deleterule(dioctl.getsetrule.ruleidx));
+       break;
+
+     case IIOCDODFACT:
+       return(deflect_extern_action(dioctl.fwd_ctrl.subcmd,
+                                    dioctl.fwd_ctrl.callid,
+                                    dioctl.fwd_ctrl.to_nr)); 
+
+     case  IIOCDOCFACT:
+     case  IIOCDOCFDIS:
+     case  IIOCDOCFINT:
+       if (!divert_if.drv_to_name(dioctl.cf_ctrl.drvid)) 
+         return(-EINVAL); /* invalid driver */
+       if ((i = cf_command(dioctl.cf_ctrl.drvid,
+                          (cmd == IIOCDOCFACT) ? 1: (cmd == IIOCDOCFDIS) ? 0:2,
+                          dioctl.cf_ctrl.cfproc,
+                          dioctl.cf_ctrl.msn,  
+                          dioctl.cf_ctrl.service,
+                          dioctl.cf_ctrl.fwd_nr,
+                          &dioctl.cf_ctrl.procid)))
+         return(i);    
+       break;
+   
+     default: 
+       return(-EINVAL);
+   } /* switch cmd */
+  return(copy_to_user((char *) arg, &dioctl, sizeof(dioctl))); /* success */
+} /* isdn_divert_ioctl */
+
+
+#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,
+	isdn_divert_read,
+	isdn_divert_write,
+	NULL,                          /* isdn_readdir */
+	isdn_divert_poll,              /* isdn_poll */
+	isdn_divert_ioctl,             /* isdn_ioctl */
+	NULL,                          /* isdn_mmap */
+	isdn_divert_open,
+	NULL,                          /* flush */ 
+	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 */
+};
+
+/****************************/
+/* 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;
+
+#endif CONFIG_PROC_FS
+
+/***************************************************************************/
+/* divert_dev_init must be called before the proc filesystem may be used   */
+/***************************************************************************/
+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
+#endif CONFIG_PROC_FS
+
+  return(0);
+} /* divert_dev_init */
+
+/***************************************************************************/
+/* divert_dev_deinit must be called before leaving isdn when included as   */
+/* a module.                                                               */
+/***************************************************************************/
+int divert_dev_deinit(void)
+{ int i;
+
+#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 */
+#endif CONFIG_PROC_FS
+
+  return(0);
+} /* divert_dev_deinit */
+
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/divert/isdn_divert.c linux/drivers/isdn/divert/isdn_divert.c
--- v2.3.13/linux/drivers/isdn/divert/isdn_divert.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/divert/isdn_divert.c	Sun Aug 15 11:49:08 1999
@@ -0,0 +1,901 @@
+/* 
+ * $Id: isdn_divert.c,v 1.2 1999/07/04 21:37:32 werner Exp $
+ *
+ * DSS1 main diversion supplementary handling for i4l.
+ *
+ * Copyright 1999       by Werner Cornelius (werner@isdn4linux.de)
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ * $Log: isdn_divert.c,v $
+ * Revision 1.2  1999/07/04 21:37:32  werner
+ * Ported from kernel version 2.0
+ *
+ *
+ *
+ */
+
+
+
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/proc_fs.h>
+#include "isdn_divert.h"
+
+/**********************************/
+/* structure keeping calling info */
+/**********************************/
+struct call_struc
+  { isdn_ctrl ics; /* delivered setup + driver parameters */
+    ulong divert_id; /* Id delivered to user */
+    unsigned char akt_state; /* actual state */
+    char deflect_dest[35]; /* deflection destination */   
+    struct timer_list timer; /* timer control structure */
+    char info[90]; /* device info output */ 
+    struct call_struc *next; /* pointer to next entry */
+    struct call_struc *prev;
+  };
+
+
+/********************************************/
+/* structure keeping deflection table entry */
+/********************************************/
+struct deflect_struc
+  { struct deflect_struc *next,*prev; 
+    divert_rule rule; /* used rule */
+  };
+
+
+/*****************************************/
+/* variables for main diversion services */
+/*****************************************/
+/* diversion/deflection processes */
+static struct call_struc *divert_head = NULL; /* head of remembered entrys */
+static ulong next_id = 1; /* next info id */   
+static struct deflect_struc *table_head = NULL;
+static struct deflect_struc *table_tail = NULL; 
+static unsigned char extern_wait_max = 4; /* maximum wait in s for external process */ 
+
+/***************************/
+/* timer callback function */
+/***************************/
+static void deflect_timer_expire(ulong arg)
+{ int flags;
+  struct call_struc *cs = (struct call_struc *) arg;
+
+  save_flags(flags);
+  cli();
+  del_timer(&cs->timer); /* delete active timer */
+  restore_flags(flags);
+
+  switch(cs->akt_state)
+   { case DEFLECT_PROCEED:
+       cs->ics.command = ISDN_CMD_HANGUP; /* cancel action */
+       divert_if.ll_cmd(&cs->ics);                   	  
+       save_flags(flags);
+       cli();
+       cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
+       cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
+       add_timer(&cs->timer);
+       restore_flags(flags); 
+       break;
+
+     case DEFLECT_ALERT:
+       cs->ics.command = ISDN_CMD_REDIR; /* protocol */
+       strcpy(cs->ics.parm.setup.phone,cs->deflect_dest);
+       strcpy(cs->ics.parm.setup.eazmsn,"Testtext delayed");
+       divert_if.ll_cmd(&cs->ics);                   	  
+       save_flags(flags);
+       cli();
+       cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
+       cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
+       add_timer(&cs->timer);
+       restore_flags(flags); 
+       break;
+
+     case DEFLECT_AUTODEL:
+     default:
+       save_flags(flags);
+       cli();
+       if (cs->prev) 
+         cs->prev->next = cs->next; /* forward link */
+        else
+         divert_head = cs->next;
+       if (cs->next)
+         cs->next->prev = cs->prev; /* back link */           
+       restore_flags(flags); 
+       kfree(cs);
+       return;
+
+   } /* switch */
+} /* deflect_timer_func */
+
+
+/*****************************************/
+/* handle call forwarding de/activations */
+/* 0 = deact, 1 = act, 2 = interrogate   */
+/*****************************************/
+int cf_command(int drvid, int mode, 
+               u_char proc, char *msn, 
+               u_char service, char *fwd_nr, ulong *procid)
+{ int retval,msnlen,flags;
+  int fwd_len;
+  char *p,*ielenp,tmp[60];
+  struct call_struc *cs;
+
+  if (strchr(msn,'.')) return(-EINVAL); /* subaddress not allowed in msn */
+  if ((proc & 0x7F) > 2) return(-EINVAL);
+  proc &= 3;
+  p = tmp;
+  *p++ = 0x30; /* enumeration */
+  ielenp = p++; /* remember total length position */
+  *p++ = 0xa; /* proc tag */
+  *p++ = 1;   /* length */
+  *p++ = proc & 0x7F; /* procedure to de/activate/interrogate */
+  *p++ = 0xa; /* service tag */
+  *p++ = 1;   /* length */
+  *p++ = service; /* service to handle */
+
+  if (mode == 1) 
+   { if (!*fwd_nr) return(-EINVAL); /* destination missing */
+     if (strchr(fwd_nr,'.')) return(-EINVAL); /* subaddress not allowed */
+     fwd_len = strlen(fwd_nr);
+     *p++ = 0x30; /* number enumeration */
+     *p++ = fwd_len + 2; /* complete forward to len */ 
+     *p++ = 0x80; /* fwd to nr */
+     *p++ = fwd_len; /* length of number */
+     strcpy(p,fwd_nr); /* copy number */
+     p += fwd_len; /* pointer beyond fwd */
+   } /* activate */
+
+  msnlen = strlen(msn);
+  *p++ = 0x80; /* msn number */
+  if (msnlen > 1)
+   { *p++ = msnlen; /* length */
+     strcpy(p,msn);
+     p += msnlen;
+   }
+  else *p++ = 0;
+
+  *ielenp = p - ielenp - 1; /* set total IE length */ 
+
+  /* allocate mem for information struct */  
+  if (!(cs = (struct call_struc *) kmalloc(sizeof(struct call_struc), GFP_ATOMIC))) 
+             return(-ENOMEM); /* no memory */
+  init_timer(&cs->timer);
+  cs->info[0] = '\0';
+  cs->timer.function = deflect_timer_expire;
+  cs->timer.data = (ulong) cs; /* pointer to own structure */
+  cs->ics.driver = drvid;
+  cs->ics.command = ISDN_CMD_PROT_IO; /* protocol specific io */
+  cs->ics.arg = DSS1_CMD_INVOKE; /* invoke supplementary service */
+  cs->ics.parm.dss1_io.proc = (mode == 1) ? 7: (mode == 2) ? 11:8; /* operation */ 
+  cs->ics.parm.dss1_io.timeout = 4000; /* from ETS 300 207-1 */
+  cs->ics.parm.dss1_io.datalen = p - tmp; /* total len */
+  cs->ics.parm.dss1_io.data = tmp; /* start of buffer */
+  
+  save_flags(flags);
+  cli();
+  cs->ics.parm.dss1_io.ll_id = next_id++; /* id for callback */
+  restore_flags(flags);
+  *procid = cs->ics.parm.dss1_io.ll_id;  
+
+  sprintf(cs->info,"%d 0x%lx %s%s 0 %s %0x %d%s%s\n",
+	  (!mode ) ? DIVERT_DEACTIVATE : (mode == 1) ? DIVERT_ACTIVATE : DIVERT_REPORT,
+          cs->ics.parm.dss1_io.ll_id,
+          (mode != 2) ? "" : "0 ",
+          divert_if.drv_to_name(cs->ics.driver),
+          msn,
+          service & 0xFF,
+          proc,
+          (mode != 1) ? "" : " 0 ",
+          (mode != 1) ? "" : fwd_nr);
+ 
+  retval = divert_if.ll_cmd(&cs->ics); /* excute command */
+
+  if (!retval)
+   { cs->prev = NULL;
+     save_flags(flags);
+     cli();
+     cs->next = divert_head;
+     divert_head = cs; 
+     restore_flags(flags);
+   }
+  else
+   kfree(cs);
+  return(retval); 
+} /* cf_command */
+
+
+/****************************************/
+/* handle a external deflection command */
+/****************************************/
+int deflect_extern_action(u_char cmd, ulong callid, char *to_nr)
+{ struct call_struc *cs;
+  isdn_ctrl ic;
+  int flags;
+  int i;
+
+  if ((cmd & 0x7F) > 2) return(-EINVAL); /* invalid command */
+  cs = divert_head; /* start of parameter list */
+  while (cs)
+   { if (cs->divert_id == callid) break; /* found */
+     cs = cs->next;  
+   } /* search entry */
+  if (!cs) return(-EINVAL); /* invalid callid */
+
+  ic.driver = cs->ics.driver;
+  ic.arg = cs->ics.arg;
+  i = -EINVAL;
+  if (cs->akt_state == DEFLECT_AUTODEL) return(i); /* no valid call */
+  switch (cmd & 0x7F)
+   { case 0: /* hangup */
+       del_timer(&cs->timer); 
+       ic.command = ISDN_CMD_HANGUP;
+       i = divert_if.ll_cmd(&ic);                   	  
+       save_flags(flags);
+       cli();
+       cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
+       cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
+       add_timer(&cs->timer);
+       restore_flags(flags); 
+     break;      
+
+     case 1: /* alert */
+       if (cs->akt_state == DEFLECT_ALERT) return(0);
+       cmd &= 0x7F; /* never wait */
+       del_timer(&cs->timer); 
+       ic.command = ISDN_CMD_ALERT;
+       if ((i = divert_if.ll_cmd(&ic)))
+	{ save_flags(flags);
+          cli();
+          cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
+          cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
+          add_timer(&cs->timer);
+          restore_flags(flags);
+        }
+       else
+          cs->akt_state = DEFLECT_ALERT; 
+     break;      
+
+     case 2: /* redir */
+       del_timer(&cs->timer); 
+       strcpy(cs->ics.parm.setup.phone, to_nr);
+       strcpy(cs->ics.parm.setup.eazmsn, "Testtext manual");
+       ic.command = ISDN_CMD_REDIR;
+       if ((i = divert_if.ll_cmd(&ic)))
+	{ save_flags(flags);
+          cli();
+          cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
+          cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
+          add_timer(&cs->timer);
+          restore_flags(flags);
+        }
+       else
+          cs->akt_state = DEFLECT_ALERT; 
+     break;      
+
+   } /* switch */
+  return(i);
+} /* deflect_extern_action */
+
+/********************************/
+/* insert a new rule before idx */
+/********************************/
+int insertrule(int idx, divert_rule *newrule)
+{ struct deflect_struc *ds,*ds1;
+  int flags;
+
+  if (!(ds = (struct deflect_struc *) kmalloc(sizeof(struct deflect_struc), 
+                                              GFP_KERNEL))) 
+    return(-ENOMEM); /* no memory */
+
+  ds->rule = *newrule; /* set rule */
+
+  save_flags(flags);
+  cli();
+
+  if (idx >= 0)
+   { ds1 = table_head;
+     while ((ds1) && (idx > 0))
+      { idx--;
+        ds1 = ds1->next;
+      } 
+     if (!ds1) idx = -1; 
+   }
+
+  if (idx < 0)
+   { ds->prev = table_tail; /* previous entry */
+     ds->next = NULL; /* end of chain */
+     if (ds->prev) 
+       ds->prev->next = ds; /* last forward */
+      else
+        table_head = ds; /* is first entry */
+     table_tail = ds; /* end of queue */
+   }
+  else
+    { ds->next = ds1; /* next entry */
+      ds->prev = ds1->prev; /* prev entry */
+      ds1->prev = ds; /* backward chain old element */
+      if (!ds->prev)
+        table_head = ds; /* first element */
+   }
+
+  restore_flags(flags);
+  return(0);
+} /* insertrule */
+
+/***********************************/
+/* delete the rule at position idx */
+/***********************************/
+int deleterule(int idx)
+{ struct deflect_struc *ds,*ds1;
+  int flags;
+  
+  if (idx < 0) 
+   { save_flags(flags);
+     cli();
+     ds = table_head;
+     table_head = NULL;
+     table_tail = NULL;
+     restore_flags(flags);
+     while (ds)
+      { ds1 = ds; 
+        ds = ds->next;
+        kfree(ds1);
+      } 
+     return(0); 
+   }
+
+  save_flags(flags);
+  cli();
+  ds = table_head;
+
+  while ((ds) && (idx > 0))
+   { idx--; 
+     ds = ds->next;  
+   }
+
+  if (!ds) 
+   { restore_flags(flags);
+     return(-EINVAL);
+   }  
+
+  if (ds->next) 
+    ds->next->prev = ds->prev; /* backward chain */
+   else
+     table_tail = ds->prev; /* end of chain */
+
+  if (ds->prev)
+    ds->prev->next = ds->next; /* forward chain */
+   else
+     table_head = ds->next; /* start of chain */      
+  
+  restore_flags(flags);
+  kfree(ds);
+  return(0);
+} /* deleterule */
+
+/*******************************************/
+/* get a pointer to a specific rule number */
+/*******************************************/
+divert_rule *getruleptr(int idx)
+{ struct deflect_struc *ds = table_head;
+  
+  if (idx < 0) return(NULL);
+  while ((ds) && (idx >= 0))
+   { if (!(idx--)) 
+      { return(&ds->rule);
+        break;
+      }
+     ds = ds->next;  
+   }
+  return(NULL);
+} /* getruleptr */
+
+/*************************************************/
+/* called from common module on an incoming call */
+/*************************************************/
+int isdn_divert_icall(isdn_ctrl *ic)
+{ int retval = 0;
+  int flags;
+  struct call_struc *cs = NULL; 
+  struct deflect_struc *dv;
+  char *p,*p1;
+  u_char accept;
+
+  /* first check the internal deflection table */
+  for (dv = table_head; dv ; dv = dv->next )
+   { /* scan table */
+     if (((dv->rule.callopt == 1) && (ic->command == ISDN_STAT_ICALLW)) ||
+         ((dv->rule.callopt == 2) && (ic->command == ISDN_STAT_ICALL)))
+       continue; /* call option check */  
+     if (!(dv->rule.drvid & (1L << ic->driver))) 
+       continue; /* driver not matching */ 
+     if ((dv->rule.si1) && (dv->rule.si1 != ic->parm.setup.si1)) 
+       continue; /* si1 not matching */
+     if ((dv->rule.si2) && (dv->rule.si2 != ic->parm.setup.si2)) 
+       continue; /* si2 not matching */
+
+     p = dv->rule.my_msn;
+     p1 = ic->parm.setup.eazmsn;
+     accept = 0;
+     while (*p)
+      { /* complete compare */
+        if (*p == '-')
+	  { accept = 1; /* call accepted */
+            break;
+          }
+        if (*p++ != *p1++) 
+          break; /* not accepted */
+        if ((!*p) && (!*p1))
+          accept = 1;
+      } /* complete compare */
+     if (!accept) continue; /* not accepted */
+ 
+     if ((strcmp(dv->rule.caller,"0")) || (ic->parm.setup.phone[0]))
+      { p = dv->rule.caller;
+        p1 = ic->parm.setup.phone;
+        accept = 0;
+        while (*p)
+	 { /* complete compare */
+           if (*p == '-')
+	    { accept = 1; /* call accepted */
+              break;
+            }
+           if (*p++ != *p1++) 
+             break; /* not accepted */
+           if ((!*p) && (!*p1))
+             accept = 1;
+         } /* complete compare */
+        if (!accept) continue; /* not accepted */
+      }  
+
+     switch (dv->rule.action)
+       { case DEFLECT_IGNORE:
+           return(0);
+           break;
+
+         case DEFLECT_ALERT:
+         case DEFLECT_PROCEED:
+         case DEFLECT_REPORT:
+         case DEFLECT_REJECT:
+           if (dv->rule.action == DEFLECT_PROCEED)
+	    if ((!if_used) || ((!extern_wait_max) && (!dv->rule.waittime))) 
+              return(0); /* no external deflection needed */  
+           if (!(cs = (struct call_struc *) kmalloc(sizeof(struct call_struc), GFP_ATOMIC))) 
+             return(0); /* no memory */
+           init_timer(&cs->timer);
+           cs->info[0] = '\0';
+           cs->timer.function = deflect_timer_expire;
+           cs->timer.data = (ulong) cs; /* pointer to own structure */
+           
+           cs->ics = *ic; /* copy incoming data */
+           if (!cs->ics.parm.setup.phone[0]) strcpy(cs->ics.parm.setup.phone,"0");
+           if (!cs->ics.parm.setup.eazmsn[0]) strcpy(cs->ics.parm.setup.eazmsn,"0");
+	   cs->ics.parm.setup.screen = dv->rule.screen;  
+           if (dv->rule.waittime) 
+             cs->timer.expires = jiffies + (HZ * dv->rule.waittime);
+           else
+            if (dv->rule.action == DEFLECT_PROCEED)
+              cs->timer.expires = jiffies + (HZ * extern_wait_max); 
+            else  
+              cs->timer.expires = 0;
+           cs->akt_state = dv->rule.action;                
+           save_flags(flags);
+           cli();
+           cs->divert_id = next_id++; /* new sequence number */
+           restore_flags(flags);
+           cs->prev = NULL;
+           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");
+                   ic->parm.setup.screen = dv->rule.screen;
+                   strcpy(ic->parm.setup.phone,dv->rule.to_nr);
+                   cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
+                   cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
+                   retval = 4; 
+                 }
+               else
+                 retval = 1; /* alerting */                 
+             }
+           else
+             { cs->deflect_dest[0] = '\0';
+	       retval = 3; /* only proceed */
+             }  
+           sprintf(cs->info,"%d 0x%lx %s %s %s %s 0x%x 0x%x %d %d %s\n",
+                   cs->akt_state,
+                   cs->divert_id,
+                   divert_if.drv_to_name(cs->ics.driver),
+                   (ic->command == ISDN_STAT_ICALLW) ? "1":"0", 
+                   cs->ics.parm.setup.phone, 
+                   cs->ics.parm.setup.eazmsn,
+                   cs->ics.parm.setup.si1,
+                   cs->ics.parm.setup.si2,
+                   cs->ics.parm.setup.screen,
+                   dv->rule.waittime,
+                   cs->deflect_dest);
+           if ((dv->rule.action == DEFLECT_REPORT) ||
+               (dv->rule.action == DEFLECT_REJECT))
+	    { put_info_buffer(cs->info);
+	      kfree(cs); /* remove */
+              return((dv->rule.action == DEFLECT_REPORT) ? 0:2); /* nothing to do */ 
+            }              
+           break;
+  
+         default:
+           return(0); /* ignore call */
+           break;
+       } /* switch action */    
+     break; 
+   } /* scan_table */
+
+  if (cs) 
+   { cs->prev = NULL;
+     save_flags(flags);
+     cli();
+     cs->next = divert_head;
+     divert_head = cs; 
+     if (cs->timer.expires) add_timer(&cs->timer);
+     restore_flags(flags);
+
+     put_info_buffer(cs->info); 
+     return(retval);
+   }
+  else
+     return(0);
+} /* isdn_divert_icall */
+
+
+void deleteprocs(void)
+{ struct call_struc *cs, *cs1; 
+  int flags;
+
+  save_flags(flags);
+  cli();
+  cs = divert_head;
+  divert_head = NULL;
+  while (cs)
+   { del_timer(&cs->timer);
+     cs1 = cs;
+     cs = cs->next;
+     kfree(cs1);
+   } 
+  restore_flags(flags);
+} /* deleteprocs */
+
+/****************************************************/
+/* put a address including address type into buffer */
+/****************************************************/
+int put_address(char *st, u_char *p, int len)
+{ u_char retval = 0;
+  u_char adr_typ = 0; /* network standard */
+
+  if (len < 2) return(retval);
+  if (*p == 0xA1)
+   { retval = *(++p) + 2; /* total length */
+     if (retval > len) return(0); /* too short */
+     len = retval - 2; /* remaining length */
+     if (len < 3) return(0);
+     if ((*(++p) != 0x0A) || (*(++p) != 1)) return(0);
+     adr_typ = *(++p);
+     len -= 3;
+     p++;
+     if (len < 2) return(0);
+     if (*p++ != 0x12) return(0);
+     if (*p > len) return(0); /* check number length */
+     len = *p++;
+   }   
+  else
+   if (*p == 0x80)
+    { retval = *(++p) + 2; /* total length */
+      if (retval > len) return(0);
+      len = retval - 2;
+      p++;
+    }
+   else  
+    return(0); /* invalid address information */
+
+  sprintf(st,"%d ",adr_typ);
+  st += strlen(st);
+  if (!len) 
+    *st++ = '-';
+  else
+   while (len--)
+     *st++ = *p++;
+  *st = '\0';
+  return(retval);
+} /* put_address */
+
+/*************************************/
+/* report a succesfull interrogation */
+/*************************************/
+int interrogate_success(isdn_ctrl *ic, struct call_struc *cs)
+{ char *src = ic->parm.dss1_io.data;
+  int restlen = ic->parm.dss1_io.datalen;
+  int cnt = 1;
+  u_char n,n1;
+  char st[90], *p, *stp;
+
+  if (restlen < 2) return(-100); /* frame too short */
+  if (*src++ != 0x30) return(-101);
+  if ((n = *src++) > 0x81) return(-102); /* invalid length field */
+  restlen -= 2; /* remaining bytes */
+  if (n == 0x80)
+   { if (restlen < 2) return(-103);
+     if ((*(src+restlen-1)) || (*(src+restlen-2))) return(-104);
+     restlen -= 2;
+   }
+  else
+   if ( n == 0x81)
+    { n = *src++;
+      restlen--;
+      if (n > restlen) return(-105);
+      restlen = n;
+    }
+   else
+    if (n > restlen) return(-106);
+     else 
+      restlen = n; /* standard format */   
+  if (restlen < 3) return(-107); /* no procedure */
+  if ((*src++ != 2) || (*src++ != 1) || (*src++ != 0x0B)) return(-108);
+  restlen -= 3; 
+  if (restlen < 2) return(-109); /* list missing */
+  if (*src == 0x31)
+   { src++; 
+     if ((n = *src++) > 0x81) return(-110); /* invalid length field */
+     restlen -= 2; /* remaining bytes */
+     if (n == 0x80)
+      { if (restlen < 2) return(-111);
+        if ((*(src+restlen-1)) || (*(src+restlen-2))) return(-112);
+        restlen -= 2;
+      }
+     else
+      if ( n == 0x81)
+       { n = *src++;
+         restlen--;
+         if (n > restlen) return(-113);
+         restlen = n;
+       }
+      else
+       if (n > restlen) return(-114);
+        else 
+         restlen = n; /* standard format */   
+   } /* result list header */ 
+
+  while (restlen >= 2)
+   { stp = st;
+     sprintf(stp,"%d 0x%lx %d %s ",DIVERT_REPORT, ic->parm.dss1_io.ll_id,
+                 cnt++,divert_if.drv_to_name(ic->driver));
+     stp += strlen(stp);
+     if (*src++ != 0x30) return(-115); /* invalid enum */
+     n = *src++;
+     restlen -= 2;
+     if (n > restlen) return(-116); /* enum length wrong */
+     restlen -= n;
+     p = src; /* one entry */
+     src += n;
+     if (!(n1 = put_address(stp,p,n & 0xFF))) continue;
+     stp += strlen(stp);
+     p += n1;
+     n -= n1;
+     if (n < 6) continue; /* no service and proc */
+     if ((*p++ != 0x0A) || (*p++ != 1)) continue;
+     sprintf(stp," 0x%02x ",(*p++) & 0xFF);
+     stp += strlen(stp);
+     if ((*p++ != 0x0A) || (*p++ != 1)) continue;
+     sprintf(stp,"%d ",(*p++) & 0xFF);
+     stp += strlen(stp);
+     n -= 6;
+     if (n > 2)
+      { if (*p++ != 0x30) continue;
+        if (*p > (n-2)) continue;
+        n = *p++;
+        if (!(n1 = put_address(stp,p,n & 0xFF))) continue;
+        stp += strlen(stp);
+      }
+     sprintf(stp,"\n");
+     put_info_buffer(st);
+   } /* while restlen */
+  if (restlen) return(-117);
+  return(0);   
+} /* interrogate_success */
+
+/*********************************************/
+/* callback for protocol specific extensions */
+/*********************************************/
+int prot_stat_callback(isdn_ctrl *ic)
+{ struct call_struc *cs, *cs1;
+  int i,flags;
+
+  cs = divert_head; /* start of list */
+  cs1 = NULL;
+  while (cs)
+   { if (ic->driver == cs->ics.driver) 
+      { switch (cs->ics.arg)
+	 { case DSS1_CMD_INVOKE:
+             if ((cs->ics.parm.dss1_io.ll_id == ic->parm.dss1_io.ll_id) &&
+                 (cs->ics.parm.dss1_io.hl_id == ic->parm.dss1_io.hl_id))
+	      { switch (ic->arg)
+		{  case DSS1_STAT_INVOKE_ERR:
+                     sprintf(cs->info,"128 0x%lx 0x%x\n", 
+                             ic->parm.dss1_io.ll_id,
+                             ic->parm.dss1_io.timeout);
+                     put_info_buffer(cs->info);
+                   break;
+                   
+                   case DSS1_STAT_INVOKE_RES:
+                     switch (cs->ics.parm.dss1_io.proc)
+		      {  case  7:
+                         case  8:
+                            put_info_buffer(cs->info); 
+                           break;
+                       
+                         case  11:
+                           i = interrogate_success(ic,cs);
+                           if (i)
+                             sprintf(cs->info,"%d 0x%lx %d\n",DIVERT_REPORT, 
+                                     ic->parm.dss1_io.ll_id,i);
+                           put_info_buffer(cs->info); 
+                           break;
+                       
+		         default: 
+                           printk(KERN_WARNING "dss1_divert: unknown proc %d\n",cs->ics.parm.dss1_io.proc);
+                           break;
+                      } 
+
+
+#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:
+                     printk(KERN_WARNING "dss1_divert unknown invoke answer %lx\n",ic->arg);
+                   break;  
+                 } 
+                cs1 = cs; /* remember structure */
+                cs = NULL; 
+                continue; /* abort search */
+              } /* id found */ 
+           break;
+   
+	   case DSS1_CMD_INVOKE_ABORT:
+             printk(KERN_WARNING "dss1_divert unhandled invoke abort\n"); 
+           break;   
+         
+	   default:
+             printk(KERN_WARNING "dss1_divert unknown cmd 0x%lx\n",cs->ics.arg); 
+           break; 
+         } /* switch ics.arg */ 
+        cs = cs->next; 
+      } /* driver ok */
+   }  
+   
+  if (!cs1) 
+   { printk(KERN_WARNING "dss1_divert unhandled process\n");
+     return(0);
+   }  
+
+  if (cs1->ics.driver == -1)
+   { save_flags(flags);
+     cli();
+     del_timer(&cs1->timer);
+     if (cs1->prev) 
+       cs1->prev->next = cs1->next; /* forward link */
+     else
+       divert_head = cs1->next;
+     if (cs1->next)
+       cs1->next->prev = cs1->prev; /* back link */           
+     restore_flags(flags); 
+     kfree(cs1);
+   } 
+
+  return(0);
+} /* prot_stat_callback */
+
+
+/***************************/
+/* status callback from HL */
+/***************************/
+int isdn_divert_stat_callback(isdn_ctrl *ic)
+{ struct call_struc *cs, *cs1;
+  int flags, retval;
+
+  retval = -1;
+  cs = divert_head; /* start of list */
+     while (cs)
+      { if ((ic->driver == cs->ics.driver) && (ic->arg == cs->ics.arg))
+         { switch (ic->command)
+	    { case ISDN_STAT_DHUP:
+                sprintf(cs->info,"129 0x%lx\n",cs->divert_id);
+                del_timer(&cs->timer);
+                cs->ics.driver = -1;
+                break;
+
+	      case ISDN_STAT_CAUSE:
+                sprintf(cs->info,"130 0x%lx %s\n",cs->divert_id,ic->parm.num);
+                break;
+
+	      case ISDN_STAT_REDIR:
+                sprintf(cs->info,"131 0x%lx\n",cs->divert_id);
+                del_timer(&cs->timer);
+                cs->ics.driver = -1;
+                break; 
+
+	      default:
+                sprintf(cs->info,"999 0x%lx 0x%x\n",cs->divert_id,(int)(ic->command));
+                break; 
+            }
+          put_info_buffer(cs->info);
+          retval = 0; 
+         }
+        cs1 = cs; 
+        cs = cs->next;
+        if (cs1->ics.driver == -1)
+          { 
+            save_flags(flags);
+            cli();
+            if (cs1->prev) 
+              cs1->prev->next = cs1->next; /* forward link */
+            else
+              divert_head = cs1->next;
+            if (cs1->next)
+              cs1->next->prev = cs1->prev; /* back link */           
+            restore_flags(flags); 
+            kfree(cs1);
+          } 
+      }  
+  return(retval); /* not found */
+} /* isdn_divert_stat_callback */ 
+
+
+/********************/
+/* callback from ll */
+/********************/ 
+int ll_callback(isdn_ctrl *ic)
+{
+  switch (ic->command)
+   { case ISDN_STAT_ICALL:
+     case ISDN_STAT_ICALLW:
+       return(isdn_divert_icall(ic));
+     break;
+
+     case ISDN_STAT_PROT:
+       if ((ic->arg & 0xFF) == ISDN_PTYPE_EURO)
+	{ if (ic->arg != DSS1_STAT_INVOKE_BRD)
+            return(prot_stat_callback(ic));
+          else
+            return(0); /* DSS1 invoke broadcast */
+        }
+       else
+         return(-1); /* protocol not euro */    
+
+     default:
+       return(isdn_divert_stat_callback(ic));
+   }
+} /* ll_callback */
+
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/divert/isdn_divert.h linux/drivers/isdn/divert/isdn_divert.h
--- v2.3.13/linux/drivers/isdn/divert/isdn_divert.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/divert/isdn_divert.h	Sun Aug 15 11:49:08 1999
@@ -0,0 +1,158 @@
+/* 
+ * $Id: isdn_divert.h,v 1.2 1999/07/04 21:37:33 werner Exp $
+ *
+ * Header for the diversion supplementary ioctl interface.
+ *
+ * Copyright 1998       by Werner Cornelius (werner@ikt.de)
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ * $Log: isdn_divert.h,v $
+ * Revision 1.2  1999/07/04 21:37:33  werner
+ * Ported from kernel version 2.0
+ *
+ *
+ *
+ */
+
+
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+/******************************************/
+/* IOCTL codes for interface to user prog */
+/******************************************/
+#define DIVERT_IIOC_VERSION 0x01 /* actual version */
+#define IIOCGETVER   _IO('I', 1)  /* get version of interface */
+#define IIOCGETDRV   _IO('I', 2)  /* get driver number */
+#define IIOCGETNAM   _IO('I', 3)  /* get driver name */
+#define IIOCGETRULE  _IO('I', 4)  /* read one rule */
+#define IIOCMODRULE  _IO('I', 5)  /* modify/replace a rule */  
+#define IIOCINSRULE  _IO('I', 6)  /* insert/append one rule */
+#define IIOCDELRULE  _IO('I', 7)  /* delete a rule */
+#define IIOCDODFACT  _IO('I', 8)  /* hangup/reject/alert/immediately deflect a call */
+#define IIOCDOCFACT  _IO('I', 9)  /* activate control forwarding in PBX */
+#define IIOCDOCFDIS  _IO('I',10)  /* deactivate control forwarding in PBX */
+#define IIOCDOCFINT  _IO('I',11)  /* interrogate control forwarding in PBX */
+
+/*************************************/
+/* states reported through interface */
+/*************************************/
+#define DEFLECT_IGNORE    0  /* ignore incoming call */
+#define DEFLECT_REPORT    1  /* only report */
+#define DEFLECT_PROCEED   2  /* deflect when externally triggered */
+#define DEFLECT_ALERT     3  /* alert and deflect after delay */ 
+#define DEFLECT_REJECT    4  /* reject immediately */
+#define DIVERT_ACTIVATE   5  /* diversion activate */
+#define DIVERT_DEACTIVATE 6  /* diversion deactivate */
+#define DIVERT_REPORT     7  /* interrogation result */ 
+#define DEFLECT_AUTODEL 255  /* only for internal use */ 
+
+#define DEFLECT_ALL_IDS   0xFFFFFFFF /* all drivers selected */
+
+typedef struct
+ { ulong drvid;     /* driver ids, bit mapped */
+   char my_msn[35]; /* desired msn, subaddr allowed */
+   char caller[35]; /* caller id, partial string with * + subaddr allowed */
+   char to_nr[35];  /* deflected to number incl. subaddress */
+   u_char si1,si2;  /* service indicators, si1=bitmask, si1+2 0 = all */
+   u_char screen;   /* screening: 0 = no info, 1 = info, 2 = nfo with nr */
+   u_char callopt;  /* option for call handling: 
+                       0 = all calls
+                       1 = only non waiting calls
+                       2 = only waiting calls */
+   u_char action;   /* desired action: 
+                       0 = don't report call -> ignore
+                       1 = report call, do not allow/proceed for deflection
+                       2 = report call, send proceed, wait max waittime secs
+                       3 = report call, alert and deflect after waittime 
+                       4 = report call, reject immediately  
+                       actions 1-2 only take place if interface is opened 
+		    */
+   u_char waittime; /* maximum wait time for proceeding */ 
+ } divert_rule;
+
+typedef union
+ { int drv_version; /* return of driver version */
+   struct 
+   { int drvid; /* id of driver */
+     char drvnam[30]; /* name of driver */
+   } getid;
+   struct
+   { int ruleidx; /* index of rule */
+     divert_rule rule; /* rule parms */ 
+   } getsetrule;
+   struct
+   { u_char subcmd;  /* 0 = hangup/reject,
+                        1 = alert,
+                        2 = deflect */
+     ulong callid;   /* id of call delivered by ascii output */
+     char to_nr[35]; /* destination when deflect,
+                        else uus1 string (maxlen 31),
+                        data from rule used if empty */ 
+   } fwd_ctrl; 
+   struct
+   { int drvid;      /* id of driver */
+     u_char cfproc;  /* cfu = 0, cfb = 1, cfnr = 2 */
+     ulong procid;   /* process id returned when no error */ 
+     u_char service; /* basically coded service, 0 = all */
+     char msn[25];   /* desired msn, empty = all */
+     char fwd_nr[35];/* forwarded to number + subaddress */
+   } cf_ctrl;  
+ } divert_ioctl;
+
+#ifdef __KERNEL__
+
+#include <linux/isdnif.h>
+#include <linux/isdn_divertif.h>
+
+#define AUTODEL_TIME 30 /* timeout in s to delete internal entrys */
+
+/**************************************************/
+/* structure keeping ascii info for device output */
+/**************************************************/
+struct divert_info
+  { struct divert_info *next;
+    ulong usage_cnt; /* number of files still to work */   
+    char info_start[2]; /* info string start */ 
+  }; 
+
+
+/**************/
+/* Prototypes */
+/**************/
+extern ulong if_used; /* number of interface users */
+extern int divert_dev_deinit(void);
+extern int divert_dev_init(void);
+extern void put_info_buffer(char *);
+extern int ll_callback(isdn_ctrl *);
+extern isdn_divert_if divert_if;
+extern divert_rule *getruleptr(int);
+extern int insertrule(int, divert_rule *);
+extern int deleterule(int);
+extern void deleteprocs(void);
+extern int deflect_extern_action(u_char, ulong, char *);
+extern int cf_command(int, int, u_char, char *, u_char, char *, ulong *);
+
+#endif __KERNEL__
+
+
+
+
+
+
+
+
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/eicon/eicon.h linux/drivers/isdn/eicon/eicon.h
--- v2.3.13/linux/drivers/isdn/eicon/eicon.h	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/eicon/eicon.h	Sun Aug 15 11:49:08 1999
@@ -1,4 +1,4 @@
-/* $Id: eicon.h,v 1.5 1999/03/29 11:19:41 armin Exp $
+/* $Id: eicon.h,v 1.8 1999/07/25 15:12:01 armin Exp $
  *
  * ISDN low-level module for Eicon.Diehl active ISDN-Cards.
  *
@@ -21,6 +21,19 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon.h,v $
+ * Revision 1.8  1999/07/25 15:12:01  armin
+ * fix of some debug logs.
+ * enabled ISA-cards option.
+ *
+ * Revision 1.7  1999/07/11 17:16:23  armin
+ * Bugfixes in queue handling.
+ * Added DSP-DTMF decoder functions.
+ * Reorganized ack_handler.
+ *
+ * Revision 1.6  1999/06/09 19:31:24  armin
+ * Wrong PLX size for request_region() corrected.
+ * Added first MCA code from Erik Weber.
+ *
  * Revision 1.5  1999/03/29 11:19:41  armin
  * I/O stuff now in seperate file (eicon_io.c)
  * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
@@ -100,6 +113,7 @@
 #define EICON_ISA_BOOT_NORMAL 2
 
 /* Struct for downloading protocol via ioctl for ISA cards */
+/* same struct for downloading protocol via ioctl for MCA cards */
 typedef struct {
 	/* start-up parameters */
 	unsigned char tei;
@@ -156,6 +170,7 @@
 /* Data for downloading protocol via ioctl */
 typedef union {
 	eicon_isa_codebuf isa;
+	eicon_isa_codebuf mca;
 	eicon_pci_codebuf pci;
 } eicon_codebuf;
 
@@ -171,6 +186,7 @@
 #ifdef __KERNEL__
 
 /* Kernel includes */
+#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/tqueue.h>
@@ -333,19 +349,39 @@
   __u16                 ref;            /* saved reference          */
 } entity;
 
+#define FAX_MAX_SCANLINE 256
+
+typedef struct {
+	__u8		PrevObject;
+	__u8		NextObject;
+	__u8		abLine[FAX_MAX_SCANLINE];
+	__u8		abFrame[FAX_MAX_SCANLINE];
+	unsigned int	LineLen;
+	unsigned int	LineDataLen;
+	__u32		LineData;
+	unsigned int	NullBytesPos;
+	__u8		NullByteExist;
+	int		PageCount;
+	__u8		Dle;
+	__u8		Eop;
+} eicon_ch_fax_buf;
 
 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   */
-	unsigned int   queued;           /* User-Data Bytes in TX queue */
-	unsigned int   waitq;            /* User-Data Bytes in wait queue */
-	unsigned int   waitpq;           /* User-Data Bytes in packet queue */
+	int		queued;          /* User-Data Bytes in TX queue */
+	int		waitq;           /* User-Data Bytes in wait queue */
+	int		waitpq;          /* User-Data Bytes in packet queue */
 	unsigned short plci;
 	unsigned short ncci;
 	unsigned char  l2prot;           /* Layer 2 protocol            */
 	unsigned char  l3prot;           /* Layer 3 protocol            */
+#ifdef CONFIG_ISDN_TTY_FAX
+	T30_s		*fax;		 /* pointer to fax data in LL	*/
+	eicon_ch_fax_buf fax2;		 /* fax related struct		*/
+#endif
 	entity		e;		 /* Entity  			*/
 	char		cpn[32];	 /* remember cpn		*/
 	char		oad[32];	 /* remember oad		*/
@@ -392,14 +428,10 @@
 #define EICON_LOCK_TX 0
 #define EICON_LOCK_RX 1
 
-typedef struct {
-	int dummy;
-} eicon_mca_card;
-
 typedef union {
 	eicon_isa_card isa;
 	eicon_pci_card pci;
-	eicon_mca_card mca;
+	eicon_isa_card mca;
 } eicon_hwif;
 
 typedef struct {
@@ -465,6 +497,9 @@
 	char   *status_buf_end;
         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
 } eicon_card;
 
 /* -----------------------------------------------------------**
@@ -521,6 +556,12 @@
 extern void eicon_irq(int irq, void *dev_id, struct pt_regs *regs);
 extern void eicon_io_rcv_dispatch(eicon_card *ccard);
 extern void eicon_io_ack_dispatch(eicon_card *ccard);
+#ifdef CONFIG_MCA
+extern int eicon_mca_find_card(int, int, int, char *);
+extern int eicon_mca_probe(int, int, int, int, char *);
+extern int eicon_info(char *, int , void *);
+#endif /* CONFIG_MCA */
+
 extern ulong DebugVar;
 
 #endif  /* __KERNEL__ */
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/eicon/eicon_dsp.h linux/drivers/isdn/eicon/eicon_dsp.h
--- v2.3.13/linux/drivers/isdn/eicon/eicon_dsp.h	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/eicon/eicon_dsp.h	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: eicon_dsp.h,v 1.2 1999/03/29 11:19:42 armin Exp $
+/* $Id: eicon_dsp.h,v 1.4 1999/07/25 15:12:02 armin Exp $
  *
  * ISDN lowlevel-module for Eicon.Diehl active cards.
  *        DSP definitions
@@ -21,6 +21,15 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: eicon_dsp.h,v $
+ * Revision 1.4  1999/07/25 15:12:02  armin
+ * fix of some debug logs.
+ * enabled ISA-cards option.
+ *
+ * Revision 1.3  1999/07/11 17:16:24  armin
+ * Bugfixes in queue handling.
+ * Added DSP-DTMF decoder functions.
+ * Reorganized ack_handler.
+ *
  * Revision 1.2  1999/03/29 11:19:42  armin
  * I/O stuff now in seperate file (eicon_io.c)
  * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
@@ -31,7 +40,7 @@
  *
  */
 
-#ifndef DSP_H
+#ifndef DSP_H 
 #define DSP_H
 
 #define DSP_UDATA_REQUEST_RECONFIGURE           0
@@ -264,6 +273,10 @@
   <word> tone duration (ms)
   <word> gap duration (ms)
 */
+typedef struct enable_dtmf_s {
+	__u16 tone;
+	__u16 gap;
+} enable_dtmf_s;
 
 #define DSP_UDATA_REQUEST_DISABLE_DTMF_RECEIVER 18
 /*
@@ -299,6 +312,108 @@
 returns:
   - none -
 */
+
+/* ============= FAX ================ */
+
+#define EICON_FAXID_LEN 20
+
+typedef struct eicon_t30_s {
+  __u8          code;
+  __u8          rate;
+  __u8          resolution;
+  __u8          format;
+  __u8          pages_low;
+  __u8          pages_high;
+  __u8          atf;
+  __u8          control_bits_low;
+  __u8          control_bits_high;
+  __u8          feature_bits_low;
+  __u8          feature_bits_high;
+  __u8          universal_5;
+  __u8          universal_6;
+  __u8          universal_7;
+  __u8          station_id_len;
+  __u8          head_line_len;
+  __u8          station_id[EICON_FAXID_LEN];
+/* __u8          head_line[]; */
+} eicon_t30_s;
+
+        /* EDATA transmit messages */
+#define EDATA_T30_DIS       0x01
+#define EDATA_T30_FTT       0x02
+#define EDATA_T30_MCF       0x03
+
+        /* EDATA receive messages */
+#define EDATA_T30_DCS       0x81
+#define EDATA_T30_TRAIN_OK  0x82
+#define EDATA_T30_EOP       0x83
+#define EDATA_T30_MPS       0x84
+#define EDATA_T30_EOM       0x85
+#define EDATA_T30_DTC       0x86
+
+#define T30_FORMAT_SFF            0
+#define T30_FORMAT_ASCII          1
+#define T30_FORMAT_COUNT          2
+
+#define T30_CONTROL_BIT_DISABLE_FINE      0x0001
+#define T30_CONTROL_BIT_ENABLE_ECM        0x0002
+#define T30_CONTROL_BIT_ECM_64_BYTES      0x0004
+#define T30_CONTROL_BIT_ENABLE_2D_CODING  0x0008
+#define T30_CONTROL_BIT_ENABLE_T6_CODING  0x0010
+#define T30_CONTROL_BIT_ENABLE_UNCOMPR    0x0020
+#define T30_CONTROL_BIT_ACCEPT_POLLING    0x0040
+#define T30_CONTROL_BIT_REQUEST_POLLING   0x0080
+#define T30_CONTROL_BIT_MORE_DOCUMENTS    0x0100
+
+#define T30_CONTROL_BIT_ALL_FEATURES\
+  (T30_CONTROL_BIT_ENABLE_ECM | T30_CONTROL_BIT_ENABLE_2D_CODING |\
+   T30_CONTROL_BIT_ENABLE_T6_CODING | T30_CONTROL_BIT_ENABLE_UNCOMPR)
+
+#define T30_FEATURE_BIT_FINE              0x0001
+#define T30_FEATURE_BIT_ECM               0x0002
+#define T30_FEATURE_BIT_ECM_64_BYTES      0x0004
+#define T30_FEATURE_BIT_2D_CODING         0x0008
+#define T30_FEATURE_BIT_T6_CODING         0x0010
+#define T30_FEATURE_BIT_UNCOMPR_ENABLED   0x0020
+#define T30_FEATURE_BIT_POLLING           0x0040
+
+#define FAX_OBJECT_DOCU		1
+#define FAX_OBJECT_PAGE		2
+#define FAX_OBJECT_LINE		3
+
+#define T4_EOL			0x800
+#define T4_EOL_BITSIZE		12
+#define T4_EOL_DWORD		(T4_EOL << (32 - T4_EOL_BITSIZE))
+#define T4_EOL_MASK_DWORD	((__u32) -1 << (32 - T4_EOL_BITSIZE))
+
+#define SFF_LEN_FLD_SIZE	3
+
+#define _DLE_	0x10
+#define _ETX_	0x03
+
+typedef struct eicon_sff_dochead {
+	__u32	id		__attribute__ ((packed));
+	__u8	version		__attribute__ ((packed));
+	__u8	reserved1	__attribute__ ((packed));
+	__u16	userinfo	__attribute__ ((packed));
+	__u16	pagecount	__attribute__ ((packed));
+	__u16	off1pagehead	__attribute__ ((packed));
+	__u32	offnpagehead	__attribute__ ((packed));
+	__u32	offdocend	__attribute__ ((packed));
+} eicon_sff_dochead;
+
+typedef struct eicon_sff_pagehead {
+	__u8	pageheadid	__attribute__ ((packed));
+	__u8	pageheadlen	__attribute__ ((packed));
+	__u8	resvert		__attribute__ ((packed));
+	__u8	reshoriz	__attribute__ ((packed));
+	__u8	coding		__attribute__ ((packed));
+	__u8	reserved2	__attribute__ ((packed));
+	__u16	linelength	__attribute__ ((packed));
+	__u16	pagelength	__attribute__ ((packed));
+	__u32	offprevpage	__attribute__ ((packed));
+	__u32	offnextpage	__attribute__ ((packed));
+} eicon_sff_pagehead;
 
 #endif	/* DSP_H */
 
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/eicon/eicon_idi.c linux/drivers/isdn/eicon/eicon_idi.c
--- v2.3.13/linux/drivers/isdn/eicon/eicon_idi.c	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/eicon/eicon_idi.c	Sun Aug 15 11:49:08 1999
@@ -1,4 +1,4 @@
-/* $Id: eicon_idi.c,v 1.9 1999/03/29 11:19:42 armin Exp $
+/* $Id: eicon_idi.c,v 1.11 1999/07/25 15:12:03 armin Exp $
  *
  * ISDN lowlevel-module for Eicon.Diehl active cards.
  *        IDI interface 
@@ -21,6 +21,15 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon_idi.c,v $
+ * Revision 1.11  1999/07/25 15:12:03  armin
+ * fix of some debug logs.
+ * enabled ISA-cards option.
+ *
+ * Revision 1.10  1999/07/11 17:16:24  armin
+ * Bugfixes in queue handling.
+ * Added DSP-DTMF decoder functions.
+ * Reorganized ack_handler.
+ *
  * Revision 1.9  1999/03/29 11:19:42  armin
  * I/O stuff now in seperate file (eicon_io.c)
  * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
@@ -61,6 +70,7 @@
  *
  */
 
+#include <linux/config.h>
 #define __NO_VERSION__
 #include "eicon.h"
 #include "eicon_idi.h"
@@ -68,7 +78,7 @@
 
 #undef EICON_FULL_SERVICE_OKTETT
 
-char *eicon_idi_revision = "$Revision: 1.9 $";
+char *eicon_idi_revision = "$Revision: 1.11 $";
 
 eicon_manifbuf *manbuf;
 
@@ -86,11 +96,15 @@
 
 int eicon_idi_manage_assign(eicon_card *card);
 int eicon_idi_manage_remove(eicon_card *card);
+int idi_fill_in_T30(eicon_chan *chan, unsigned char *buffer);
 
 int
 idi_assign_req(eicon_REQ *reqbuf, int signet, eicon_chan *chan)
 {
 	int l = 0;
+	int tmp;
+
+	tmp = 0;
   if (!signet) {
 	/* Signal Layer */
 	reqbuf->XBuffer.P[l++] = CAI;
@@ -133,10 +147,25 @@
 		case ISDN_PROTO_L2_MODEM:
 			reqbuf->XBuffer.P[l++] = 2;
 			break;
+		case ISDN_PROTO_L2_FAX:
+  			if (chan->fsm_state == EICON_STATE_IWAIT)
+				reqbuf->XBuffer.P[l++] = 3; /* autoconnect on incoming */
+			else
+				reqbuf->XBuffer.P[l++] = 2;
+			break;
 		default:
 			reqbuf->XBuffer.P[l++] = 1;
 	}
 	switch(chan->l3prot) {
+		case ISDN_PROTO_L3_FAX:
+#ifdef CONFIG_ISDN_TTY_FAX
+			reqbuf->XBuffer.P[l++] = 6;
+			reqbuf->XBuffer.P[l++] = NLC;
+			tmp = idi_fill_in_T30(chan, &reqbuf->XBuffer.P[l+1]);
+			reqbuf->XBuffer.P[l++] = tmp; 
+			l += tmp;
+			break;
+#endif
 		case ISDN_PROTO_L3_TRANS:
 		default:
 			reqbuf->XBuffer.P[l++] = 4;
@@ -210,6 +239,20 @@
 			reqbuf->XBuffer.P[6] = 128;
 			reqbuf->XBuffer.P[7] = 0;
 			break;
+		case ISDN_PROTO_L2_FAX:
+			reqbuf->XBuffer.P[2] = 0x10;
+			reqbuf->XBuffer.P[3] = 0;
+			reqbuf->XBuffer.P[4] = 0;
+			reqbuf->XBuffer.P[5] = 0;
+			reqbuf->XBuffer.P[6] = 128;
+			reqbuf->XBuffer.P[7] = 0;
+			break;
+		case ISDN_PROTO_L2_TRANS:
+			switch(chan->l3prot) {
+				case ISDN_PROTO_L3_TRANSDSP:
+					reqbuf->XBuffer.P[2] = 22; /* DTMF, audio events on */
+			}
+			break;
 	}
 	reqbuf->XBuffer.P[8] = 0;
 	reqbuf->XBuffer.length = l;
@@ -222,8 +265,8 @@
 int
 idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer)
 {
-        struct sk_buff *skb;
-        struct sk_buff *skb2;
+        struct sk_buff *skb = 0;
+        struct sk_buff *skb2 = 0;
 	eicon_REQ *reqbuf;
 	eicon_chan_ptr *chan2;
 
@@ -232,7 +275,11 @@
 
         if ((!skb) || (!skb2)) {
 		if (DebugVar & 1)
-                	printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed\n", chan->No);
+                	printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed in do_req()\n", chan->No);
+		if (skb) 
+			dev_kfree_skb(skb);
+		if (skb2) 
+			dev_kfree_skb(skb2);
                 return -ENOMEM; 
 	}
 
@@ -241,7 +288,7 @@
 
 	reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ));
 	if (DebugVar & 8)
-		printk(KERN_DEBUG "idi_req: Ch%d: 0x%02x (%s)\n", chan->No, cmd, (layer)?"Net":"Sig");
+		printk(KERN_DEBUG "idi_req: Ch%d: req %x (%s)\n", chan->No, cmd, (layer)?"Net":"Sig");
 	if (layer) cmd |= 0x700;
 	switch(cmd) {
 		case ASSIGN:
@@ -282,6 +329,8 @@
 		default:
 			if (DebugVar & 1)
 				printk(KERN_ERR "idi_req: Ch%d: Unknown request\n", chan->No);
+			dev_kfree_skb(skb);
+			dev_kfree_skb(skb2);
 			return(-1);
 	}
 
@@ -358,6 +407,9 @@
 	chan->fsm_state = EICON_STATE_NULL;
 	if (DebugVar & 8)
 		printk(KERN_DEBUG"idi_req: Ch%d: Hangup\n", chan->No);
+#ifdef CONFIG_ISDN_TTY_FAX
+	chan->fax = 0;
+#endif
   return(0);
 }
 
@@ -389,7 +441,11 @@
 
         if ((!skb) || (!skb2)) {
 		if (DebugVar & 1)
-                	printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed\n", chan->No);
+                	printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed in connect_req()\n", chan->No);
+		if (skb) 
+			dev_kfree_skb(skb);
+		if (skb2) 
+			dev_kfree_skb(skb2);
                 return -ENOMEM; 
 	}
 
@@ -472,6 +528,20 @@
 			reqbuf->XBuffer.P[l-2] = 128;
 			reqbuf->XBuffer.P[l-1] = 0;
                         break;
+                case ISDN_PROTO_L2_FAX:
+			reqbuf->XBuffer.P[l-6] = 0x10;
+			reqbuf->XBuffer.P[l-5] = 0;
+			reqbuf->XBuffer.P[l-4] = 0;
+			reqbuf->XBuffer.P[l-3] = 0;
+			reqbuf->XBuffer.P[l-2] = 128;
+			reqbuf->XBuffer.P[l-1] = 0;
+                        break;
+		case ISDN_PROTO_L2_TRANS:
+			switch(chan->l3prot) {
+				case ISDN_PROTO_L3_TRANSDSP:
+					reqbuf->XBuffer.P[l-6] = 22; /* DTMF, audio events on */
+			}
+			break;
         }
 	
 	reqbuf->XBuffer.P[l++] = 0; /* end */
@@ -813,6 +883,81 @@
   }
 }
 
+
+int
+idi_send_udata(eicon_card *card, eicon_chan *chan, int UReq, u_char *buffer, int len)
+{
+	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)) {
+		if (DebugVar & 1)
+			printk(KERN_DEBUG"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]);
+
+	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);
+		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, 1 + len + sizeof(eicon_REQ));
+
+	reqbuf->Req = IDI_N_UDATA;
+	reqbuf->ReqCh = 0;
+	reqbuf->ReqId = 1;
+
+	reqbuf->XBuffer.length = len + 1;
+	reqbuf->XBuffer.P[0] = UReq;
+	memcpy(&reqbuf->XBuffer.P[1], buffer, len);
+	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_audio_cmd(eicon_card *ccard, eicon_chan *chan, int cmd, u_char *value)
+{
+	u_char buf[6];
+	struct enable_dtmf_s *dtmf_buf = (struct enable_dtmf_s *)buf;
+
+	memset(buf, 0, 6);
+	switch(cmd) {
+		case ISDN_AUDIO_SETDD:
+			if (value[0]) {
+				dtmf_buf->tone = (__u16) (value[1] * 5);
+				dtmf_buf->gap = (__u16) (value[1] * 5);
+				idi_send_udata(ccard, chan,
+					DSP_UDATA_REQUEST_ENABLE_DTMF_RECEIVER,
+					buf, 4);
+			} else {
+				idi_send_udata(ccard, chan,
+					DSP_UDATA_REQUEST_DISABLE_DTMF_RECEIVER,
+					buf, 0);
+			}
+			break;
+	}
+}
+
 void
 idi_parse_udata(eicon_card *ccard, eicon_chan *chan, unsigned char *buffer, int len)
 {
@@ -822,6 +967,9 @@
         {"", "V.21", "V.23", "V.22", "V.22bis", "V.32bis", "V.34",
          "V.8", "Bell 212A", "Bell 103", "V.29 Leased", "V.33 Leased", "V.90",
          "V.21 CH2", "V.27ter", "V.29", "V.33", "V.17"};
+	static u_char dtmf_code[] = {
+	'1','4','7','*','2','5','8','0','3','6','9','#','A','B','C','D'
+	};
 
 	switch (buffer[0]) {
 		case DSP_UDATA_INDICATION_SYNC:
@@ -863,6 +1011,17 @@
 			if (DebugVar & 8)
   				printk(KERN_DEBUG"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]]);
+			cmd.driver = ccard->myid;
+			cmd.command = ISDN_STAT_AUDIO;
+			cmd.parm.num[0] = ISDN_AUDIO_DTMF;
+			cmd.parm.num[1] = dtmf_code[buffer[1]];
+			cmd.arg = chan->No;
+			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]);
@@ -887,7 +1046,7 @@
 	
 	if ((DebugVar & 128) || 
 	   ((DebugVar & 16) && (ind->Ind != 8))) {
-        	printk(KERN_DEBUG "idi_hdl: Ch%d: Ind=%d Id=%d Ch=%d MInd=%d MLen=%d Len=%d\n", chan->No,
+        	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);
 	}
 
@@ -921,6 +1080,9 @@
 				cmd.command = ISDN_STAT_DHUP;
 				ccard->interface.statcallb(&cmd);
 				eicon_idi_listen_req(ccard, chan);
+#ifdef CONFIG_ISDN_TTY_FAX
+				chan->fax = 0;
+#endif
 				break;
 			case INDICATE_IND:
 				if (DebugVar & 8)
@@ -994,9 +1156,17 @@
 					cmd.command = ISDN_STAT_DCONN;
 					cmd.arg = chan->No;
 					ccard->interface.statcallb(&cmd);
-					idi_do_req(ccard, chan, IDI_N_CONNECT, 1);
+					if (chan->l2prot != ISDN_PROTO_L2_FAX) {
+						idi_do_req(ccard, chan, IDI_N_CONNECT, 1);
+					}
+#ifdef CONFIG_ISDN_TTY_FAX
+					else {
+						if (chan->fax)
+							chan->fax->phase = ISDN_FAX_PHASE_A;
+					}
+#endif
 				} else
-				idi_hangup(ccard, chan);
+					idi_hangup(ccard, chan);
 				break;
 			case CALL_CON:
 				if (DebugVar & 8)
@@ -1009,6 +1179,12 @@
 					ccard->interface.statcallb(&cmd);
 					idi_do_req(ccard, chan, ASSIGN, 1); 
 					idi_do_req(ccard, chan, IDI_N_CONNECT, 1);
+#ifdef CONFIG_ISDN_TTY_FAX
+					if (chan->l2prot == ISDN_PROTO_L2_FAX) {
+						if (chan->fax)
+							chan->fax->phase = ISDN_FAX_PHASE_A;
+					}
+#endif
 				} else
 				idi_hangup(ccard, chan);
 				break;
@@ -1038,6 +1214,27 @@
 					chan->fsm_state = EICON_STATE_WMCONN;
 					break;
 				}
+				if (chan->l2prot == ISDN_PROTO_L2_FAX) {
+#ifdef CONFIG_ISDN_TTY_FAX
+					chan->fsm_state = EICON_STATE_ACTIVE;
+					idi_parse_edata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length);
+					if (chan->fax) {
+						if (chan->fax->phase == ISDN_FAX_PHASE_B) {
+							idi_fax_send_header(ccard, chan, 2);
+							cmd.driver = ccard->myid;
+							cmd.command = ISDN_STAT_FAXIND;
+							cmd.arg = chan->No;
+							chan->fax->r_code = ISDN_TTY_FAX_DCS;
+							ccard->interface.statcallb(&cmd);
+						}
+					}
+					else {
+						if (DebugVar & 1)
+							printk(KERN_DEBUG "idi_ind: N_CONNECT_ACK with NULL fax struct, ERROR\n");
+					}
+#endif
+					break;
+				}
 				chan->fsm_state = EICON_STATE_ACTIVE;
 				cmd.driver = ccard->myid;
 				cmd.command = ISDN_STAT_BCONN;
@@ -1048,6 +1245,9 @@
 				if (DebugVar & 16)
   					printk(KERN_DEBUG"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;
+				}
 				if (chan->l2prot == ISDN_PROTO_L2_MODEM) {
 					chan->fsm_state = EICON_STATE_WMCONN;
 					break;
@@ -1065,6 +1265,12 @@
 					idi_do_req(ccard, chan, IDI_N_DISC_ACK, 1);
 					idi_do_req(ccard, chan, REMOVE, 1);
 				}
+#ifdef CONFIG_ISDN_TTY_FAX
+				if (chan->l2prot == ISDN_PROTO_L2_FAX) {
+					idi_parse_edata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length);
+					idi_fax_hangup(ccard, chan);
+				}
+#endif
 				chan->queued = 0;
 				chan->waitq = 0;
 				chan->waitpq = 0;
@@ -1078,6 +1284,12 @@
 			case IDI_N_DISC_ACK:
 				if (DebugVar & 16)
   					printk(KERN_DEBUG"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);
+					idi_fax_hangup(ccard, chan);
+				}
+#endif
 				break; 
 			case IDI_N_DATA_ACK:
 				if (DebugVar & 16)
@@ -1087,12 +1299,23 @@
 				skb_pull(skb, sizeof(eicon_IND) - 1);
 				if (DebugVar & 128)
 					printk(KERN_DEBUG"idi_rcv: Ch%d: %d bytes\n", chan->No, skb->len);
-				ccard->interface.rcvcallb_skb(ccard->myid, chan->No, skb);
-				free_buff = 0; 
+				if (chan->l2prot == ISDN_PROTO_L2_FAX) {
+#ifdef CONFIG_ISDN_TTY_FAX
+					idi_faxdata_rcv(ccard, chan, skb);
+#endif
+				} else {
+					ccard->interface.rcvcallb_skb(ccard->myid, chan->No, skb);
+					free_buff = 0; 
+				}
 				break; 
 			case IDI_N_UDATA:
 				idi_parse_udata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length);
 				break; 
+#ifdef CONFIG_ISDN_TTY_FAX
+			case IDI_N_EDATA:
+				idi_edata_action(ccard, chan, ind->RBuffer.P, ind->RBuffer.length);
+				break; 
+#endif
 			default:
 				if (DebugVar & 8)
 					printk(KERN_WARNING "idi_ind: Ch%d: UNHANDLED NetIndication 0x%02x\n", chan->No, ind->Ind);
@@ -1106,89 +1329,134 @@
 }
 
 void
-idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
+idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack)
 {
-	int j;
-        eicon_RC *ack = (eicon_RC *)skb->data;
-	eicon_chan *chan;
 	isdn_ctrl cmd;
 
-	if ((ack->Rc != ASSIGN_OK) && (ack->Rc != OK)) {
-		if ((chan = ccard->IdTable[ack->RcId]) != NULL) {
-			chan->e.busy = 0;
-			if (DebugVar & 24)
-				printk(KERN_ERR "eicon_ack: Ch%d: Not OK: Rc=%d Id=%d Ch=%d\n", chan->No, 
-					ack->Rc, ack->RcId, ack->RcCh);
-			if (chan->No == ccard->nchannels) { /* Management */
-				chan->fsm_state = 2;
-			} else {	/* any other channel */
-					/* card reports error: we hangup */
-				idi_hangup(ccard, chan);
-				cmd.driver = ccard->myid;
-				cmd.command = ISDN_STAT_DHUP;
-				cmd.arg = chan->No;
-				ccard->interface.statcallb(&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);
+		return;
+	}
+
+	/* Management Interface */	
+	if (chan->No == ccard->nchannels) {
+		/* Managementinterface: changing state */
+		if (chan->e.Req == 0x04)
+			chan->fsm_state = 1;
+	}
+
+	/* Remove an Id */
+	if (chan->e.Req == REMOVE) {
+		if (ack->Reference != chan->e.ref) {
+			if (DebugVar & 1)
+				printk(KERN_DEBUG "idi_ack: Ch%d: Rc-Ref %d not equal to stored %d\n", chan->No,
+					ack->Reference, chan->e.ref);
 		}
-	} 
-	else {
-		if ((chan = ccard->IdTable[ack->RcId]) != NULL) {
-			if (ack->RcId != ((chan->e.ReqCh) ? chan->e.B2Id : chan->e.D3Id)) {
-				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);
-			} else {	
-				if (chan->No == ccard->nchannels) { /* Management */
-					if (chan->e.Req == 0x04) chan->fsm_state = 1;
-				}
-				if (chan->e.ReqCh) {
-					switch(chan->e.Req & 0x0f) {
-						case IDI_N_MDATA:
-						case IDI_N_DATA:
-							chan->queued -= chan->waitq;
-							if (chan->queued < 0) chan->queued = 0;
-							if ((chan->e.Req & 0x0f) == IDI_N_DATA) {
+		ccard->IdTable[ack->RcId] = NULL;
+		if (DebugVar & 16)
+			printk(KERN_DEBUG "idi_ack: Ch%d: Removed : Id=%d 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;
+		return;
+	}
+
+	/* Signal layer */
+	if (!chan->e.ReqCh) {
+		if (DebugVar & 16)
+			printk(KERN_DEBUG "idi_ack: Ch%d: RC OK Id=%d Ch=%d (ref:%d)\n", chan->No,
+				ack->RcId, ack->RcCh, ack->Reference);
+	} else {
+	/* Network layer */
+		switch(chan->e.Req & 0x0f) {
+			case IDI_N_MDATA:
+			case IDI_N_DATA:
+				if ((chan->e.Req & 0x0f) == IDI_N_DATA) {
+					if (chan->queued) {
+						cmd.driver = ccard->myid;
+						cmd.command = ISDN_STAT_BSENT;
+						cmd.arg = chan->No;
+						cmd.parm.length = chan->waitpq;
+						ccard->interface.statcallb(&cmd);
+					}
+					chan->waitpq = 0;
+#ifdef CONFIG_ISDN_TTY_FAX
+					if (chan->l2prot == ISDN_PROTO_L2_FAX) {
+						if (((chan->queued - chan->waitq) < 1) &&
+						    (chan->fax2.Eop)) {
+							chan->fax2.Eop = 0;
+							if (chan->fax) {
 								cmd.driver = ccard->myid;
-								cmd.command = ISDN_STAT_BSENT;
+								cmd.command = ISDN_STAT_FAXIND;
 								cmd.arg = chan->No;
-								cmd.parm.length = chan->waitpq;
-								chan->waitpq = 0;
+								chan->fax->r_code = ISDN_TTY_FAX_SENT;
 								ccard->interface.statcallb(&cmd);
 							}
-							break;
-						default:
-							if (DebugVar & 16)
-								printk(KERN_DEBUG "idi_ack: Ch%d: RC OK Id=%d Ch=%d (ref:%d)\n", chan->No,
-									ack->RcId, ack->RcCh, ack->Reference);
+							else {
+								if (DebugVar & 1)
+									printk(KERN_DEBUG "idi_ack: Sent with NULL fax struct, ERROR\n");
+							}
+						}
 					}
-				} 
-				else {
-					if (DebugVar & 16)
-						printk(KERN_DEBUG "idi_ack: Ch%d: RC OK Id=%d Ch=%d (ref:%d)\n", chan->No,
-							ack->RcId, ack->RcCh, ack->Reference);
+#endif
 				}
+				chan->queued -= chan->waitq;
+				if (chan->queued < 0) chan->queued = 0;
+				break;
+			default:
+				if (DebugVar & 16)
+					printk(KERN_DEBUG "idi_ack: Ch%d: RC OK Id=%d Ch=%d (ref:%d)\n", chan->No,
+						ack->RcId, ack->RcCh, ack->Reference);
+		}
+	}
+}
 
-				if (chan->e.Req == REMOVE) {
-					if (ack->Reference == chan->e.ref) {
-						ccard->IdTable[ack->RcId] = NULL;
-						if (DebugVar & 16)
-							printk(KERN_DEBUG "idi_ack: Ch%d: Removed : Id=%d 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;
-					}
-					else {
-						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);
-					}
-				}
-				chan->e.busy = 0;
+void
+idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
+{
+	int j;
+        eicon_RC *ack = (eicon_RC *)skb->data;
+	eicon_chan *chan;
+	isdn_ctrl cmd;
+	int dCh = -1;
+
+	if ((chan = ccard->IdTable[ack->RcId]) != NULL)
+		dCh = chan->No;
+	
+
+	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);
+			break;
+		case READY_INT:
+		case TIMER_INT:
+			/* we do nothing here */
+			break;
+
+		case OK:
+			if (!chan) {
+				if (DebugVar & 1)
+					printk(KERN_ERR "idi_ack: Ch%d: OK on chan without Id\n", dCh);
+				break;
+			}
+			idi_handle_ack_ok(ccard, chan, ack);
+			break;
+
+		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);
 			}
-		}
-		else {
 			for(j = 0; j < ccard->nchannels + 1; j++) {
 				if (ccard->bch[j].e.ref == ack->Reference) {
 					if (!ccard->bch[j].e.ReqCh) 
@@ -1199,7 +1467,7 @@
 					ccard->bch[j].e.busy = 0;
 					ccard->bch[j].e.ref = 0;
 					if (DebugVar & 16)
-						printk(KERN_DEBUG"idi_ack: Ch%d: Id %d assigned (%s)\n", j, 
+						printk(KERN_DEBUG"idi_ack: Ch%d: Id %x assigned (%s)\n", j, 
 							ack->RcId, (ccard->bch[j].e.ReqCh)? "Net":"Sig");
 					break;
 				}
@@ -1209,14 +1477,40 @@
 					printk(KERN_DEBUG"idi_ack: Ch??: ref %d not found for Id %d\n", 
 						ack->Reference, ack->RcId);
 			}
-		}
+			break;
+
+		case OUT_OF_RESOURCES:
+		case UNKNOWN_COMMAND:
+		case WRONG_COMMAND:
+		case WRONG_ID:
+		case WRONG_CH:
+		case UNKNOWN_IE:
+		case WRONG_IE:
+		default:
+			chan->e.busy = 0;
+			if (DebugVar & 24)
+				printk(KERN_ERR "eicon_ack: Ch%d: Not OK: Rc=%d Id=%d Ch=%d\n", dCh, 
+					ack->Rc, ack->RcId, ack->RcCh);
+			if (dCh == ccard->nchannels) { /* Management */
+				chan->fsm_state = 2;
+			} else if (dCh >= 0) {
+					/* any other channel */
+					/* card reports error: we hangup */
+				idi_hangup(ccard, chan);
+				cmd.driver = ccard->myid;
+				cmd.command = ISDN_STAT_DHUP;
+				cmd.arg = chan->No;
+				ccard->interface.statcallb(&cmd);
+			}
 	}
-  dev_kfree_skb(skb);
-  eicon_schedule_tx(ccard);
+	if (chan)
+		chan->e.busy = 0;
+	dev_kfree_skb(skb);
+	eicon_schedule_tx(ccard);
 }
 
 int
-idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb)
+idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb, int que)
 {
         struct sk_buff *xmit_skb;
         struct sk_buff *skb2;
@@ -1240,6 +1534,7 @@
 		return 0;
 	if (DebugVar & 128)
 		printk(KERN_DEBUG"idi_snd: Ch%d: %d bytes\n", chan->No, len);
+
 	save_flags(flags);
 	cli();
 	while(offset < len) {
@@ -1249,10 +1544,14 @@
 	        xmit_skb = alloc_skb(plen + sizeof(eicon_REQ), GFP_ATOMIC);
         	skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC);
 
-	        if ((!skb) || (!skb2)) {
+	        if ((!xmit_skb) || (!skb2)) {
 			restore_flags(flags);
 			if (DebugVar & 1)
-	        	        printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed\n", chan->No);
+	        	        printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed in send_data()\n", chan->No);
+			if (xmit_skb) 
+				dev_kfree_skb(skb);
+			if (skb2) 
+				dev_kfree_skb(skb2);
                 	return -ENOMEM;
 	        }
 
@@ -1278,7 +1577,8 @@
 
 		offset += plen;
 	}
-	chan->queued += len;
+	if (que)
+		chan->queued += len;
 	restore_flags(flags);
 	eicon_schedule_tx(card);
         dev_kfree_skb(skb);
@@ -1303,7 +1603,11 @@
 
         if ((!skb) || (!skb2)) {
 		if (DebugVar & 1)
-			printk(KERN_WARNING "idi_err: alloc_skb failed\n");
+			printk(KERN_WARNING "idi_err: alloc_skb failed in manage_assign()\n");
+		if (skb) 
+			dev_kfree_skb(skb);
+		if (skb2) 
+			dev_kfree_skb(skb2);
                 return -ENOMEM;
         }
 
@@ -1342,7 +1646,11 @@
 
         if ((!skb) || (!skb2)) {
 		if (DebugVar & 1)
-                	printk(KERN_WARNING "idi_err: alloc_skb failed\n");
+                	printk(KERN_WARNING "idi_err: alloc_skb failed in manage_remove()\n");
+		if (skb) 
+			dev_kfree_skb(skb);
+		if (skb2) 
+			dev_kfree_skb(skb2);
                 return -ENOMEM;
         }
 
@@ -1379,7 +1687,8 @@
 
         chan = &(card->bch[card->nchannels]);
 
-	if (chan->e.D3Id) return -EBUSY;
+	if (chan->e.D3Id)
+		return -EBUSY;
 	chan->e.D3Id = 1;
 	while((skb2 = skb_dequeue(&chan->e.X)))
 		dev_kfree_skb(skb2);
@@ -1409,6 +1718,7 @@
 		return -ENOMEM;
 	}
 	if (copy_from_user(manbuf, mb, sizeof(eicon_manifbuf))) {
+		kfree(manbuf);
 		chan->e.D3Id = 0;
 		return -EFAULT;
 	}
@@ -1418,7 +1728,11 @@
 
         if ((!skb) || (!skb2)) {
 		if (DebugVar & 1)
-                	printk(KERN_WARNING "idi_err_manif: alloc_skb failed\n");
+                	printk(KERN_WARNING "idi_err_manif: alloc_skb failed in manage()\n");
+		if (skb) 
+			dev_kfree_skb(skb);
+		if (skb2) 
+			dev_kfree_skb(skb2);
 		kfree(manbuf);
 		chan->e.D3Id = 0;
                 return -ENOMEM;
@@ -1464,11 +1778,13 @@
 	}
 
 	if ((ret = eicon_idi_manage_remove(card))) {
+		kfree(manbuf);
 		chan->e.D3Id = 0;
 		return(ret);
 	}
 
 	if (copy_to_user(mb, manbuf, sizeof(eicon_manifbuf))) {
+		kfree(manbuf);
 		chan->e.D3Id = 0;
 		return -EFAULT;
 	}
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/eicon/eicon_idi.h linux/drivers/isdn/eicon/eicon_idi.h
--- v2.3.13/linux/drivers/isdn/eicon/eicon_idi.h	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/eicon/eicon_idi.h	Sun Aug 15 11:49:08 1999
@@ -1,4 +1,4 @@
-/* $Id: eicon_idi.h,v 1.4 1999/03/29 11:19:44 armin Exp $
+/* $Id: eicon_idi.h,v 1.6 1999/07/25 15:12:04 armin Exp $
  *
  * ISDN lowlevel-module for the Eicon.Diehl active cards.
  * IDI-Interface
@@ -21,6 +21,15 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon_idi.h,v $
+ * Revision 1.6  1999/07/25 15:12:04  armin
+ * fix of some debug logs.
+ * enabled ISA-cards option.
+ *
+ * Revision 1.5  1999/07/11 17:16:26  armin
+ * Bugfixes in queue handling.
+ * Added DSP-DTMF decoder functions.
+ * Reorganized ack_handler.
+ *
  * Revision 1.4  1999/03/29 11:19:44  armin
  * I/O stuff now in seperate file (eicon_io.c)
  * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
@@ -45,6 +54,7 @@
 #ifndef IDI_H
 #define IDI_H
 
+#include <linux/config.h>
 
 #define ASSIGN  0x01
 #define REMOVE  0xff
@@ -232,6 +242,12 @@
   __u8 B[1];                            /* buffer space for Req,Ind and Rc */
 } eicon_pr_ram;
 
+typedef struct {
+	__u8		*Data;
+	unsigned int	Size;
+	unsigned int	Len;
+	__u8		*Next;
+} eicon_OBJBUFFER;
 
 extern int idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer);
 extern int idi_hangup(eicon_card *card, eicon_chan *chan);
@@ -243,6 +259,11 @@
 extern void idi_handle_ack(eicon_card *card, struct sk_buff *skb);
 extern void idi_handle_ind(eicon_card *card, struct sk_buff *skb);
 extern int eicon_idi_manage(eicon_card *card, eicon_manifbuf *mb);
-extern int idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb);
+extern int idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb, int que);
+extern void idi_audio_cmd(eicon_card *ccard, eicon_chan *chan, int cmd, u_char *value);
+#ifdef CONFIG_ISDN_TTY_FAX
+extern void idi_fax_cmd(eicon_card *card, eicon_chan *chan);
+extern int idi_faxdata_send(eicon_card *ccard, eicon_chan *chan, struct sk_buff *skb);
+#endif
 
 #endif
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/eicon/eicon_io.c linux/drivers/isdn/eicon/eicon_io.c
--- v2.3.13/linux/drivers/isdn/eicon/eicon_io.c	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/eicon/eicon_io.c	Sun Aug 15 11:49:08 1999
@@ -1,4 +1,4 @@
-/* $Id: eicon_io.c,v 1.1 1999/03/29 11:19:45 armin Exp $
+/* $Id: eicon_io.c,v 1.2 1999/07/25 15:12:05 armin Exp $
  *
  * ISDN low-level module for Eicon.Diehl active ISDN-Cards.
  * Code for communicating with hardware.
@@ -24,6 +24,10 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon_io.c,v $
+ * Revision 1.2  1999/07/25 15:12:05  armin
+ * fix of some debug logs.
+ * enabled ISA-cards option.
+ *
  * Revision 1.1  1999/03/29 11:19:45  armin
  * I/O stuff now in seperate file (eicon_io.c)
  * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
@@ -32,6 +36,7 @@
  */
 
 
+#include <linux/config.h>
 #include "eicon.h"
 
 void
@@ -57,7 +62,7 @@
 						break;
 					default: 
 						printk(KERN_ERR "idi: Indication for unknown channel Ind=%d Id=%d\n", ind->Ind, ind->IndId);
-						printk(KERN_DEBUG "idi_hdl: Ch??: Ind=%d Id=%d Ch=%d MInd=%d MLen=%d Len=%d\n",
+						printk(KERN_DEBUG "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);
 				}
 			}
@@ -303,6 +308,7 @@
         }
 
 	switch(ccard->type) {
+#ifdef CONFIG_ISDN_DRV_EICON_ISA
 		case EICON_CTYPE_S:
 		case EICON_CTYPE_SX:
 		case EICON_CTYPE_SCOM:
@@ -314,6 +320,7 @@
 			scom = 0;
 			prram = (eicon_pr_ram *)isa_card->shmem;
 			break;
+#endif
 		case EICON_CTYPE_MAESTRAP:
 			scom = 0;
         		ram = (char *)pci_card->PCIram;
@@ -434,7 +441,7 @@
 			chan->e.busy = 1; 
 			restore_flags(flags);
 			if (DebugVar & 32)
-	                	printk(KERN_DEBUG "eicon: Req=%x Id=%x Ch=%x Len=%x Ref=%d\n", 
+	                	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,
@@ -510,6 +517,7 @@
 	isa_card = &ccard->hwif.isa;
 
 	switch(ccard->type) {
+#ifdef CONFIG_ISDN_DRV_EICON_ISA
 		case EICON_CTYPE_S:
 		case EICON_CTYPE_SX:
 		case EICON_CTYPE_SCOM:
@@ -523,6 +531,7 @@
 			prram = (eicon_pr_ram *)isa_card->shmem;
 			irqprobe = &isa_card->irqprobe;
 			break;
+#endif
 		case EICON_CTYPE_MAESTRAP:
 			scom = 0;
 			ram = (char *)pci_card->PCIram;
@@ -546,6 +555,7 @@
 
 	if (*irqprobe) {
 		switch(ccard->type) {
+#ifdef CONFIG_ISDN_DRV_EICON_ISA
 			case EICON_CTYPE_S:
 			case EICON_CTYPE_SX:
 			case EICON_CTYPE_SCOM:
@@ -563,6 +573,7 @@
 				}
 				(*irqprobe)++;
 				break;
+#endif
 			case EICON_CTYPE_MAESTRAP:
 	        		if (readb(&ram[0x3fe])) { 
         		               	writeb(0, &prram->RcOutput);
@@ -581,6 +592,7 @@
 	}
 
 	switch(ccard->type) {
+#ifdef CONFIG_ISDN_DRV_EICON_ISA
 		case EICON_CTYPE_S:
 		case EICON_CTYPE_SX:
 		case EICON_CTYPE_SCOM:
@@ -592,6 +604,7 @@
 				return;
 			} 
 			break;
+#endif
 		case EICON_CTYPE_MAESTRAP:
 			if (!(readb(&ram[0x3fe]))) { /* card did not interrupt */
 				if (DebugVar & 1)
@@ -629,7 +642,7 @@
 			ack->RcCh = ram_inb(ccard, &com->RcCh);
 			ack->Reference = ccard->ref_in++;
 			if (DebugVar & 64)
-                        	printk(KERN_INFO "eicon: IRQ Rc=%d Id=%d Ch=%d Ref=%d\n",
+                        	printk(KERN_INFO "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);
@@ -652,7 +665,7 @@
 			ind->MLength = ram_inw(ccard, &com->MLength);
 			ind->RBuffer.length = len; 
 			if (DebugVar & 64)
-                        	printk(KERN_INFO "eicon: IRQ Ind=%d Id=%d Ch=%d MInd=%d MLen=%d Len=%d\n",
+                        	printk(KERN_INFO "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);
@@ -679,7 +692,7 @@
 				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=%d Ch=%d Ref=%d\n",
+	                        	printk(KERN_INFO "eicon: IRQ Rc=%d Id=%x Ch=%d Ref=%d\n",
 						Rc,ack->RcId,ack->RcCh,ack->Reference);
                         	ram_outb(ccard, &RcIn->Rc, 0);
 				 skb_queue_tail(&ccard->rackq, skb);
@@ -711,7 +724,7 @@
 				ind->MLength = ram_inw(ccard, &IndIn->MLength);
 				ind->RBuffer.length = len;
 				if (DebugVar & 64)
-	                        	printk(KERN_INFO "eicon: IRQ Ind=%d Id=%d Ch=%d MInd=%d MLen=%d Len=%d\n",
+	                        	printk(KERN_INFO "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);
@@ -728,6 +741,7 @@
 
 	/* clear interrupt */
 	switch(ccard->type) {
+#ifdef CONFIG_ISDN_DRV_EICON_ISA
 		case EICON_CTYPE_QUADRO:
 			writeb(0, isa_card->intack);
 			writeb(0, &com[0x401]);
@@ -738,6 +752,7 @@
 		case EICON_CTYPE_S2M:
 			writeb(0, isa_card->intack);
 			break;
+#endif
 		case EICON_CTYPE_MAESTRAP:
 			writew(MP_IRQ_RESET_VAL, &cfg[MP_IRQ_RESET]);
 			writew(0, &cfg[MP_IRQ_RESET + 2]); 
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/eicon/eicon_isa.c linux/drivers/isdn/eicon/eicon_isa.c
--- v2.3.13/linux/drivers/isdn/eicon/eicon_isa.c	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/eicon/eicon_isa.c	Sun Aug 15 11:49:08 1999
@@ -1,4 +1,4 @@
-/* $Id: eicon_isa.c,v 1.5 1999/04/01 12:48:33 armin Exp $
+/* $Id: eicon_isa.c,v 1.6 1999/07/25 15:12:06 armin Exp $
  *
  * ISDN low-level module for Eicon.Diehl active ISDN-Cards.
  * Hardware-specific code for old ISA cards.
@@ -22,6 +22,10 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon_isa.c,v $
+ * Revision 1.6  1999/07/25 15:12:06  armin
+ * fix of some debug logs.
+ * enabled ISA-cards option.
+ *
  * Revision 1.5  1999/04/01 12:48:33  armin
  * Changed some log outputs.
  *
@@ -46,6 +50,7 @@
  *
  */
 
+#include <linux/config.h>
 #include "eicon.h"
 #include "eicon_isa.h"
 
@@ -53,7 +58,9 @@
 #define release_shmem release_region
 #define request_shmem request_region
 
-char *eicon_isa_revision = "$Revision: 1.5 $";
+char *eicon_isa_revision = "$Revision: 1.6 $";
+
+#ifdef CONFIG_ISDN_DRV_EICON_ISA
 
 /* Mask for detecting invalid IRQ parameter */
 static int eicon_isa_valid_irq[] = {
@@ -430,3 +437,5 @@
 	card->irqprobe = 0;
 	return 0;
 }
+
+#endif /* CONFIG_ISDN_DRV_EICON_ISA */
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/eicon/eicon_mod.c linux/drivers/isdn/eicon/eicon_mod.c
--- v2.3.13/linux/drivers/isdn/eicon/eicon_mod.c	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/eicon/eicon_mod.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: eicon_mod.c,v 1.5 1999/04/01 12:48:35 armin Exp $
+/* $Id: eicon_mod.c,v 1.8 1999/07/25 15:12:08 armin Exp $
  *
  * ISDN lowlevel-module for Eicon.Diehl active cards.
  * 
@@ -26,6 +26,19 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon_mod.c,v $
+ * Revision 1.8  1999/07/25 15:12:08  armin
+ * fix of some debug logs.
+ * enabled ISA-cards option.
+ *
+ * Revision 1.7  1999/07/11 17:16:27  armin
+ * Bugfixes in queue handling.
+ * Added DSP-DTMF decoder functions.
+ * Reorganized ack_handler.
+ *
+ * Revision 1.6  1999/06/09 19:31:26  armin
+ * Wrong PLX size for request_region() corrected.
+ * Added first MCA code from Erik Weber.
+ *
  * Revision 1.5  1999/04/01 12:48:35  armin
  * Changed some log outputs.
  *
@@ -53,14 +66,18 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#ifdef CONFIG_MCA
+#include <linux/mca.h>
+#endif
 
 #include "eicon.h"
 
 #define INCLUDE_INLINE_FUNCS
 
-static eicon_card *cards = (eicon_card *) NULL;
+static eicon_card *cards = (eicon_card *) NULL;   /* glob. var , contains
+                                                     start of card-list   */
 
-static char *eicon_revision = "$Revision: 1.5 $";
+static char *eicon_revision = "$Revision: 1.8 $";
 
 extern char *eicon_pci_revision;
 extern char *eicon_isa_revision;
@@ -75,19 +92,23 @@
 ulong DebugVar;
 
 /* Parameters to be set by insmod */
+#ifdef CONFIG_ISDN_DRV_EICON_ISA
 static int   membase      = -1;
 static int   irq          = -1;
+#endif
 static char *id           = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
 
 MODULE_DESCRIPTION(             "Driver for Eicon.Diehl active ISDN cards");
 MODULE_AUTHOR(                  "Armin Schindler");
 MODULE_SUPPORTED_DEVICE(        "ISDN subsystem");
+MODULE_PARM_DESC(id,   		"ID-String of first card");
+MODULE_PARM(id,           	"s");
+#ifdef CONFIG_ISDN_DRV_EICON_ISA
 MODULE_PARM_DESC(membase,	"Base address of first ISA card");
 MODULE_PARM_DESC(irq,    	"IRQ of first card");
-MODULE_PARM_DESC(id,   		"ID-String of first card");
 MODULE_PARM(membase,    	"i");
 MODULE_PARM(irq,          	"i");
-MODULE_PARM(id,           	"s");
+#endif
 
 char *eicon_ctype_name[] = {
         "ISDN-S",
@@ -291,10 +312,10 @@
 {
 	switch (card->bus) {
 		case EICON_BUS_ISA:
+		case EICON_BUS_MCA:
 		case EICON_BUS_PCI:
 			eicon_io_rcv_dispatch(card);
 			break;
-		case EICON_BUS_MCA:
 		default:
 			if (DebugVar & 1)
 				printk(KERN_WARNING
@@ -307,10 +328,10 @@
 {
 	switch (card->bus) {
 		case EICON_BUS_ISA:
+		case EICON_BUS_MCA:
 		case EICON_BUS_PCI:
 			eicon_io_ack_dispatch(card);
 			break;
-		case EICON_BUS_MCA:
 		default:
 			if (DebugVar & 1)
 				printk(KERN_WARNING
@@ -323,10 +344,10 @@
 {
 	switch (card->bus) {
 		case EICON_BUS_ISA:
+		case EICON_BUS_MCA:
 		case EICON_BUS_PCI:
 			eicon_io_transmit(card);
 			break;
-		case EICON_BUS_MCA:
 		default:
 			if (DebugVar & 1)
 				printk(KERN_WARNING
@@ -356,6 +377,7 @@
 				case EICON_IOCTL_GETMMIO:
 					switch (card->bus) {
 						case EICON_BUS_ISA:
+						case EICON_BUS_MCA:
 							return (int)card->hwif.isa.shmem;
 #if CONFIG_PCI
 						case EICON_BUS_PCI:
@@ -368,11 +390,13 @@
 							       card->bus);
 							ret = -ENODEV;
 					}
+#ifdef CONFIG_ISDN_DRV_EICON_ISA
 				case EICON_IOCTL_SETMMIO:
 					if (card->flags & EICON_FLAGS_LOADED)
 						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)
@@ -386,9 +410,11 @@
 							       card->bus);
 							ret = -ENODEV;
 					}					
+#endif
 				case EICON_IOCTL_GETIRQ:
 					switch (card->bus) {
 						case EICON_BUS_ISA:
+						case EICON_BUS_MCA:
 							return card->hwif.isa.irq;
 #if CONFIG_PCI
 						case EICON_BUS_PCI:
@@ -408,6 +434,7 @@
 						return -EFAULT;
 					switch (card->bus) {
 						case EICON_BUS_ISA:
+						case EICON_BUS_MCA:
 							card->hwif.isa.irq = a;
 							return 0;
 						default:
@@ -417,11 +444,13 @@
 							       card->bus);
 							ret = -ENODEV;
 					}					
+#ifdef CONFIG_ISDN_DRV_EICON_ISA
 				case EICON_IOCTL_LOADBOOT:
 					if (card->flags & EICON_FLAGS_RUNNING)
 						return -EBUSY;  
 					switch (card->bus) {
 						case EICON_BUS_ISA:
+						case EICON_BUS_MCA:
 							ret = eicon_isa_bootload(
 								&(card->hwif.isa),
 								&(((eicon_codebuf *)a)->isa));
@@ -434,11 +463,14 @@
 							ret = -ENODEV;
 					}
 					return ret;
+#endif
+#ifdef CONFIG_ISDN_DRV_EICON_ISA
 				case EICON_IOCTL_LOADISA:
 					if (card->flags & EICON_FLAGS_RUNNING)
 						return -EBUSY;  
 					switch (card->bus) {
 						case EICON_BUS_ISA:
+						case EICON_BUS_MCA:
 							ret = eicon_isa_load(
 								&(card->hwif.isa),
 								&(((eicon_codebuf *)a)->isa));
@@ -465,7 +497,7 @@
 							ret = -ENODEV;
 					}
 					return ret;
-
+#endif
 				case EICON_IOCTL_MANIF:
 					if (!card->flags & EICON_FLAGS_RUNNING)
 						return -ENODEV;
@@ -639,11 +671,6 @@
 		case ISDN_CMD_SETL3:
 			if (!card->flags & EICON_FLAGS_RUNNING)
 				return -ENODEV;
-			if ((c->arg >> 8) != ISDN_PROTO_L3_TRANS) {
-				if (DebugVar & 1)
-					printk(KERN_WARNING "L3 protocol unknown\n");
-				return -1;
-			}
 			if (!(chan = find_channel(card, c->arg & 0x1f)))
 				break;
 			chan->l3prot = (c->arg >> 8);
@@ -678,6 +705,13 @@
 		case ISDN_CMD_UNLOCK:
 			MOD_DEC_USE_COUNT;
 			return 0;
+		case ISDN_CMD_AUDIO:
+			if (!card->flags & EICON_FLAGS_RUNNING)
+				return -ENODEV;
+			if (!(chan = find_channel(card, c->arg & 0x1f)))
+				break;
+			idi_audio_cmd(card, chan, c->arg >> 8, c->parm.num);
+			return 0;
         }
 	
         return -EINVAL;
@@ -753,6 +787,10 @@
 {
         eicon_card *card = eicon_findcard(id);
 	eicon_chan *chan;
+	int ret = 0;
+	int len;
+
+	len = skb->len;
 	
         if (card) {
                 if (!card->flags & EICON_FLAGS_RUNNING) {
@@ -763,9 +801,10 @@
 			dev_kfree_skb(skb);
 			return -ENODEV;
 		}
-		if (chan->fsm_state == EICON_STATE_ACTIVE)
-			return (idi_send_data(card, chan, ack, skb));
-		else {
+		if (chan->fsm_state == EICON_STATE_ACTIVE) {
+				ret = idi_send_data(card, chan, ack, skb, 1);
+			return (ret);
+		} else {
 			dev_kfree_skb(skb);
 			return -ENODEV;
 		}
@@ -787,7 +826,9 @@
 	int i;
 	int j;
 	int qloop;
+#ifdef CONFIG_ISDN_DRV_EICON_ISA
 	char qid[5];
+#endif
         eicon_card *card;
 #if CONFIG_PCI
 	eicon_pci_card *pcic;
@@ -828,12 +869,32 @@
 		card->myid = -1;
 		card->type = Type;
 		switch (Type) {
+#ifdef CONFIG_ISDN_DRV_EICON_ISA
+#if CONFIG_MCA /* only needed for MCA */
+                        case EICON_CTYPE_S:
+                        case EICON_CTYPE_SX:
+                        case EICON_CTYPE_SCOM:
+                                if (membase == -1)
+                                        membase = EICON_ISA_MEMBASE;
+                                if (irq == -1)
+                                        irq = EICON_ISA_IRQ;
+                                card->bus = EICON_BUS_MCA;
+                                card->hwif.isa.card = (void *)card;
+                                card->hwif.isa.shmem = (eicon_isa_shmem *)membase;
+                                card->hwif.isa.master = 1;
+
+                                card->hwif.isa.irq = irq;
+                                card->hwif.isa.type = Type;
+                                card->nchannels = 2;
+                                card->interface.channels = 1;
+                                break;
+#endif /* CONFIG_MCA */
 			case EICON_CTYPE_QUADRO:
 				if (membase == -1)
 					membase = EICON_ISA_MEMBASE;
 				if (irq == -1)
 					irq = EICON_ISA_IRQ;
-				card->bus = EICON_BUS_ISA;
+                                card->bus = EICON_BUS_ISA;
 				card->hwif.isa.card = (void *)card;
 				card->hwif.isa.shmem = (eicon_isa_shmem *)(membase + (i+1) * EICON_ISA_QOFFSET);
 				card->hwif.isa.master = 0;
@@ -868,6 +929,7 @@
 				card->nchannels = 2;
 				card->interface.channels = 1;
 				break;
+#endif
 #if CONFIG_PCI
 			case EICON_CTYPE_MAESTRA:
 				(eicon_pci_card *)pcic = (eicon_pci_card *)membase;
@@ -876,7 +938,10 @@
 					ISDN_FEATURE_L2_V11096 |
 					ISDN_FEATURE_L2_V11019 |
 					ISDN_FEATURE_L2_V11038 |
-					ISDN_FEATURE_L2_MODEM;
+					ISDN_FEATURE_L2_MODEM |
+					ISDN_FEATURE_L2_FAX |
+					ISDN_FEATURE_L3_TRANSDSP |
+					ISDN_FEATURE_L3_FAX;
                                 card->hwif.pci.card = (void *)card;
 				card->hwif.pci.PCIreg = pcic->PCIreg;
 				card->hwif.pci.PCIcfg = pcic->PCIcfg;
@@ -897,7 +962,10 @@
 					ISDN_FEATURE_L2_V11096 |
 					ISDN_FEATURE_L2_V11019 |
 					ISDN_FEATURE_L2_V11038 |
-					ISDN_FEATURE_L2_MODEM;
+					ISDN_FEATURE_L2_MODEM |
+					ISDN_FEATURE_L2_FAX |
+					ISDN_FEATURE_L3_TRANSDSP |
+					ISDN_FEATURE_L3_FAX;
                                 card->hwif.pci.card = (void *)card;
                                 card->hwif.pci.shmem = (eicon_pci_shmem *)pcic->shmem;
 				card->hwif.pci.PCIreg = pcic->PCIreg;
@@ -913,6 +981,7 @@
 				card->interface.channels = 1;
 				break;
 #endif
+#ifdef CONFIG_ISDN_DRV_EICON_ISA
 			case EICON_CTYPE_ISABRI:
 				if (membase == -1)
 					membase = EICON_ISA_MEMBASE;
@@ -932,7 +1001,7 @@
 					membase = EICON_ISA_MEMBASE;
 				if (irq == -1)
 					irq = EICON_ISA_IRQ;
-				card->bus = EICON_BUS_ISA;
+                                card->bus = EICON_BUS_ISA;
 				card->hwif.isa.card = (void *)card;
 				card->hwif.isa.shmem = (eicon_isa_shmem *)membase;
 				card->hwif.isa.master = 1;
@@ -941,6 +1010,7 @@
 				card->nchannels = 30;
 				card->interface.channels = 1;
 				break;
+#endif
 			default:
 				printk(KERN_WARNING "eicon_alloccard: Invalid type %d\n", Type);
 				kfree(card);
@@ -978,15 +1048,21 @@
 eicon_registercard(eicon_card * card)
 {
         switch (card->bus) {
+#ifdef CONFIG_ISDN_DRV_EICON_ISA
 		case EICON_BUS_ISA:
 			/* TODO something to print */
 			break;
+#ifdef CONFIG_MCA
+		case EICON_BUS_MCA:
+			eicon_isa_printpar(&card->hwif.isa);
+			break;
+#endif
+#endif
 		case EICON_BUS_PCI:
 #if CONFIG_PCI
 			eicon_pci_printpar(&card->hwif.pci); 
 			break;
 #endif
-		case EICON_BUS_MCA:
 		default:
 			if (DebugVar & 1)
 				printk(KERN_WARNING
@@ -1015,15 +1091,19 @@
         cmd.driver = card->myid;
         card->interface.statcallb(&cmd);
         switch (card->bus) {
+#ifdef CONFIG_ISDN_DRV_EICON_ISA
 		case EICON_BUS_ISA:
+#ifdef CONFIG_MCA
+		case EICON_BUS_MCA:
+#endif
 			eicon_isa_release(&card->hwif.isa);
 			break;
+#endif
 		case EICON_BUS_PCI:
 #if CONFIG_PCI
 			eicon_pci_release(&card->hwif.pci);
 			break;
 #endif
-		case EICON_BUS_MCA:
 		default:
 			if (DebugVar & 1)
 				printk(KERN_WARNING
@@ -1050,9 +1130,11 @@
 	int added = 0;
 	int failed = 0;
 
+#ifdef CONFIG_ISDN_DRV_EICON_ISA
 	if (!Type) /* ISA */
 		if ((Type = eicon_isa_find_card(membase, irq, id)) < 0)
 			return 0;
+#endif
 	eicon_alloccard(Type, membase, irq, id);
         p = cards;
         while (p) {
@@ -1063,11 +1145,14 @@
 			 */
 			added++;
 			switch (p->bus) {
+#ifdef CONFIG_ISDN_DRV_EICON_ISA
 				case EICON_BUS_ISA:
+				case EICON_BUS_MCA:
 					if (eicon_registercard(p))
 						break;
 					registered = 1;
 					break;
+#endif
 				case EICON_BUS_PCI:
 #if CONFIG_PCI
 					if (eicon_registercard(p))
@@ -1075,7 +1160,6 @@
 					registered = 1;
 					break;
 #endif
-				case EICON_BUS_MCA:
 				default:
 					if (DebugVar & 1)
 						printk(KERN_WARNING
@@ -1119,7 +1203,7 @@
 __initfunc(int
 eicon_init(void))
 {
-	int tmp = 0;
+	int card_count = 0;
 	int release = 0;
 	char tmprev[50];
 
@@ -1130,10 +1214,18 @@
 	printk("%s/", eicon_getrev(tmprev));
 	release += getrel(tmprev);
 	strcpy(tmprev, eicon_pci_revision);
+#if CONFIG_PCI
 	printk("%s/", eicon_getrev(tmprev));
+#else
+	printk("---/");
+#endif
 	release += getrel(tmprev);
 	strcpy(tmprev, eicon_isa_revision);
+#ifdef CONFIG_ISDN_DRV_EICON_ISA
 	printk("%s/", eicon_getrev(tmprev));
+#else
+	printk("---/");
+#endif
 	release += getrel(tmprev);
 	strcpy(tmprev, eicon_idi_revision);
 	printk("%s\n", eicon_getrev(tmprev));
@@ -1142,18 +1234,46 @@
         printk(KERN_INFO "%s Release: %s.%s\n", DRIVERNAME,
 		DRIVERRELEASE, tmprev);
 
-	tmp = eicon_addcard(0, membase, irq, id);
+#ifdef CONFIG_ISDN_DRV_EICON_ISA
+#ifdef CONFIG_MCA
+	/* Check if we have MCA-bus */
+        if (!MCA_bus)
+                {
+                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);
+               	if (!eicon_mca_find_card(0, membase, irq, id))
+                       card_count++;
+        };
+#else
+	card_count = eicon_addcard(0, membase, irq, id);
+#endif /* CONFIG_MCA */
+#endif /* CONFIG_ISDN_DRV_EICON_ISA */
+ 
 #if CONFIG_PCI
-	tmp += eicon_pci_find_card(id);
+	card_count += eicon_pci_find_card(id);
 #endif
         if (!cards) {
 #ifdef MODULE
+#ifndef CONFIG_PCI
+#ifndef CONFIG_ISDN_DRV_EICON_ISA
+                printk(KERN_INFO "Eicon: Driver is neither ISA nor PCI compiled !\n");
+#else
                 printk(KERN_INFO "Eicon: No cards defined, driver not loaded !\n");
 #endif
+#else
+                printk(KERN_INFO "Eicon: No PCI-cards found, driver not loaded !\n");
+#endif
+#endif
 		return -ENODEV;
 
 	} else
-		printk(KERN_INFO "Eicon: %d card%s added\n", tmp, (tmp>1)?"s":"");
+		printk(KERN_INFO "Eicon: %d card%s added\n", card_count, 
+                       (card_count>1)?"s":"");
         /* No symbols to export, hide all symbols */
         EXPORT_NO_SYMBOLS;
         return 0;
@@ -1166,6 +1286,13 @@
         eicon_card *card = cards;
         eicon_card *last;
         while (card) {
+#ifdef CONFIG_MCA
+        	if (MCA_bus)
+                        {
+                        mca_mark_as_unused (card->mca_slot);
+                        mca_set_adapter_procfn(card->mca_slot, NULL, NULL);
+                        };
+#endif
                 unregister_card(card); 
                 card = card->next;
         }
@@ -1178,7 +1305,7 @@
         printk(KERN_INFO "%s unloaded\n", DRIVERNAME);
 }
 
-#else
+#else /* no module */
 __initfunc(void
 eicon_setup(char *str, int *ints))
 {
@@ -1207,4 +1334,173 @@
        		printk(KERN_INFO "eicon: membase=0x%x irq=%d id=%s\n", membase, irq, id);
 	}
 }
-#endif
+#endif /* MODULE */
+
+#ifdef CONFIG_ISDN_DRV_EICON_ISA
+#ifdef CONFIG_MCA
+
+struct eicon_mca_adapters_struct {
+	char * name;
+	int adf_id;
+};
+/* possible MCA-brands of eicon cards                                         */
+struct eicon_mca_adapters_struct eicon_mca_adapters[] = {
+	{ "ISDN-P/2 Adapter", 0x6abb },
+	{ "ISDN-[S|SX|SCOM]/2 Adapter", 0x6a93 },
+	{ "DIVA /MCA", 0x6336 },
+	{ NULL, 0 },
+};
+
+int eicon_mca_find_card(int type,          /* type-idx of eicon-card          */
+                        int membase,
+		        int irq,
+			char * id)         /* name of eicon-isdn-dev          */
+{
+	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);
+	/* find a no-driver-assigned eicon card                               */
+	for (j=0; eicon_mca_adapters[j].adf_id != 0; j++) 
+		{
+		for ( curr_slot=0; curr_slot<=MCA_MAX_SLOT_NR; curr_slot++) 
+			{
+			curr_slot = mca_find_unused_adapter(
+				         eicon_mca_adapters[j].adf_id, curr_slot);
+			if (curr_slot != MCA_NOTFOUND) 
+				{
+				/* check if pre-set parameters match
+				   these of the card, check cards memory      */
+				if (!(int) eicon_mca_probe(curr_slot,
+                                                           j,
+                                                	   membase, 
+                                                           irq,
+                                                           id))
+					{
+					return 0;
+					/* means: adapter parms did match     */
+					};
+			};
+			break;
+			/* MCA_NOTFOUND-branch: no matching adapter of
+			   THIS flavor found, next flavor                     */
+
+            	};
+	};
+	/* all adapter flavors checked without match, finito with:            */
+        return ENODEV;
+};
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ *  stolen from 3c523.c/elmc_getinfo, ewe, 10.5.1999 
+ */
+int eicon_info(char * buf, int slot, void *d)
+{
+	int len = 0;
+	struct eicon_card *dev;
+
+        dev = (struct eicon_card *) d;
+
+	if (dev == NULL)
+		return len;
+	len += sprintf(buf+len, "eicon ISDN adapter, type %d.\n",dev->type);
+	len += sprintf(buf+len, "IRQ: %d\n", dev->hwif.isa.irq);
+	len += sprintf(buf+len, "MEMBASE: %#lx\n", (unsigned long)dev->hwif.isa.shmem);
+
+	return len;
+};
+
+int eicon_mca_probe(int slot,  /* slot-nr where the card was detected         */
+		    int a_idx, /* idx-nr of probed card in eicon_mca_adapters */
+                    int membase,
+                    int irq,
+		    char * id) /* name of eicon-isdn-dev                      */
+{				
+	unsigned char adf_pos0;
+	int cards_irq, cards_membase, cards_io;
+	int type = EICON_CTYPE_S;
+	int irq_array[]={0,3,4,2};
+	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);
+	switch (a_idx) {
+		case 0:                /* P/2-Adapter (== PRI/S2M ? )         */
+			cards_membase= 0xC0000+((adf_pos0>>4)*0x4000);
+			if (membase == -1) { 
+				membase = cards_membase;
+			} else {
+				if (membase != cards_membase)
+					return ENODEV;
+			};
+			cards_irq=irq_array[((adf_pos0 & 0xC)>>2)];
+			if (irq == -1) { 
+				irq = cards_irq;
+			} else {
+				if (irq != irq)
+					return ENODEV;
+			};
+			cards_io= 0xC00 + ((adf_pos0>>4)*0x10);
+			type = EICON_CTYPE_ISAPRI; 
+			break;
+
+		case 1:                /* [S|SX|SCOM]/2                       */
+			cards_membase= 0xC0000+((adf_pos0>>4)*0x2000);
+			if (membase == -1) { 
+				membase = cards_membase;
+			} else {
+				if (membase != cards_membase)
+					return ENODEV;
+			};
+			cards_irq=irq_array[((adf_pos0 & 0xC)>>2)];
+			if (irq == -1) { 
+				irq = cards_irq;
+			} else {
+				if (irq != cards_irq)
+					return ENODEV;
+			};
+
+			cards_io= 0xC00 + ((adf_pos0>>4)*0x10);
+			type = EICON_CTYPE_SCOM; 
+		 	break;	
+
+		case 2:                /* DIVA/MCA                            */
+			cards_io = 0x200+ ((adf_pos0>>4)* 0x20);
+			cards_irq = irq_array1[(adf_pos0 & 0x7)];
+			if (irq == -1) { 
+				irq = cards_irq;
+			} else {
+				if (irq != irq)
+					return ENODEV;
+			};
+			type = 0; 
+			break;
+		default:
+			return  ENODEV;
+	};
+	/* Uebereinstimmung vorgegebener membase & irq */
+	if ( 1 == eicon_addcard(type, membase, irq, id)) { 
+		mca_set_adapter_name(slot, eicon_mca_adapters[a_idx].name);
+  		mca_set_adapter_procfn(slot, (MCA_ProcFn) eicon_info, cards);
+
+        	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_slot+1);
+		return  0 ; /* eicon_addcard hat eine Karte zugefuegt */
+	} else {
+		return ENODEV;
+	};
+};
+#endif /* CONFIG_MCA */
+#endif /* CONFIG_ISDN_DRV_EICON_ISA */
+
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/eicon/eicon_pci.c linux/drivers/isdn/eicon/eicon_pci.c
--- v2.3.13/linux/drivers/isdn/eicon/eicon_pci.c	Wed May 26 16:55:40 1999
+++ linux/drivers/isdn/eicon/eicon_pci.c	Sun Aug 15 11:49:08 1999
@@ -1,4 +1,4 @@
-/* $Id: eicon_pci.c,v 1.6 1999/04/01 12:48:37 armin Exp $
+/* $Id: eicon_pci.c,v 1.9 1999/08/11 21:01:11 keil Exp $
  *
  * ISDN low-level module for Eicon.Diehl active ISDN-Cards.
  * Hardware-specific code for PCI cards.
@@ -26,6 +26,16 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon_pci.c,v $
+ * Revision 1.9  1999/08/11 21:01:11  keil
+ * new PCI codefix
+ *
+ * Revision 1.8  1999/08/10 16:02:20  calle
+ * struct pci_dev changed in 2.3.13. Made the necessary changes.
+ *
+ * Revision 1.7  1999/06/09 19:31:29  armin
+ * Wrong PLX size for request_region() corrected.
+ * Added first MCA code from Erik Weber.
+ *
  * Revision 1.6  1999/04/01 12:48:37  armin
  * Changed some log outputs.
  *
@@ -61,7 +71,7 @@
 #include "eicon_pci.h"
 
 
-char *eicon_pci_revision = "$Revision: 1.6 $";
+char *eicon_pci_revision = "$Revision: 1.9 $";
 
 #if CONFIG_PCI	         /* intire stuff is only for PCI */
 
@@ -136,8 +146,8 @@
           aparms->type = EICON_CTYPE_MAESTRA;
 
           aparms->irq = pdev->irq;
-          preg = pdev->base_address[2] & 0xfffffffc;
-          pcfg = pdev->base_address[1] & 0xffffff80;
+          preg = get_pcibase(pdev, 2) & 0xfffffffc;
+          pcfg = get_pcibase(pdev, 1) & 0xffffff80;
 
 #ifdef EICON_PCI_DEBUG
           printk(KERN_DEBUG "eicon_pci: irq=%d\n", aparms->irq);
@@ -158,9 +168,9 @@
          printk(KERN_INFO "Eicon: DIVA Server PRI/PCI detected !\n");
           aparms->type = EICON_CTYPE_MAESTRAP; /*includes 9M,30M*/
           aparms->irq = pdev->irq;
-          pram = pdev->base_address[0] & 0xfffff000;
-          preg = pdev->base_address[2] & 0xfffff000;
-          pcfg = pdev->base_address[4] & 0xfffff000;
+          pram = get_pcibase(pdev, 0) & 0xfffff000;
+          preg = get_pcibase(pdev, 2) & 0xfffff000;
+          pcfg = get_pcibase(pdev, 4) & 0xfffff000;
 
 #ifdef EICON_PCI_DEBUG
           printk(KERN_DEBUG "eicon_pci: irq=%d\n", aparms->irq);
@@ -194,12 +204,13 @@
 			} else {
 				request_region(aparms->PCIreg, 0x20, "eicon reg");
 			}
-			if (check_region((aparms->PCIcfg), 0x100)) {
+			if (check_region((aparms->PCIcfg), 0x80)) {
 				printk(KERN_WARNING "eicon_pci: cfg port already in use !\n");
 				aparms->PCIcfg = 0;
+				release_region(aparms->PCIreg, 0x20);
 				break;	
 			} else {
-				request_region(aparms->PCIcfg, 0x100, "eicon cfg");
+				request_region(aparms->PCIcfg, 0x80, "eicon cfg");
 			}
 			break;
     		case PCI_MAESTRAQ:
@@ -327,7 +338,7 @@
 				outw(0, card->PCIreg + M_DATA);
 
 				release_region(card->PCIreg, 0x20);
-				release_region(card->PCIcfg, 0x100);
+				release_region(card->PCIcfg, 0x80);
 				break;
                 	case EICON_CTYPE_MAESTRAQ:
 	                case EICON_CTYPE_MAESTRAQ_U:
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/Makefile linux/drivers/isdn/hisax/Makefile
--- v2.3.13/linux/drivers/isdn/hisax/Makefile	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/hisax/Makefile	Thu Aug 12 09:42:33 1999
@@ -25,13 +25,11 @@
 endif
 
 ISAC_OBJ :=
-ARCOFI_OBJ :=
 HSCX_OBJ :=
 ISAR_OBJ :=
 HFC_OBJ :=
 HFC_2BDS0 :=
-RAWHDLC_OBJ :=
-
+JADE_OBJ :=
 ifeq ($(CONFIG_HISAX_16_0),y)
 	 O_OBJS += teles0.o
 	 ISAC_OBJ := isac.o
@@ -78,7 +76,6 @@
 	 O_OBJS += elsa.o
 	 ISAC_OBJ := isac.o
 	 HSCX_OBJ := hscx.o
-	 ARCOFI_OBJ := arcofi.o
 endif
 
 ifeq ($(CONFIG_HISAX_IX1MICROR2),y)
@@ -127,16 +124,15 @@
 ifeq ($(CONFIG_HISAX_NETJET),y)
 	 O_OBJS += netjet.o
 	 ISAC_OBJ := isac.o
-#	 RAWHDLC_OBJ := rawhdlc.o
 endif
 
-ifeq ($(CONFIG_HISAX_TELES3C),y)
-	 O_OBJS += teles3c.o
+ifeq ($(CONFIG_HISAX_HFCS),y)
+	 O_OBJS += hfcscard.o
 	 HFC_2BDS0 := hfc_2bds0.o
 endif
-ifeq ($(CONFIG_HISAX_AMD7930),y)
-	 O_OBJS += amd7930.o
-	 RAWHDLC_OBJ := rawhdlc.o
+
+ifeq ($(CONFIG_HISAX_HFC_PCI),y)
+	 HFC_2BDS0 += hfc_pci.o
 endif
 
 ifeq ($(CONFIG_HISAX_NICCY),y)
@@ -145,8 +141,45 @@
 	 HSCX_OBJ := hscx.o
 endif
 
-O_OBJS += $(ISAC_OBJ) $(HSCX_OBJ) $(ISAR_OBJ) $(ARCOFI_OBJ) 
-O_OBJS += $(HFC_OBJ) $(HFC_2BDS0) $(RAWHDLC_OBJ) 
+ifeq ($(CONFIG_HISAX_ISURF),y)
+	 O_OBJS += isurf.o
+	 ISAC_OBJ := isac.o
+	 ISAR_OBJ := isar.o
+endif
+
+ifeq ($(CONFIG_HISAX_HSTSAPHIR),y)
+	 O_OBJS += saphir.o
+	 ISAC_OBJ := isac.o
+	 HSCX_OBJ := hscx.o
+endif
+
+ifeq ($(CONFIG_HISAX_BKM_A4T),y)
+	 O_OBJS += bkm_a4t.o
+	 ISAC_OBJ := isac.o
+	 JADE_OBJ := jade.o
+endif
+ifeq ($(CONFIG_HISAX_SCT_QUADRO),y)
+	 O_OBJS += bkm_a8.o
+	 ISAC_OBJ := isac.o
+	 HSCX_OBJ := hscx.o
+endif
+
+ifeq ($(CONFIG_HISAX_GAZEL),y)
+	 O_OBJS += gazel.o
+	 ISAC_OBJ := isac.o
+	 HSCX_OBJ := hscx.o
+endif
+
+# ifeq ($(CONFIG_HISAX_TESTEMU),y)
+#	 O_OBJS += testemu.o
+# endif
+
+ifeq ($(ISAC_OBJ), isac.o)
+	ISAC_OBJ += arcofi.o
+endif
+
+O_OBJS += $(ISAC_OBJ) $(HSCX_OBJ) $(ISAR_OBJ) $(JADE_OBJ)
+O_OBJS += $(HFC_OBJ) $(HFC_2BDS0)
 OX_OBJS += config.o
 
 O_TARGET :=
@@ -164,7 +197,8 @@
 include $(TOPDIR)/Rules.make
 
 MD5FILES += isac.c isdnl1.c isdnl2.c isdnl3.c \
-	    tei.c callc.c cert.c l3dss1.c l3_1tr6.c elsa.c
+	    tei.c callc.c cert.c l3dss1.c l3_1tr6.c \
+	    elsa.c diva.c
 
 CERT = $(shell md5sum -c md5sums.asc >> /dev/null;echo $$?)
 
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/amd7930.c linux/drivers/isdn/hisax/amd7930.c
--- v2.3.13/linux/drivers/isdn/hisax/amd7930.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/isdn/hisax/amd7930.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: amd7930.c,v 1.2 1998/02/12 23:07:10 keil Exp $
+/* $Id: amd7930.c,v 1.3 1999/07/12 21:04:52 keil Exp $
  *
  * HiSax ISDN driver - chip specific routines for AMD 7930
  *
@@ -7,6 +7,10 @@
  *
  *
  * $Log: amd7930.c,v $
+ * Revision 1.3  1999/07/12 21:04:52  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
  * Revision 1.2  1998/02/12 23:07:10  keil
  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
  *
@@ -105,7 +109,7 @@
 #include "rawhdlc.h"
 #include <linux/interrupt.h>
 
-static const char *amd7930_revision = "$Revision: 1.2 $";
+static const char *amd7930_revision = "$Revision: 1.3 $";
 
 #define RCV_BUFSIZE	1024	/* Size of raw receive buffer in bytes */
 #define RCV_BUFBLKS	4	/* Number of blocks to divide buffer into
@@ -734,8 +738,6 @@
 		case CARD_RELEASE:
 			release_amd7930(cs);
 			return(0);
-		case CARD_SETIRQ:
-			return(0);
 		case CARD_INIT:
 			cs->l1cmd = amd7930_l1cmd;
 			amd7930_liu_init(0, &amd7930_liu_callback, (void *)cs);
@@ -747,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.13/linux/drivers/isdn/hisax/arcofi.c linux/drivers/isdn/hisax/arcofi.c
--- v2.3.13/linux/drivers/isdn/hisax/arcofi.c	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/hisax/arcofi.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: arcofi.c,v 1.6 1998/09/30 22:21:56 keil Exp $
+/* $Id: arcofi.c,v 1.7 1999/07/01 08:11:17 keil Exp $
 
  * arcofi.c   Ansteuerung ARCOFI 2165
  *
@@ -7,6 +7,9 @@
  *
  *
  * $Log: arcofi.c,v $
+ * Revision 1.7  1999/07/01 08:11:17  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 1.6  1998/09/30 22:21:56  keil
  * cosmetics
  *
@@ -32,48 +35,120 @@
 #include "hisax.h"
 #include "isdnl1.h"
 #include "isac.h"
+#include "arcofi.h"
 
-int
-send_arcofi(struct IsdnCardState *cs, const u_char *msg, int bc, int receive) {
+#define ARCOFI_TIMER_VALUE	20
+
+static void
+add_arcofi_timer(struct IsdnCardState *cs) {
+	if (test_and_set_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) {
+		del_timer(&cs->dc.isac.arcofitimer);
+	}	
+	init_timer(&cs->dc.isac.arcofitimer);
+	cs->dc.isac.arcofitimer.expires = jiffies + ((ARCOFI_TIMER_VALUE * HZ)/1000);
+	add_timer(&cs->dc.isac.arcofitimer);
+}
+
+static void
+send_arcofi(struct IsdnCardState *cs) {
 	u_char val;
-	long flags;
-	int cnt=30;
 	
-	cs->mon_txp = 0;
-	cs->mon_txc = msg[0];
-	memcpy(cs->mon_tx, &msg[1], cs->mon_txc);
-	switch(bc) {
+	add_arcofi_timer(cs);
+	cs->dc.isac.mon_txp = 0;
+	cs->dc.isac.mon_txc = cs->dc.isac.arcofi_list->len;
+	memcpy(cs->dc.isac.mon_tx, cs->dc.isac.arcofi_list->msg, cs->dc.isac.mon_txc);
+	switch(cs->dc.isac.arcofi_bc) {
 		case 0: break;
-		case 1: cs->mon_tx[1] |= 0x40;
+		case 1: cs->dc.isac.mon_tx[1] |= 0x40;
 			break;
 		default: break;
 	}
-	cs->mocr &= 0x0f;
-	cs->mocr |= 0xa0;
-	test_and_clear_bit(HW_MON1_TX_END, &cs->HW_Flags);
-	if (receive)
-		test_and_clear_bit(HW_MON1_RX_END, &cs->HW_Flags);
-	cs->writeisac(cs, ISAC_MOCR, cs->mocr);
+	cs->dc.isac.mocr &= 0x0f;
+	cs->dc.isac.mocr |= 0xa0;
+	cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
 	val = cs->readisac(cs, ISAC_MOSR);
-	cs->writeisac(cs, ISAC_MOX1, cs->mon_tx[cs->mon_txp++]);
-	cs->mocr |= 0x10;
-	cs->writeisac(cs, ISAC_MOCR, cs->mocr);
-	save_flags(flags);
-	sti();
-	while (cnt && !test_bit(HW_MON1_TX_END, &cs->HW_Flags)) {
-		cnt--;
-		udelay(500);
+	cs->writeisac(cs, ISAC_MOX1, cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]);
+	cs->dc.isac.mocr |= 0x10;
+	cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
+}
+
+int
+arcofi_fsm(struct IsdnCardState *cs, int event, void *data) {
+	if (cs->debug & L1_DEB_MONITOR) {
+		debugl1(cs, "arcofi state %d event %d", cs->dc.isac.arcofi_state, event);
 	}
-	if (receive) {
-		while (cnt && !test_bit(HW_MON1_RX_END, &cs->HW_Flags)) {
-			cnt--;
-			udelay(500);
-		}
+	if (event == ARCOFI_TIMEOUT) {
+		cs->dc.isac.arcofi_state = ARCOFI_NOP;
+		test_and_set_bit(FLG_ARCOFI_ERROR, &cs->HW_Flags);
+		wake_up_interruptible(&cs->dc.isac.arcofi_wait);
+ 		return(1);
 	}
-	restore_flags(flags);
-	if (cnt <= 0) {
-		printk(KERN_WARNING"HiSax arcofi monitor timed out\n");
-		debugl1(cs, "HiSax arcofi monitor timed out");
+	switch (cs->dc.isac.arcofi_state) {
+		case ARCOFI_NOP:
+			if (event == ARCOFI_START) {
+				cs->dc.isac.arcofi_list = data;
+				cs->dc.isac.arcofi_state = ARCOFI_TRANSMIT;
+				send_arcofi(cs);
+			}
+			break;
+		case ARCOFI_TRANSMIT:
+			if (event == ARCOFI_TX_END) {
+				if (cs->dc.isac.arcofi_list->receive) {
+					add_arcofi_timer(cs);
+					cs->dc.isac.arcofi_state = ARCOFI_RECEIVE;
+				} else {
+					if (cs->dc.isac.arcofi_list->next) {
+						cs->dc.isac.arcofi_list =
+							cs->dc.isac.arcofi_list->next;
+						send_arcofi(cs);
+					} else {
+						if (test_and_clear_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) {
+							del_timer(&cs->dc.isac.arcofitimer);
+						}
+						cs->dc.isac.arcofi_state = ARCOFI_NOP;
+						wake_up_interruptible(&cs->dc.isac.arcofi_wait);
+					}
+				}
+			}
+			break;
+		case ARCOFI_RECEIVE:
+			if (event == ARCOFI_RX_END) {
+				if (cs->dc.isac.arcofi_list->next) {
+					cs->dc.isac.arcofi_list =
+						cs->dc.isac.arcofi_list->next;
+					cs->dc.isac.arcofi_state = ARCOFI_TRANSMIT;
+					send_arcofi(cs);
+				} else {
+					if (test_and_clear_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) {
+						del_timer(&cs->dc.isac.arcofitimer);
+					}
+					cs->dc.isac.arcofi_state = ARCOFI_NOP;
+					wake_up_interruptible(&cs->dc.isac.arcofi_wait);
+				}
+			}
+			break;
+		default:
+			debugl1(cs, "Arcofi unknown state %x", cs->dc.isac.arcofi_state);
+			return(2);
+	}
+	return(0);
+}
+
+static void
+arcofi_timer(struct IsdnCardState *cs) {
+	arcofi_fsm(cs, ARCOFI_TIMEOUT, NULL);
+}
+
+void
+clear_arcofi(struct IsdnCardState *cs) {
+	if (test_and_clear_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) {
+		del_timer(&cs->dc.isac.arcofitimer);
 	}
-	return(cnt);	
+}
+
+void
+init_arcofi(struct IsdnCardState *cs) {
+	cs->dc.isac.arcofitimer.function = (void *) arcofi_timer;
+	cs->dc.isac.arcofitimer.data = (long) cs;
+	init_timer(&cs->dc.isac.arcofitimer);
 }
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/arcofi.h linux/drivers/isdn/hisax/arcofi.h
--- v2.3.13/linux/drivers/isdn/hisax/arcofi.h	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/hisax/arcofi.h	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: arcofi.h,v 1.3 1998/05/25 12:57:39 keil Exp $
+/* $Id: arcofi.h,v 1.4 1999/07/01 08:11:18 keil Exp $
 
  * arcofi.h   Ansteuerung ARCOFI 2165
  *
@@ -7,6 +7,9 @@
  *
  *
  * $Log: arcofi.h,v $
+ * Revision 1.4  1999/07/01 08:11:18  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 1.3  1998/05/25 12:57:39  keil
  * HiSax golden code from certification, Don't use !!!
  * No leased lines, no X75, but many changes.
@@ -21,4 +24,16 @@
  
 #define ARCOFI_USE	1
 
-extern int send_arcofi(struct IsdnCardState *cs, const u_char *msg, int bc, int receive);
+/* states */
+#define ARCOFI_NOP	0
+#define ARCOFI_TRANSMIT	1
+#define ARCOFI_RECEIVE	2
+/* events */
+#define ARCOFI_START	1
+#define ARCOFI_TX_END	2
+#define ARCOFI_RX_END	3
+#define ARCOFI_TIMEOUT	4
+
+extern int arcofi_fsm(struct IsdnCardState *cs, int event, void *data);
+extern void init_arcofi(struct IsdnCardState *cs);
+extern void clear_arcofi(struct IsdnCardState *cs);
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/asuscom.c linux/drivers/isdn/hisax/asuscom.c
--- v2.3.13/linux/drivers/isdn/hisax/asuscom.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/isdn/hisax/asuscom.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: asuscom.c,v 1.5 1998/11/15 23:54:19 keil Exp $
+/* $Id: asuscom.c,v 1.7 1999/07/12 21:04:53 keil Exp $
 
  * asuscom.c     low level stuff for ASUSCOM NETWORK INC. ISDNLink cards
  *
@@ -8,6 +8,13 @@
  *
  *
  * $Log: asuscom.c,v $
+ * Revision 1.7  1999/07/12 21:04:53  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 1.6  1999/07/01 08:11:18  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 1.5  1998/11/15 23:54:19  keil
  * changes from 2.0
  *
@@ -32,7 +39,7 @@
 
 extern const char *CardType[];
 
-const char *Asuscom_revision = "$Revision: 1.5 $";
+const char *Asuscom_revision = "$Revision: 1.7 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -181,7 +188,7 @@
 asuscom_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u_char val, stat = 0;
+	u_char val;
 
 	if (!cs) {
 		printk(KERN_WARNING "ISDNLink: Spurious interrupt!\n");
@@ -189,16 +196,12 @@
 	}
 	val = readreg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_ISTA + 0x40);
       Start_HSCX:
-	if (val) {
+	if (val)
 		hscx_int_main(cs, val);
-		stat |= 1;
-	}
 	val = readreg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_ISTA);
       Start_ISAC:
-	if (val) {
+	if (val)
 		isac_interrupt(cs, val);
-		stat |= 2;
-	}
 	val = readreg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_ISTA + 0x40);
 	if (val) {
 		if (cs->debug & L1_DEB_HSCX)
@@ -211,23 +214,19 @@
 			debugl1(cs, "ISAC IntStat after IntRoutine");
 		goto Start_ISAC;
 	}
-	if (stat & 1) {
-		writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK, 0xFF);
-		writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK + 0x40, 0xFF);
-		writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK, 0x0);
-		writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK + 0x40, 0x0);
-	}
-	if (stat & 2) {
-		writereg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_MASK, 0xFF);
-		writereg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_MASK, 0x0);
-	}
+	writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK, 0xFF);
+	writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK + 0x40, 0xFF);
+	writereg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_MASK, 0x0);
+	writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK, 0x0);
+	writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK + 0x40, 0x0);
 }
 
 static void
 asuscom_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u_char ista, val, icnt = 20;
+	u_char ista, val, icnt = 5;
 
 	if (!cs) {
 		printk(KERN_WARNING "ISDNLink: Spurious interrupt!\n");
@@ -290,13 +289,13 @@
 	save_flags(flags);
 	sti();
 	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(1);
+	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;
-	schedule_timeout(1);
+	schedule_timeout((10*HZ)/1000);
 	if (cs->subtyp == ASUS_IPAC) {
 		writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_CONF, 0x0);
 		writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_ACFG, 0xff);
@@ -317,13 +316,6 @@
 		case CARD_RELEASE:
 			release_io_asuscom(cs);
 			return(0);
-		case CARD_SETIRQ:
-			if (cs->subtyp == ASUS_IPAC)
-				return(request_irq(cs->irq, &asuscom_interrupt_ipac,
-					I4L_IRQ_FLAG, "HiSax", cs));
-			else
-				return(request_irq(cs->irq, &asuscom_interrupt,
-					I4L_IRQ_FLAG, "HiSax", cs));
 		case CARD_INIT:
 			cs->debug |= L1_DEB_IPAC;
 			inithscxisac(cs, 3);
@@ -334,8 +326,8 @@
 	return(0);
 }
 
-int __init 
-setup_asuscom(struct IsdnCard *card)
+__initfunc(int
+setup_asuscom(struct IsdnCard *card))
 {
 	int bytecnt;
 	struct IsdnCardState *cs = card->cs;
@@ -378,6 +370,7 @@
 		cs->writeisac = &WriteISAC_IPAC;
 		cs->readisacfifo = &ReadISACfifo_IPAC;
 		cs->writeisacfifo = &WriteISACfifo_IPAC;
+		cs->irq_func = &asuscom_interrupt_ipac;
 		printk(KERN_INFO "Asus: IPAC version %x\n", val);
 	} else {
 		cs->subtyp = ASUS_ISACHSCX;
@@ -390,6 +383,7 @@
 		cs->writeisac = &WriteISAC;
 		cs->readisacfifo = &ReadISACfifo;
 		cs->writeisacfifo = &WriteISACfifo;
+		cs->irq_func = &asuscom_interrupt;
 		ISACVersion(cs, "ISDNLink:");
 		if (HscxVersion(cs, "ISDNLink:")) {
 			printk(KERN_WARNING
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/avm_a1.c linux/drivers/isdn/hisax/avm_a1.c
--- v2.3.13/linux/drivers/isdn/hisax/avm_a1.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/isdn/hisax/avm_a1.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: avm_a1.c,v 2.10 1998/11/15 23:54:21 keil Exp $
+/* $Id: avm_a1.c,v 2.11 1999/07/12 21:04:54 keil Exp $
 
  * avm_a1.c     low level stuff for AVM A1 (Fritz) isdn cards
  *
@@ -6,6 +6,10 @@
  *
  *
  * $Log: avm_a1.c,v $
+ * Revision 2.11  1999/07/12 21:04:54  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
  * Revision 2.10  1998/11/15 23:54:21  keil
  * changes from 2.0
  *
@@ -66,7 +70,7 @@
 #include "isdnl1.h"
 
 extern const char *CardType[];
-static const char *avm_revision = "$Revision: 2.10 $";
+static const char *avm_revision = "$Revision: 2.11 $";
 
 #define	 AVM_A1_STAT_ISAC	0x01
 #define	 AVM_A1_STAT_HSCX	0x02
@@ -153,7 +157,7 @@
 avm_a1_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u_char val, sval, stat = 0;
+	u_char val, sval;
 
 	if (!cs) {
 		printk(KERN_WARNING "AVM A1: Spurious interrupt!\n");
@@ -167,29 +171,21 @@
 			debugl1(cs, "avm IntStatus %x", sval);
 		if (!(sval & AVM_A1_STAT_HSCX)) {
 			val = readreg(cs->hw.avm.hscx[1], HSCX_ISTA);
-			if (val) {
+			if (val)
 				hscx_int_main(cs, val);
-				stat |= 1;
-			}
 		}
 		if (!(sval & AVM_A1_STAT_ISAC)) {
 			val = readreg(cs->hw.avm.isac, ISAC_ISTA);
-			if (val) {
+			if (val)
 				isac_interrupt(cs, val);
-				stat |= 2;
-			}
 		}
 	}
-	if (stat & 1) {
-		writereg(cs->hw.avm.hscx[0], HSCX_MASK, 0xFF);
-		writereg(cs->hw.avm.hscx[1], HSCX_MASK, 0xFF);
-		writereg(cs->hw.avm.hscx[0], HSCX_MASK, 0x0);
-		writereg(cs->hw.avm.hscx[1], HSCX_MASK, 0x0);
-	}
-	if (stat & 2) {
-		writereg(cs->hw.avm.isac, ISAC_MASK, 0xFF);
-		writereg(cs->hw.avm.isac, ISAC_MASK, 0x0);
-	}
+	writereg(cs->hw.avm.hscx[0], HSCX_MASK, 0xFF);
+	writereg(cs->hw.avm.hscx[1], HSCX_MASK, 0xFF);
+	writereg(cs->hw.avm.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.avm.isac, ISAC_MASK, 0x0);
+	writereg(cs->hw.avm.hscx[0], HSCX_MASK, 0x0);
+	writereg(cs->hw.avm.hscx[1], HSCX_MASK, 0x0);
 }
 
 inline static void
@@ -219,9 +215,6 @@
 		case CARD_RELEASE:
 			release_ioregs(cs, 0x3f);
 			return(0);
-		case CARD_SETIRQ:
-			return(request_irq(cs->irq, &avm_a1_interrupt,
-					I4L_IRQ_FLAG, "HiSax", cs));
 		case CARD_INIT:
 			inithscxisac(cs, 1);
 			byteout(cs->hw.avm.cfg_reg, 0x16);
@@ -234,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;
@@ -378,6 +371,7 @@
 	cs->BC_Write_Reg = &WriteHSCX;
 	cs->BC_Send_Data = &hscx_fill_fifo;
 	cs->cardmsg = &AVM_card_msg;
+	cs->irq_func = &avm_a1_interrupt;
 	ISACVersion(cs, "AVM A1:");
 	if (HscxVersion(cs, "AVM A1:")) {
 		printk(KERN_WARNING
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/avm_a1p.c linux/drivers/isdn/hisax/avm_a1p.c
--- v2.3.13/linux/drivers/isdn/hisax/avm_a1p.c	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/hisax/avm_a1p.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: avm_a1p.c,v 2.3 1998/11/15 23:54:22 keil Exp $
+/* $Id: avm_a1p.c,v 2.4 1999/07/12 21:04:55 keil Exp $
  *
  * avm_a1p.c    low level stuff for the following AVM cards:
  *              A1 PCMCIA
@@ -8,6 +8,10 @@
  * Author       Carsten Paeth (calle@calle.in-berlin.de)
  *
  * $Log: avm_a1p.c,v $
+ * Revision 2.4  1999/07/12 21:04:55  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
  * Revision 2.3  1998/11/15 23:54:22  keil
  * changes from 2.0
  *
@@ -67,7 +71,7 @@
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
 
-static const char *avm_revision = "$Revision: 2.3 $";
+static const char *avm_revision = "$Revision: 2.4 $";
 
 static inline u_char
 ReadISAC(struct IsdnCardState *cs, u_char offset)
@@ -195,7 +199,7 @@
 avm_a1p_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u_char val, sval, stat = 0;
+	u_char val, sval;
 
 	if (!cs) {
 		printk(KERN_WARNING "AVM A1 PCMCIA: Spurious interrupt!\n");
@@ -206,35 +210,26 @@
 			debugl1(cs, "avm IntStatus %x", sval);
 		if (sval & ASL0_R_HSCX) {
                         val = ReadHSCX(cs, 1, HSCX_ISTA);
-			if (val) {
+			if (val)
 				hscx_int_main(cs, val);
-				stat |= 1;
-			}
 		}
 		if (sval & ASL0_R_ISAC) {
 			val = ReadISAC(cs, ISAC_ISTA);
-			if (val) {
+			if (val)
 				isac_interrupt(cs, val);
-				stat |= 2;
-			}
 		}
 	}
-	if (stat & 1) {
-		WriteHSCX(cs, 0, HSCX_MASK, 0xff);
-		WriteHSCX(cs, 1, HSCX_MASK, 0xff);
-		WriteHSCX(cs, 0, HSCX_MASK, 0x00);
-		WriteHSCX(cs, 1, HSCX_MASK, 0x00);
-	}
-	if (stat & 2) {
-		WriteISAC(cs, ISAC_MASK, 0xff);
-		WriteISAC(cs, ISAC_MASK, 0x00);
-	}
+	WriteHSCX(cs, 0, HSCX_MASK, 0xff);
+	WriteHSCX(cs, 1, HSCX_MASK, 0xff);
+	WriteISAC(cs, ISAC_MASK, 0xff);
+	WriteISAC(cs, ISAC_MASK, 0x00);
+	WriteHSCX(cs, 0, HSCX_MASK, 0x00);
+	WriteHSCX(cs, 1, HSCX_MASK, 0x00);
 }
 
 static int
 AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
-	int ret;
 	switch (mt) {
 		case CARD_RESET:
 			byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
@@ -249,15 +244,6 @@
 		        /* free_irq(cs->irq, cs); */
 			return 0;
 
-		case CARD_SETIRQ:
-			ret = request_irq(cs->irq, &avm_a1p_interrupt,
-					I4L_IRQ_FLAG, "HiSax", cs);
-			if (ret)
-				return ret;
-			byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,
-				ASL0_W_TDISABLE|ASL0_W_TRESET|ASL0_W_IRQENABLE);
-                        return 0;
-
 		case CARD_INIT:
 			clear_pending_isac_ints(cs);
 			clear_pending_hscx_ints(cs);
@@ -323,6 +309,7 @@
 	cs->BC_Write_Reg = &WriteHSCX;
 	cs->BC_Send_Data = &hscx_fill_fifo;
 	cs->cardmsg = &AVM_card_msg;
+	cs->irq_func = &avm_a1p_interrupt;
 
 	ISACVersion(cs, "AVM A1 PCMCIA:");
 	if (HscxVersion(cs, "AVM A1 PCMCIA:")) {
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/avm_pci.c linux/drivers/isdn/hisax/avm_pci.c
--- v2.3.13/linux/drivers/isdn/hisax/avm_pci.c	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/hisax/avm_pci.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: avm_pci.c,v 1.7 1999/02/22 18:26:30 keil Exp $
+/* $Id: avm_pci.c,v 1.11 1999/08/11 21:01:18 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,19 @@
  *
  *
  * $Log: avm_pci.c,v $
+ * Revision 1.11  1999/08/11 21:01:18  keil
+ * new PCI codefix
+ *
+ * Revision 1.10  1999/08/10 16:01:44  calle
+ * struct pci_dev changed in 2.3.13. Made the necessary changes.
+ *
+ * Revision 1.9  1999/07/12 21:04:57  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 1.8  1999/07/01 08:11:19  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 1.7  1999/02/22 18:26:30  keil
  * Argh ! ISAC address was only set with PCI
  *
@@ -37,10 +50,13 @@
 #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.7 $";
+static const char *avm_pci_rev = "$Revision: 1.11 $";
 
 #define  AVM_FRITZ_PCI		1
 #define  AVM_FRITZ_PNP		2
@@ -466,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);
-				dev_kfree_skb(bcs->tx_skb);
+				idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
 				bcs->hw.hdlc.count = 0;
 				bcs->tx_skb = NULL;
 			}
@@ -593,7 +609,7 @@
 		discard_queue(&bcs->rqueue);
 		discard_queue(&bcs->squeue);
 		if (bcs->tx_skb) {
-			dev_kfree_skb(bcs->tx_skb);
+			idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
 			bcs->tx_skb = NULL;
 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 		}
@@ -687,7 +703,7 @@
 avm_pcipnp_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u_char val, stat = 0;
+	u_char val;
 	u_char sval;
 
 	if (!cs) {
@@ -701,15 +717,12 @@
 	if (!(sval & AVM_STATUS0_IRQ_ISAC)) {
 		val = ReadISAC(cs, ISAC_ISTA);
 		isac_interrupt(cs, val);
-		stat |= 2;
 	}
 	if (!(sval & AVM_STATUS0_IRQ_HDLC)) {
 		HDLC_irq_main(cs);
 	}
-	if (stat & 2) {
-		WriteISAC(cs, ISAC_MASK, 0xFF);
-		WriteISAC(cs, ISAC_MASK, 0x0);
-	}
+	WriteISAC(cs, ISAC_MASK, 0xFF);
+	WriteISAC(cs, ISAC_MASK, 0x0);
 }
 
 static void
@@ -733,8 +746,6 @@
 static int
 AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
-	u_int irq_flag;
-
 	switch (mt) {
 		case CARD_RESET:
 			reset_avmpcipnp(cs);
@@ -743,13 +754,6 @@
 			outb(0, cs->hw.avm.cfg_reg + 2);
 			release_region(cs->hw.avm.cfg_reg, 32);
 			return(0);
-		case CARD_SETIRQ:
-			if (cs->subtyp == AVM_FRITZ_PCI)
-				irq_flag = I4L_IRQ_FLAG | SA_SHIRQ;
-			else
-				irq_flag = I4L_IRQ_FLAG;
-			return(request_irq(cs->irq, &avm_pcipnp_interrupt,
-					irq_flag, "HiSax", cs));
 		case CARD_INIT:
 			clear_pending_isac_ints(cs);
 			initisac(cs);
@@ -769,7 +773,11 @@
 	return(0);
 }
 
+#ifdef COMPAT_HAS_NEW_PCI
 static 	struct pci_dev *dev_avm __initdata = NULL;
+#else
+static  int pci_index __initdata = 0;
+#endif
 
 __initfunc(int
 setup_avm_pcipnp(struct IsdnCard *card))
@@ -788,6 +796,7 @@
 		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);
@@ -799,7 +808,7 @@
 				printk(KERN_WARNING "FritzPCI: No IRQ for PCI card found\n");
 				return(0);
 			}
-			cs->hw.avm.cfg_reg = dev_avm->base_address[1] &
+			cs->hw.avm.cfg_reg = get_pcibase(dev_avm, 1) &
 				PCI_BASE_ADDRESS_IO_MASK; 
 			if (!cs->hw.avm.cfg_reg) {
 				printk(KERN_WARNING "FritzPCI: No IO-Adr for PCI card found\n");
@@ -811,6 +820,37 @@
 			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");
 		return (0);
 #endif /* CONFIG_PCI */
@@ -846,8 +886,6 @@
 		break;
 	  default:
 	  	printk(KERN_WARNING "AVM unknown subtype %d\n", cs->subtyp);
-		outb(0, cs->hw.avm.cfg_reg + 2);
-		release_region(cs->hw.avm.cfg_reg, 32);
 	  	return(0);
 	}
 	printk(KERN_INFO "HiSax: %s config irq:%d base:0x%X\n",
@@ -860,6 +898,7 @@
 	cs->writeisacfifo = &WriteISACfifo;
 	cs->BC_Send_Data = &fill_hdlc;
 	cs->cardmsg = &AVM_card_msg;
+	cs->irq_func = &avm_pcipnp_interrupt;
 	ISACVersion(cs, (cs->subtyp == AVM_FRITZ_PCI) ? "AVM PCI:" : "AVM PnP:");
 	return (1);
 }
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/bkm_a4t.c linux/drivers/isdn/hisax/bkm_a4t.c
--- v2.3.13/linux/drivers/isdn/hisax/bkm_a4t.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/hisax/bkm_a4t.c	Sun Aug 15 11:49:08 1999
@@ -0,0 +1,404 @@
+/* $Id: bkm_a4t.c,v 1.6 1999/08/11 21:01:22 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
+ *              derived from the original file netjet.c
+ *
+ * Author       Roland Klabunde (R.Klabunde@Berkom.de)
+ *
+ * $Log: bkm_a4t.c,v $
+ * Revision 1.6  1999/08/11 21:01:22  keil
+ * new PCI codefix
+ *
+ * Revision 1.5  1999/08/10 16:01:46  calle
+ * struct pci_dev changed in 2.3.13. Made the necessary changes.
+ *
+ * Revision 1.4  1999/07/14 11:43:14  keil
+ * correct PCI_SUBSYSTEM_VENDOR_ID
+ *
+ * Revision 1.3  1999/07/12 21:04:58  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 1.2  1999/07/01 08:07:53  keil
+ * Initial version
+ *
+ *
+ */
+
+#define __NO_VERSION__
+
+#include <linux/config.h>
+#include "hisax.h"
+#include "isac.h"
+#include "hscx.h"
+#include "jade.h"
+#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.6 $";
+
+
+static inline u_char
+readreg(unsigned int ale, unsigned int adr, u_char off)
+{
+	register u_int ret;
+	long flags;
+	unsigned int *po = (unsigned int *) adr;	/* Postoffice */
+	save_flags(flags);
+	cli();
+	*po = (GCS_2 | PO_WRITE | off);
+	__WAITI20__(po);
+	*po = (ale | PO_READ);
+	__WAITI20__(po);
+	ret = *po;
+	restore_flags(flags);
+	return ((unsigned char) ret);
+}
+
+
+static inline void
+readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
+{
+	/* fifo read without cli because it's allready done  */
+	int i;
+	for (i = 0; i < size; i++)
+		*data++ = readreg(ale, adr, off);
+}
+
+
+static inline void
+writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
+{
+	long flags;
+	unsigned int *po = (unsigned int *) adr;	/* Postoffice */
+	save_flags(flags);
+	cli();
+	*po = (GCS_2 | PO_WRITE | off);
+	__WAITI20__(po);
+	*po = (ale | PO_WRITE | data);
+	__WAITI20__(po);
+	restore_flags(flags);
+}
+
+
+static inline void
+writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
+{
+	/* fifo write without cli because it's allready done  */
+	int i;
+
+	for (i = 0; i < size; i++)
+		writereg(ale, adr, off, *data++);
+}
+
+
+/* Interface functions */
+
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
+{
+	return (readreg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, offset));
+}
+
+static void
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+	writereg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, offset, value);
+}
+
+static void
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	readfifo(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, 0, data, size);
+}
+
+static void
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	writefifo(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, 0, data, size);
+}
+
+static u_char
+ReadJADE(struct IsdnCardState *cs, int jade, u_char offset)
+{
+	return (readreg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, offset + (jade == -1 ? 0 : (jade ? 0xC0 : 0x80))));
+}
+
+static void
+WriteJADE(struct IsdnCardState *cs, int jade, u_char offset, u_char value)
+{
+	writereg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, offset + (jade == -1 ? 0 : (jade ? 0xC0 : 0x80)), value);
+}
+
+/*
+ * fast interrupt JADE stuff goes here
+ */
+
+#define READJADE(cs, nr, reg) readreg(cs->hw.ax.jade_ale,\
+ 		cs->hw.ax.jade_adr, reg + (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)))
+#define WRITEJADE(cs, nr, reg, data) writereg(cs->hw.ax.jade_ale,\
+ 		cs->hw.ax.jade_adr, reg + (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), data)
+
+#define READJADEFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.ax.jade_ale,\
+		cs->hw.ax.jade_adr, (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), ptr, cnt)
+#define WRITEJADEFIFO(cs, nr, ptr, cnt) writefifo( cs->hw.ax.jade_ale,\
+		cs->hw.ax.jade_adr, (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), ptr, cnt)
+
+#include "jade_irq.c"
+
+static void
+bkm_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char val = 0;
+	I20_REGISTER_FILE *pI20_Regs;
+
+	if (!cs) {
+		printk(KERN_WARNING "HiSax: Telekom A4T: Spurious interrupt!\n");
+		return;
+	}
+	pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
+
+	/* ISDN interrupt pending? */
+	if (pI20_Regs->i20IntStatus & intISDN) {
+		/* Reset the ISDN interrupt     */
+		pI20_Regs->i20IntStatus = intISDN;
+		/* Disable ISDN interrupt */
+		pI20_Regs->i20IntCtrl &= ~intISDN;
+		/* Channel A first */
+		val = readreg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, jade_HDLC_ISR + 0x80);
+		if (val) {
+			jade_int_main(cs, val, 0);
+		}
+		/* Channel B  */
+		val = readreg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, jade_HDLC_ISR + 0xC0);
+		if (val) {
+			jade_int_main(cs, val, 1);
+		}
+		/* D-Channel */
+		val = readreg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, ISAC_ISTA);
+		if (val) {
+			isac_interrupt(cs, val);
+		}
+		/* Reenable ISDN interrupt */
+		pI20_Regs->i20IntCtrl |= intISDN;
+	}
+}
+
+void
+release_io_bkm(struct IsdnCardState *cs)
+{
+	if (cs->hw.ax.base) {
+		iounmap((void *) cs->hw.ax.base);
+		cs->hw.ax.base = 0;
+	}
+}
+
+static void
+enable_bkm_int(struct IsdnCardState *cs, unsigned bEnable)
+{
+	if (cs->typ == ISDN_CTYPE_BKM_A4T) {
+		I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
+		if (bEnable)
+			pI20_Regs->i20IntCtrl |= (intISDN | intPCI);
+		else
+			/* CAUTION: This disables the video capture driver too */
+			pI20_Regs->i20IntCtrl &= ~(intISDN | intPCI);
+	}
+}
+
+static void
+reset_bkm(struct IsdnCardState *cs)
+{
+	long flags;
+
+	if (cs->typ == ISDN_CTYPE_BKM_A4T) {
+		I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
+		save_flags(flags);
+		sti();
+		/* Issue the I20 soft reset     */
+		pI20_Regs->i20SysControl = 0xFF;	/* all in */
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout((10 * HZ) / 1000);
+		/* Remove the soft reset */
+		pI20_Regs->i20SysControl = sysRESET | 0xFF;
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout((10 * HZ) / 1000);
+		/* Set our configuration */
+		pI20_Regs->i20SysControl = sysRESET | sysCFG;
+		/* Issue ISDN reset     */
+		pI20_Regs->i20GuestControl = guestWAIT_CFG |
+		    g_A4T_JADE_RES |
+		    g_A4T_ISAR_RES |
+		    g_A4T_ISAC_RES |
+		    g_A4T_JADE_BOOTR |
+		    g_A4T_ISAR_BOOTR;
+		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;
+		schedule_timeout((10 * HZ) / 1000);
+		restore_flags(flags);
+	}
+}
+
+static int
+BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+	switch (mt) {
+		case CARD_RESET:
+			/* Disable ints */
+			enable_bkm_int(cs, 0);
+			reset_bkm(cs);
+			return (0);
+		case CARD_RELEASE:
+			/* Sanity */
+			enable_bkm_int(cs, 0);
+			reset_bkm(cs);
+			release_io_bkm(cs);
+			return (0);
+		case CARD_INIT:
+			clear_pending_isac_ints(cs);
+			clear_pending_jade_ints(cs);
+			initisac(cs);
+			initjade(cs);
+			/* Enable ints */
+			enable_bkm_int(cs, 1);
+			return (0);
+		case CARD_TEST:
+			return (0);
+	}
+	return (0);
+}
+
+#ifdef COMPAT_HAS_NEW_PCI
+static struct pci_dev *dev_a4t __initdata = NULL;
+#else
+static int pci_index __initdata = 0;
+#endif
+
+__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);
+	printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ == ISDN_CTYPE_BKM_A4T) {
+		cs->subtyp = BKM_A4T;
+	} else
+		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);
+	}
+	if ((dev_a4t = pci_find_device(I20_VENDOR_ID, I20_DEVICE_ID, dev_a4t))) {
+		u_int sub_sys_id = 0;
+
+		pci_read_config_dword(dev_a4t, PCI_SUBSYSTEM_VENDOR_ID,
+			&sub_sys_id);
+		if (sub_sys_id == ((A4T_SUBSYS_ID << 16) | A4T_SUBVEN_ID)) {
+			found = 1;
+			pci_memaddr = get_pcibase(dev_a4t, 0);
+			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);
+	}
+	if (!pci_memaddr) {
+		printk(KERN_WARNING "HiSax: %s: No Memory base address\n", CardType[card->typ]);
+		return (0);
+	}
+	pci_memaddr &= PCI_BASE_ADDRESS_MEM_MASK;
+	cs->hw.ax.base = (u_int) ioremap(pci_memaddr, 4096);
+	/* Check suspecious address */
+	pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
+	if ((pI20_Regs->i20IntStatus & 0x8EFFFFFF) != 0) {
+		printk(KERN_WARNING "HiSax: %s address %x-%x suspecious\n",
+		       CardType[card->typ], cs->hw.ax.base, cs->hw.ax.base + 4096);
+		iounmap((void *) cs->hw.ax.base);
+		cs->hw.ax.base = 0;
+		return (0);
+	}
+	cs->hw.ax.isac_adr = cs->hw.ax.base + PO_OFFSET;
+	cs->hw.ax.jade_adr = cs->hw.ax.base + PO_OFFSET;
+	cs->hw.ax.isac_ale = GCS_1;
+	cs->hw.ax.jade_ale = GCS_3;
+#else
+	printk(KERN_WARNING "HiSax: %s: NO_PCI_BIOS\n", CardType[card->typ]);
+	printk(KERN_WARNING "HiSax: %s: unable to configure\n", CardType[card->typ]);
+	return (0);
+#endif				/* CONFIG_PCI */
+	printk(KERN_INFO "HiSax: %s: Card configured at 0x%X IRQ %d\n",
+	       CardType[card->typ], cs->hw.ax.base, cs->irq);
+
+	reset_bkm(cs);
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->BC_Read_Reg = &ReadJADE;
+	cs->BC_Write_Reg = &WriteJADE;
+	cs->BC_Send_Data = &jade_fill_fifo;
+	cs->cardmsg = &BKM_card_msg;
+	cs->irq_func = &bkm_interrupt;
+	cs->irq_flags |= SA_SHIRQ;
+	ISACVersion(cs, "Telekom A4T:");
+	/* Jade version */
+	JadeVersion(cs, "Telekom A4T:");
+	return (1);
+}
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/bkm_a8.c linux/drivers/isdn/hisax/bkm_a8.c
--- v2.3.13/linux/drivers/isdn/hisax/bkm_a8.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/hisax/bkm_a8.c	Sun Aug 15 11:49:08 1999
@@ -0,0 +1,530 @@
+/* $Id: bkm_a8.c,v 1.6 1999/08/11 21:01:24 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
+ *              derived from the original file netjet.c
+ *
+ * Author       Roland Klabunde (R.Klabunde@Berkom.de)
+ *
+ * $Log: bkm_a8.c,v $
+ * Revision 1.6  1999/08/11 21:01:24  keil
+ * new PCI codefix
+ *
+ * Revision 1.5  1999/08/10 16:01:48  calle
+ * struct pci_dev changed in 2.3.13. Made the necessary changes.
+ *
+ * Revision 1.4  1999/07/14 11:43:15  keil
+ * correct PCI_SUBSYSTEM_VENDOR_ID
+ *
+ * Revision 1.3  1999/07/12 21:04:59  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 1.2  1999/07/01 08:07:54  keil
+ * Initial version
+ *
+ *
+ */
+#define __NO_VERSION__
+
+#include <linux/config.h>
+#include "hisax.h"
+#include "isac.h"
+#include "ipac.h"
+#include "hscx.h"
+#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.6 $";
+
+/* To survive the startup phase */
+typedef struct {
+	u_int active;		/* true/false */
+	u_int base;		/* ipac base address */
+} IPAC_STATE;
+
+static IPAC_STATE ipac_state[4 + 1] __initdata =
+{
+	{0, 0},			/* dummy */
+	{0, 0},			/* SCT_1 */
+	{0, 0},			/* SCT_2 */
+	{0, 0},			/* SCT_3 */
+	{0, 0}			/* SCT_4 */
+};
+
+static const char *sct_quadro_subtypes[] =
+{
+	"",
+	"#1",
+	"#2",
+	"#3",
+	"#4"
+};
+
+
+#define wordout(addr,val) outw(val,addr)
+#define wordin(addr) inw(addr)
+
+static inline u_char
+readreg(unsigned int ale, unsigned int adr, u_char off)
+{
+	register u_char ret;
+	long flags;
+	save_flags(flags);
+	cli();
+	wordout(ale, off);
+	ret = wordin(adr) & 0xFF;
+	restore_flags(flags);
+	return (ret);
+}
+
+static inline void
+readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
+{
+	/* fifo read without cli because it's allready done  */
+	int i;
+	wordout(ale, off);
+	for (i = 0; i < size; i++)
+		data[i] = wordin(adr) & 0xFF;
+}
+
+
+static inline void
+writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
+{
+	long flags;
+	save_flags(flags);
+	cli();
+	wordout(ale, off);
+	wordout(adr, data);
+	restore_flags(flags);
+}
+
+static inline void
+writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
+{
+	/* fifo write without cli because it's allready done  */
+	int i;
+	wordout(ale, off);
+	for (i = 0; i < size; i++)
+		wordout(adr, data[i]);
+}
+
+/* Interface functions */
+
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
+{
+	return (readreg(cs->hw.ax.base, cs->hw.ax.data_adr, offset | 0x80));
+}
+
+static void
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+	writereg(cs->hw.ax.base, cs->hw.ax.data_adr, offset | 0x80, value);
+}
+
+static void
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	readfifo(cs->hw.ax.base, cs->hw.ax.data_adr, 0x80, data, size);
+}
+
+static void
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	writefifo(cs->hw.ax.base, cs->hw.ax.data_adr, 0x80, data, size);
+}
+
+
+static u_char
+ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
+{
+	return (readreg(cs->hw.ax.base, cs->hw.ax.data_adr, offset + (hscx ? 0x40 : 0)));
+}
+
+static void
+WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
+{
+	writereg(cs->hw.ax.base, cs->hw.ax.data_adr, offset + (hscx ? 0x40 : 0), value);
+}
+
+/* Check whether the specified ipac is already active or not */
+static int
+is_ipac_active(u_int ipac_nr)
+{
+	return (ipac_state[ipac_nr].active);
+}
+
+/* Set the specific ipac to active */
+static void
+set_ipac_active(u_int ipac_nr, u_int active)
+{
+	/* set activation state */
+	ipac_state[ipac_nr].active = active;
+}
+
+/*
+ * fast interrupt HSCX stuff goes here
+ */
+
+#define READHSCX(cs, nr, reg) readreg(cs->hw.ax.base, \
+	cs->hw.ax.data_adr, reg + (nr ? 0x40 : 0))
+#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.ax.base, \
+	cs->hw.ax.data_adr, reg + (nr ? 0x40 : 0), data)
+#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.ax.base, \
+	cs->hw.ax.data_adr, (nr ? 0x40 : 0), ptr, cnt)
+#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.ax.base, \
+	cs->hw.ax.data_adr, (nr ? 0x40 : 0), ptr, cnt)
+
+#include "hscx_irq.c"
+
+static void
+bkm_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char ista, val, icnt = 5;
+	int i;
+	if (!cs) {
+		printk(KERN_WARNING "HiSax: Scitel Quadro: Spurious interrupt!\n");
+		return;
+	}
+	ista = readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ISTA);
+
+      Start_IPAC:
+	if (cs->debug & L1_DEB_IPAC)
+		debugl1(cs, "IPAC ISTA %02X", ista);
+	if (ista & 0x0f) {
+		val = readreg(cs->hw.ax.base, cs->hw.ax.data_adr, HSCX_ISTA + 0x40);
+		if (ista & 0x01)
+			val |= 0x01;
+		if (ista & 0x04)
+			val |= 0x02;
+		if (ista & 0x08)
+			val |= 0x04;
+		if (val) {
+			hscx_int_main(cs, val);
+		}
+	}
+	if (ista & 0x20) {
+		val = 0xfe & readreg(cs->hw.ax.base, cs->hw.ax.data_adr, ISAC_ISTA | 0x80);
+		if (val) {
+			isac_interrupt(cs, val);
+		}
+	}
+	if (ista & 0x10) {
+		val = 0x01;
+		isac_interrupt(cs, val);
+	}
+	ista = readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ISTA);
+	if ((ista & 0x3f) && icnt) {
+		icnt--;
+		goto Start_IPAC;
+	}
+	if (!icnt)
+		printk(KERN_WARNING "HiSax: %s (%s) IRQ LOOP\n",
+		       CardType[cs->typ],
+		       sct_quadro_subtypes[cs->subtyp]);
+	writereg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_MASK, 0xFF);
+	writereg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_MASK, 0xC0);
+
+	/* Read out all interrupt sources from currently not active ipacs */
+	/* "Handle" all interrupts from currently not active ipac by reading the regs */
+	for (i = SCT_1; i <= SCT_4; i++)
+		if (!is_ipac_active(i)) {
+			u_int base = ipac_state[i].base;
+			if (readreg(base, base + 4, 0xC1)) {
+				readreg(base, base + 4, 0xA0);
+				readreg(base, base + 4, 0xA4);
+				readreg(base, base + 4, 0x20);
+				readreg(base, base + 4, 0x24);
+				readreg(base, base + 4, 0x60);
+				readreg(base, base + 4, 0x64);
+				readreg(base, base + 4, 0xC1);
+				readreg(base, base + 4, ISAC_CIR0 + 0x80);
+			}
+		}
+}
+
+
+void
+release_io_sct_quadro(struct IsdnCardState *cs)
+{
+	/* ?? */
+}
+
+static void
+enable_bkm_int(struct IsdnCardState *cs, unsigned bEnable)
+{
+	if (cs->typ == ISDN_CTYPE_SCT_QUADRO) {
+		if (bEnable)
+			wordout(cs->hw.ax.plx_adr + 0x4C, (wordin(cs->hw.ax.plx_adr + 0x4C) | 0x41));
+		else
+			/* Issue general di only if no ipac is active */
+			if (!is_ipac_active(SCT_1) &&
+			    !is_ipac_active(SCT_2) &&
+			    !is_ipac_active(SCT_3) &&
+			    !is_ipac_active(SCT_4))
+			wordout(cs->hw.ax.plx_adr + 0x4C, (wordin(cs->hw.ax.plx_adr + 0x4C) & ~0x41));
+	}
+}
+
+static void
+reset_bkm(struct IsdnCardState *cs)
+{
+	long flags;
+
+	if (cs->typ == ISDN_CTYPE_SCT_QUADRO) {
+		if (!is_ipac_active(SCT_1) &&
+		    !is_ipac_active(SCT_2) &&
+		    !is_ipac_active(SCT_3) &&
+		    !is_ipac_active(SCT_4)) {
+			/* Issue total reset only if no ipac is active */
+			wordout(cs->hw.ax.plx_adr + 0x50, (wordin(cs->hw.ax.plx_adr + 0x50) & ~4));
+
+			save_flags(flags);
+			sti();
+			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;
+			schedule_timeout((10 * HZ) / 1000);
+			restore_flags(flags);
+		}
+	}
+}
+
+static int
+BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+	switch (mt) {
+		case CARD_RESET:
+			/* Disable ints */
+			set_ipac_active(cs->subtyp, 0);
+			enable_bkm_int(cs, 0);
+			reset_bkm(cs);
+			return (0);
+		case CARD_RELEASE:
+			/* Sanity */
+			set_ipac_active(cs->subtyp, 0);
+			enable_bkm_int(cs, 0);
+			reset_bkm(cs);
+			release_io_sct_quadro(cs);
+			return (0);
+		case CARD_INIT:
+			cs->debug |= L1_DEB_IPAC;
+			set_ipac_active(cs->subtyp, 1);
+			inithscxisac(cs, 3);
+			/* Enable ints */
+			enable_bkm_int(cs, 1);
+			return (0);
+		case CARD_TEST:
+			return (0);
+	}
+	return (0);
+}
+
+#ifdef COMPAT_HAS_NEW_PCI
+static struct pci_dev *dev_a8 __initdata = NULL;
+#else
+static int pci_index __initdata = 0;
+#endif
+
+__initfunc(int
+	   setup_sct_quadro(struct IsdnCard *card))
+{
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+#if CONFIG_PCI
+	u_char pci_bus = 0, pci_device_fn = 0, pci_irq = 0, pci_rev_id;
+	u_int found = 0;
+	u_int pci_ioaddr1, pci_ioaddr2, pci_ioaddr3, pci_ioaddr4, pci_ioaddr5;
+#endif
+
+	strcpy(tmp, sct_quadro_revision);
+	printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ == ISDN_CTYPE_SCT_QUADRO) {
+		cs->subtyp = SCT_1;	/* Preset */
+	} else
+		return (0);
+
+	/* Identify subtype by para[0] */
+	if (card->para[0] >= SCT_1 && card->para[0] <= SCT_4)
+		cs->subtyp = card->para[0];
+	else
+		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);
+	}
+	if ((dev_a8 = pci_find_device(PLX_VENDOR_ID, PLX_DEVICE_ID, dev_a8))) {
+		u_int sub_sys_id = 0;
+
+		pci_read_config_dword(dev_a8, PCI_SUBSYSTEM_VENDOR_ID,
+			&sub_sys_id);
+		if (sub_sys_id == ((SCT_SUBSYS_ID << 16) | SCT_SUBVEN_ID)) {
+			found = 1;
+			pci_ioaddr1 = get_pcibase(dev_a8, 1);
+			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],
+		       sct_quadro_subtypes[cs->subtyp]);
+		return (0);
+	}
+#ifdef ATTEMPT_PCI_REMAPPING
+/* HACK: PLX revision 1 bug: PLX address bit 7 must not be set */
+	pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_REVISION_ID, &pci_rev_id);
+	if ((pci_ioaddr1 & 0x80) && (pci_rev_id == 1)) {
+		printk(KERN_WARNING "HiSax: %s (%s): PLX rev 1, remapping required!\n",
+			CardType[card->typ],
+			sct_quadro_subtypes[cs->subtyp]);
+		/* Restart PCI negotiation */
+		pcibios_write_config_dword(pci_bus, pci_device_fn,
+			PCI_BASE_ADDRESS_1, (u_int) - 1);
+		/* Move up by 0x80 byte */
+		pci_ioaddr1 += 0x80;
+		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 */
+	}
+/* End HACK */
+#endif
+	pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &pci_ioaddr1);
+	pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_2, &pci_ioaddr2);
+	pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_3, &pci_ioaddr3);
+	pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_4, &pci_ioaddr4);
+	pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_5, &pci_ioaddr5);
+	if (!pci_ioaddr1 || !pci_ioaddr2 || !pci_ioaddr3 || !pci_ioaddr4 || !pci_ioaddr5) {
+		printk(KERN_WARNING "HiSax: %s (%s): No IO base address(es)\n",
+		       CardType[card->typ],
+		       sct_quadro_subtypes[cs->subtyp]);
+		return (0);
+	}
+	pci_ioaddr1 &= PCI_BASE_ADDRESS_IO_MASK;
+	pci_ioaddr2 &= PCI_BASE_ADDRESS_IO_MASK;
+	pci_ioaddr3 &= PCI_BASE_ADDRESS_IO_MASK;
+	pci_ioaddr4 &= PCI_BASE_ADDRESS_IO_MASK;
+	pci_ioaddr5 &= PCI_BASE_ADDRESS_IO_MASK;
+	/* Take over */
+	cs->irq = pci_irq;
+	cs->irq_flags |= SA_SHIRQ;
+	/* pci_ioaddr1 is unique to all subdevices */
+	/* pci_ioaddr2 is for the fourth subdevice only */
+	/* pci_ioaddr3 is for the third subdevice only */
+	/* pci_ioaddr4 is for the second subdevice only */
+	/* pci_ioaddr5 is for the first subdevice only */
+	cs->hw.ax.plx_adr = pci_ioaddr1;
+	/* Enter all ipac_base addresses */
+	ipac_state[SCT_1].base = pci_ioaddr5 + 0x00;
+	ipac_state[SCT_2].base = pci_ioaddr4 + 0x08;
+	ipac_state[SCT_3].base = pci_ioaddr3 + 0x10;
+	ipac_state[SCT_4].base = pci_ioaddr2 + 0x20;
+	/* For isac and hscx control path */
+	cs->hw.ax.base = ipac_state[cs->subtyp].base;
+	/* For isac and hscx data path */
+	cs->hw.ax.data_adr = cs->hw.ax.base + 4;
+#else
+	printk(KERN_WARNING "HiSax: %s (%s): NO_PCI_BIOS\n",
+	       CardType[card->typ],
+	       sct_quadro_subtypes[cs->subtyp]);
+	printk(KERN_WARNING "HiSax: %s (%s): Unable to configure\n",
+	       CardType[card->typ],
+	       sct_quadro_subtypes[cs->subtyp]);
+	return (0);
+#endif				/* CONFIG_PCI */
+	printk(KERN_INFO "HiSax: %s (%s) configured at 0x%.4X, 0x%.4X, 0x%.4X and IRQ %d\n",
+	       CardType[card->typ],
+	       sct_quadro_subtypes[cs->subtyp],
+	       cs->hw.ax.plx_adr,
+	       cs->hw.ax.base,
+	       cs->hw.ax.data_adr,
+	       cs->irq);
+
+	test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+
+	/* Disable all currently not active ipacs */
+	if (!is_ipac_active(SCT_1))
+		set_ipac_active(SCT_1, 0);
+	if (!is_ipac_active(SCT_2))
+		set_ipac_active(SCT_2, 0);
+	if (!is_ipac_active(SCT_3))
+		set_ipac_active(SCT_3, 0);
+	if (!is_ipac_active(SCT_4))
+		set_ipac_active(SCT_4, 0);
+
+	/* Perfom general reset (if possible) */
+	reset_bkm(cs);
+
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+
+	cs->BC_Read_Reg = &ReadHSCX;
+	cs->BC_Write_Reg = &WriteHSCX;
+	cs->BC_Send_Data = &hscx_fill_fifo;
+	cs->cardmsg = &BKM_card_msg;
+	cs->irq_func = &bkm_interrupt_ipac;
+
+	printk(KERN_INFO "HiSax: %s (%s): IPAC Version %d\n",
+		CardType[card->typ],
+		sct_quadro_subtypes[cs->subtyp],
+		readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ID));
+	return (1);
+}
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/bkm_ax.h linux/drivers/isdn/hisax/bkm_ax.h
--- v2.3.13/linux/drivers/isdn/hisax/bkm_ax.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/hisax/bkm_ax.h	Thu Aug 12 09:42:33 1999
@@ -0,0 +1,133 @@
+/* $Id: bkm_ax.h,v 1.2 1999/07/01 08:07:55 keil Exp $
+ * bkm_ax.h   low level decls for T-Berkom cards A4T and Scitel Quadro (4*S0, passive)
+ *
+ * Author     Roland Klabunde (R.Klabunde@Berkom.de)
+ *
+ * $Log: bkm_ax.h,v $
+ * Revision 1.2  1999/07/01 08:07:55  keil
+ * Initial version
+ *
+ *
+ *
+ */
+
+#ifndef	__BKM_AX_H__
+#define	__BKM_AX_H__
+
+/* Supported boards	(subtypes) */
+#define SCT_1		1
+#define	SCT_2		2
+#define	SCT_3		3
+#define	SCT_4		4
+#define BKM_A4T		5
+
+
+/* A4T																*/
+#define I20_DEVICE_ID       	0x6120  /* I20 PCI device ID */
+#define I20_VENDOR_ID       	0x11DE  /* I20 PCI vendor ID */
+#define	A4T_SUBVEN_ID		0x0871	
+#define	A4T_SUBSYS_ID		0xFFA4
+/* Scitel Quadro 																*/
+#define	PLX_DEVICE_ID		0x9050	/* Scitel Quadro PLX */
+#define	PLX_VENDOR_ID		0x10B5
+#define	SCT_SUBVEN_ID		0x0871
+#define	SCT_SUBSYS_ID		0xFFA8
+
+
+#define	PLX_ADDR_PLX		0x14	/* Addr PLX configuration */
+#define	PLX_ADDR_ISAC		0x18	/* Addr ISAC */
+#define	PLX_ADDR_HSCX		0x1C	/* Addr HSCX */
+#define	PLX_ADDR_ALE		0x20	/* Addr ALE */
+#define	PLX_ADDR_ALEPLUS	0x24	/* Next Addr behind ALE */
+
+#define	PLX_SUBVEN		0x2C	/* Offset SubVendor */
+#define	PLX_SUBSYS		0x2E	/* Offset SubSystem */
+
+
+/* Application specific registers I20 (Siemens SZB6120H) */
+typedef	struct {
+		/* Video front end horizontal configuration register */
+	volatile u_int	i20VFEHorzCfg;	/* Offset 00 */
+		/* Video front end vertical configuration register */
+	volatile u_int	i20VFEVertCfg;	/* Offset 04 */	
+		/* Video front end scaler and pixel format register */
+	volatile u_int	i20VFEScaler;	/* Offset 08 */	
+		/* Video display top register */
+	volatile u_int	i20VDispTop;   	/* Offset 0C */	
+		/* Video display bottom register */
+	volatile u_int	i20VDispBottom;	/* Offset 10 */	
+		/* Video stride, status and frame grab register */
+	volatile u_int	i20VidFrameGrab;/* Offset 14 */	
+		/* Video display configuration register */
+	volatile u_int	i20VDispCfg;	/* Offset 18 */	
+		/* Video masking map top */
+	volatile u_int	i20VMaskTop;	/* Offset 1C */	
+		/* Video masking map bottom */
+	volatile u_int	i20VMaskBottom;	/* Offset 20 */	
+		/* Overlay control register */
+	volatile u_int 	i20OvlyControl;	/* Offset 24 */	
+		/* System, PCI and general purpose pins control register */
+ 	volatile u_int	i20SysControl; 	/* Offset 28 */	
+#define	sysRESET		0x01000000	/* bit 24:Softreset (Low)		*/
+			/* GPIO 4...0: Output fixed for our cfg! */
+#define	sysCFG			0x000000E0	/* GPIO 7,6,5: Input */
+	/* General purpose pins and guest bus control register */
+ 	volatile u_int	i20GuestControl;/* Offset 2C */	
+#define	guestWAIT_CFG	0x00005555	/* 4 PCI waits for all */
+#define	guestISDN_INT_E	0x01000000	/* ISDN Int en (low) */
+#define	guestVID_INT_E 	0x02000000	/* Video interrupt en (low) */
+#define	guestADI1_INT_R	0x04000000	/* ADI #1 int req (low) */
+#define	guestADI2_INT_R	0x08000000	/* ADI #2 int req (low) */
+#define	guestISDN_RES	0x10000000	/* ISDN reset bit (high) */
+#define	guestADI1_INT_S	0x20000000	/* ADI #1 int pending (low) */
+#define	guestADI2_INT_S	0x40000000	/* ADI #2 int pending (low) */
+#define	guestISDN_INT_S	0x80000000	/* ISAC int pending (low) */
+
+#define	g_A4T_JADE_RES	0x01000000	/* JADE Reset (High) */
+#define	g_A4T_ISAR_RES	0x02000000	/* ISAR Reset (High) */
+#define	g_A4T_ISAC_RES	0x04000000	/* ISAC Reset (High) */
+#define	g_A4T_JADE_BOOTR 0x08000000	/* JADE enable boot SRAM (Low) NOT USED */
+#define	g_A4T_ISAR_BOOTR 0x10000000	/* ISAR enable boot SRAM (Low) NOT USED */
+#define	g_A4T_JADE_INT_S 0x20000000	/* JADE interrupt pnd (Low) */
+#define	g_A4T_ISAR_INT_S 0x40000000	/* ISAR interrupt pnd (Low) */
+#define	g_A4T_ISAC_INT_S 0x80000000	/* ISAC interrupt pnd (Low) */
+
+ 	volatile u_int	i20CodeSource;	/* Offset 30 */	
+ 	volatile u_int	i20CodeXferCtrl;/* Offset 34 */	
+ 	volatile u_int	i20CodeMemPtr;	/* Offset 38 */	
+
+  	volatile u_int	i20IntStatus;	/* Offset 3C */	
+ 	volatile u_int	i20IntCtrl;	/* Offset 40 */	
+#define	intISDN		0x40000000	/* GIRQ1En (ISAC/ADI) (High) */
+#define	intVID		0x20000000	/* GIRQ0En (VSYNC)    (High) */
+#define	intCOD		0x10000000	/* CodRepIrqEn        (High) */
+#define	intPCI 		0x01000000	/* PCI IntA enable    (High) */
+
+ 	volatile u_int	i20I2CCtrl;	/* Offset 44					*/	
+} I20_REGISTER_FILE, *PI20_REGISTER_FILE;
+
+/*
+ * Postoffice structure for A4T
+ *
+ */
+#define	PO_OFFSET	0x00000200	/* Postoffice offset from base */
+
+#define	GCS_0		0x00000000 	/* Guest bus chip selects */
+#define	GCS_1		0x00100000
+#define	GCS_2		0x00200000
+#define	GCS_3		0x00300000
+
+#define	PO_READ		0x00000000	/* R/W from/to guest bus */
+#define	PO_WRITE	0x00800000
+
+#define	PO_PEND		0x02000000
+
+#define POSTOFFICE(postoffice) *(volatile unsigned int*)(postoffice)
+
+/* Wait unlimited (don't worry)										*/ 
+#define	__WAITI20__(postoffice)										\
+do {		   	 		   											\
+  	while ((POSTOFFICE(postoffice) & PO_PEND)) ;					\
+} while (0)
+
+#endif	/* __BKM_AX_H__ */
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/callc.c linux/drivers/isdn/hisax/callc.c
--- v2.3.13/linux/drivers/isdn/hisax/callc.c	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/hisax/callc.c	Sun Aug 15 11:49:08 1999
@@ -1,4 +1,4 @@
-/* $Id: callc.c,v 2.25 1999/01/02 11:17:20 keil Exp $
+/* $Id: callc.c,v 2.31 1999/08/05 20:43:10 keil Exp $
 
  * Author       Karsten Keil (keil@isdn4linux.de)
  *              based on the teles driver from Jan den Ouden
@@ -11,6 +11,25 @@
  *              Fritz Elfert
  *
  * $Log: callc.c,v $
+ * Revision 2.31  1999/08/05 20:43:10  keil
+ * ISAR analog modem support
+ *
+ * Revision 2.30  1999/07/25 16:24:04  keil
+ * Fixed TEI now working again
+ *
+ * Revision 2.29  1999/07/13 21:05:41  werner
+ * Modified set_channel_limit to use new callback ISDN_STAT_DISCH.
+ *
+ * Revision 2.28  1999/07/09 08:30:02  keil
+ * cosmetics
+ *
+ * Revision 2.27  1999/07/05 23:51:38  werner
+ * Allow limiting of available HiSax B-chans per card. Controlled by hisaxctrl
+ * hisaxctrl id 10 <nr. of chans 0-2>
+ *
+ * Revision 2.26  1999/07/01 08:11:21  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 2.25  1999/01/02 11:17:20  keil
  * Changes for 2.2
  *
@@ -107,15 +126,21 @@
  *
  */
 
+#include <linux/config.h>
 #define __NO_VERSION__
 #include "hisax.h"
 #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))
-#endif				/* 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.25 $";
+const char *lli_revision = "$Revision: 2.31 $";
 
 extern struct IsdnCard cards[];
 extern int nrcards;
@@ -146,28 +171,7 @@
 
 /* Flags for remembering action done in lli */
 
-#define  FLG_START_D	0
-#define  FLG_ESTAB_D	1
-#define  FLG_CALL_SEND	2
-#define  FLG_CALL_REC   3
-#define  FLG_CALL_ALERT	4
-#define  FLG_START_B	5
-#define  FLG_CONNECT_B	6
-#define  FLG_LL_DCONN	7
-#define  FLG_LL_BCONN	8
-#define  FLG_DISC_SEND	9
-#define  FLG_DISC_REC	10
-#define  FLG_REL_REC	11
-#define  FLG_DO_ALERT	12
-#define  FLG_DO_HANGUP	13
-#define  FLG_DO_CONNECT	14
-#define  FLG_DO_ESTAB	15
-#define  FLG_RESUME	16
-
-/*
- * Because of callback it's a good idea to delay the shutdown of the d-channel
- */
-#define	DREL_TIMER_VALUE 40000
+#define  FLG_START_B	0
 
 /*
  * Find card with given driverId
@@ -192,7 +196,7 @@
 	int ret=0;
 
 	while ((skb = skb_dequeue(q))) {
-		dev_kfree_skb(skb);
+		idev_kfree_skb(skb, FREE_READ);
 		ret++;
 	}
 	return(ret);
@@ -211,44 +215,40 @@
 	va_end(args);
 }
 
-
 enum {
-	ST_NULL,		/*  0 inactive */
-	ST_OUT_WAIT_D,		/*  1 outgoing, awaiting d-channel establishment */
-	ST_IN_WAIT_D,		/*  2 incoming, awaiting d-channel establishment */
-	ST_OUT_DIAL,		/*  3 outgoing, SETUP send; awaiting confirm */
-	ST_IN_WAIT_LL,		/*  4 incoming call received; wait for LL confirm */
-	ST_IN_ALERT_SEND,	/*  5 incoming call received; ALERT send */
-	ST_IN_WAIT_CONN_ACK,	/*  6 incoming CONNECT send; awaiting CONN_ACK */
-	ST_WAIT_BCONN,		/*  7 CONNECT/CONN_ACK received, awaiting b-channel prot. estbl. */
-	ST_ACTIVE,		/*  8 active, b channel prot. established */
-	ST_WAIT_BRELEASE,	/*  9 call clear. (initiator), awaiting b channel prot. rel. */
-	ST_WAIT_BREL_DISC,	/* 10 call clear. (receiver), DISCONNECT req. received */
-	ST_WAIT_DCOMMAND,	/* 11 call clear. (receiver), awaiting DCHANNEL message */
-	ST_WAIT_DRELEASE,	/* 12 DISCONNECT sent, awaiting RELEASE */
-	ST_WAIT_D_REL_CNF,	/* 13 RELEASE sent, awaiting RELEASE confirm */
-	ST_WAIT_DSHUTDOWN,	/*  14 awaiting d-channel shutdown */
+        ST_NULL,                /*  0 inactive */
+        ST_OUT_DIAL,            /*  1 outgoing, SETUP send; awaiting confirm */
+        ST_IN_WAIT_LL,          /*  2 incoming call received; wait for LL confirm */
+        ST_IN_ALERT_SENT,       /*  3 incoming call received; ALERT send */
+        ST_IN_WAIT_CONN_ACK,    /*  4 incoming CONNECT send; awaiting CONN_ACK */
+        ST_WAIT_BCONN,          /*  5 CONNECT/CONN_ACK received, awaiting b-channel prot. estbl. */
+        ST_ACTIVE,              /*  6 active, b channel prot. established */
+        ST_WAIT_BRELEASE,       /*  7 call clear. (initiator), awaiting b channel prot. rel. */
+        ST_WAIT_BREL_DISC,      /*  8 call clear. (receiver), DISCONNECT req. received */
+        ST_WAIT_DCOMMAND,       /*  9 call clear. (receiver), awaiting DCHANNEL message */
+        ST_WAIT_DRELEASE,       /* 10 DISCONNECT sent, awaiting RELEASE */
+        ST_WAIT_D_REL_CNF,      /* 11 RELEASE sent, awaiting RELEASE confirm */
+        ST_IN_PROCEED_SEND,     /* 12 incoming call, proceeding send */ 
 };
+  
 
-#define STATE_COUNT (ST_WAIT_DSHUTDOWN +1)
+#define STATE_COUNT (ST_IN_PROCEED_SEND + 1)
 
-static char *strState[] =
-{
-	"ST_NULL",
-	"ST_OUT_WAIT_D",
-	"ST_IN_WAIT_D",
-	"ST_OUT_DIAL",
-	"ST_IN_WAIT_LL",
-	"ST_IN_ALERT_SEND",
-	"ST_IN_WAIT_CONN_ACK",
-	"ST_WAIT_BCONN",
-	"ST_ACTIVE",
+  static char *strState[] =
+  {
+        "ST_NULL",
+        "ST_OUT_DIAL",
+        "ST_IN_WAIT_LL",
+        "ST_IN_ALERT_SENT",
+        "ST_IN_WAIT_CONN_ACK",
+        "ST_WAIT_BCONN",
+        "ST_ACTIVE",
 	"ST_WAIT_BRELEASE",
 	"ST_WAIT_BREL_DISC",
 	"ST_WAIT_DCOMMAND",
 	"ST_WAIT_DRELEASE",
 	"ST_WAIT_D_REL_CNF",
-	"ST_WAIT_DSHUTDOWN",
+        "ST_IN_PROCEED_SEND",
 };
 
 enum {
@@ -256,29 +256,28 @@
 	EV_SETUP_CNF,		/*  1 */
 	EV_ACCEPTB,		/*  2 */
 	EV_DISCONNECT_IND,	/*  3 */
-	EV_RELEASE_CNF,		/*  4 */
-	EV_DLEST,		/*  5 */
-	EV_DLRL,		/*  6 */
+	EV_RELEASE, 		/*  4 */
+	EV_LEASED,		/*  5 */
+	EV_LEASED_REL,		/*  6 */
 	EV_SETUP_IND,		/*  7 */
-	EV_RELEASE_IND,		/*  8 */
-	EV_ACCEPTD,		/*  9 */
-	EV_SETUP_CMPL_IND,	/* 10 */
-	EV_BC_EST,		/* 11 */
-	EV_WRITEBUF,		/* 12 */
-	EV_ESTABLISH,		/* 13 */
-	EV_HANGUP,		/* 14 */
-	EV_BC_REL,		/* 15 */
-	EV_CINF,		/* 16 */
-	EV_SUSPEND,		/* 17 */
-	EV_RESUME,		/* 18 */
-	EV_SHUTDOWN_D,		/* 19 */
-	EV_NOSETUP_RSP,		/* 20 */
-	EV_SETUP_ERR,		/* 21 */
-	EV_CONNECT_ERR,		/* 22 */
-	EV_RELEASE_ERR,		/* 23 */
+	EV_ACCEPTD,		/*  8 */
+	EV_SETUP_CMPL_IND,	/*  9 */
+	EV_BC_EST,		/* 10 */
+	EV_WRITEBUF,		/* 11 */
+	EV_HANGUP,		/* 12 */
+	EV_BC_REL,		/* 13 */
+	EV_CINF,		/* 14 */
+	EV_SUSPEND,		/* 15 */
+	EV_RESUME,		/* 16 */
+	EV_NOSETUP_RSP,		/* 17 */
+	EV_SETUP_ERR,		/* 18 */
+	EV_CONNECT_ERR,		/* 19 */
+	EV_PROCEED,		/* 20 */
+	EV_ALERT,		/* 21 */ 
+	EV_REDIR,		/* 22 */ 
 };
 
-#define EVENT_COUNT (EV_RELEASE_ERR +1)
+#define EVENT_COUNT (EV_REDIR + 1)
 
 static char *strEvent[] =
 {
@@ -286,150 +285,152 @@
 	"EV_SETUP_CNF",
 	"EV_ACCEPTB",
 	"EV_DISCONNECT_IND",
-	"EV_RELEASE_CNF",
-	"EV_DLEST",
-	"EV_DLRL",
+	"EV_RELEASE",
+	"EV_LEASED",
+	"EV_LEASED_REL",
 	"EV_SETUP_IND",
-	"EV_RELEASE_IND",
 	"EV_ACCEPTD",
 	"EV_SETUP_CMPL_IND",
 	"EV_BC_EST",
 	"EV_WRITEBUF",
-	"EV_ESTABLISH",
 	"EV_HANGUP",
 	"EV_BC_REL",
 	"EV_CINF",
 	"EV_SUSPEND",
 	"EV_RESUME",
-	"EV_SHUTDOWN_D",
 	"EV_NOSETUP_RSP",
 	"EV_SETUP_ERR",
 	"EV_CONNECT_ERR",
-	"EV_RELEASE_ERR",
+	"EV_PROCEED",
+	"EV_ALERT",
+	"EV_REDIR",
 };
 
+
 static inline void
-lli_deliver_cause(struct Channel *chanp, isdn_ctrl *ic)
+HL_LL(struct Channel *chanp, int command)
 {
-	if (chanp->proc->para.cause < 0)
+        isdn_ctrl ic;
+
+        ic.driver = chanp->cs->myid;
+        ic.command = command;
+        ic.arg = chanp->chan;
+        chanp->cs->iif.statcallb(&ic);
+}
+
+static inline void
+lli_deliver_cause(struct Channel *chanp)
+{
+        isdn_ctrl ic;
+ 
+	if (chanp->proc->para.cause == NO_CAUSE)
 		return;
-	ic->driver = chanp->cs->myid;
-	ic->command = ISDN_STAT_CAUSE;
-	ic->arg = chanp->chan;
+	ic.driver = chanp->cs->myid;
+	ic.command = ISDN_STAT_CAUSE;
+	ic.arg = chanp->chan;
 	if (chanp->cs->protocol == ISDN_PTYPE_EURO)
-		sprintf(ic->parm.num, "E%02X%02X", chanp->proc->para.loc & 0x7f,
+		sprintf(ic.parm.num, "E%02X%02X", chanp->proc->para.loc & 0x7f,
 			chanp->proc->para.cause & 0x7f);
 	else
-		sprintf(ic->parm.num, "%02X%02X", chanp->proc->para.loc & 0x7f,
+		sprintf(ic.parm.num, "%02X%02X", chanp->proc->para.loc & 0x7f,
 			chanp->proc->para.cause & 0x7f);
-	chanp->cs->iif.statcallb(ic);
+	chanp->cs->iif.statcallb(&ic);
 }
 
-static void
-lli_d_established(struct FsmInst *fi, int event, void *arg)
+static inline void
+lli_close(struct FsmInst *fi)
 {
-	struct Channel *chanp = fi->userdata;
+        struct Channel *chanp = fi->userdata;
 
-	test_and_set_bit(FLG_ESTAB_D, &chanp->Flags);
-	if (chanp->leased) {
-		isdn_ctrl ic;
-		int ret;
-
-		chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan);
-		FsmChangeState(fi, ST_IN_WAIT_LL);
-		test_and_set_bit(FLG_CALL_REC, &chanp->Flags);
-		if (chanp->debug & 1)
-			link_debug(chanp, 0, "STAT_ICALL_LEASED");
-		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_ICALL;
-		ic.arg = chanp->chan;
-		ic.parm.setup.si1 = 7;
-		ic.parm.setup.si2 = 0;
-		ic.parm.setup.plan = 0;
-		ic.parm.setup.screen = 0;
-		sprintf(ic.parm.setup.eazmsn,"%d", chanp->chan + 1);
-		sprintf(ic.parm.setup.phone,"LEASED%d", chanp->cs->myid);
-		ret = chanp->cs->iif.statcallb(&ic);
-		if (chanp->debug & 1)
-			link_debug(chanp, 1, "statcallb ret=%d", ret);
-		if (!ret) {
-			chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
-			FsmChangeState(fi, ST_NULL);
-		}
-	} else if (fi->state == ST_WAIT_DSHUTDOWN)
-		FsmChangeState(fi, ST_NULL);
+        FsmChangeState(fi, ST_NULL);
+        chanp->Flags = 0;
+        chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
+}
+
+ static void
+lli_leased_in(struct FsmInst *fi, int event, void *arg)
+{
+        struct Channel *chanp = fi->userdata;
+
+        isdn_ctrl ic;
+        int ret;
+ 
+        chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan);
+        FsmChangeState(fi, ST_IN_WAIT_LL);
+        if (chanp->debug & 1)
+                link_debug(chanp, 0, "STAT_ICALL_LEASED");
+        ic.driver = chanp->cs->myid;
+	ic.command = ((chanp->chan < 2) ? ISDN_STAT_ICALL : ISDN_STAT_ICALLW);
+        ic.arg = chanp->chan;
+        ic.parm.setup.si1 = 7;
+        ic.parm.setup.si2 = 0;
+        ic.parm.setup.plan = 0;
+        ic.parm.setup.screen = 0;
+        sprintf(ic.parm.setup.eazmsn,"%d", chanp->chan + 1);
+        sprintf(ic.parm.setup.phone,"LEASED%d", chanp->cs->myid);
+        ret = chanp->cs->iif.statcallb(&ic);
+        if (chanp->debug & 1)
+                link_debug(chanp, 1, "statcallb ret=%d", ret);
+ 
+        if (!ret) {
+                chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
+                FsmChangeState(fi, ST_NULL);
+        }
 }
 
-static void
-lli_d_released(struct FsmInst *fi, int event, void *arg)
-{
-	struct Channel *chanp = fi->userdata;
-
-	test_and_clear_bit(FLG_START_D, &chanp->Flags);
-}
 
 /*
  * Dial out
  */
 static void
+lli_init_bchan_out(struct FsmInst *fi, int event, void *arg)
+{
+        struct Channel *chanp = fi->userdata;
+ 
+        FsmChangeState(fi, ST_WAIT_BCONN);
+        if (chanp->debug & 1)
+                link_debug(chanp, 0, "STAT_DCONN");
+        HL_LL(chanp, ISDN_STAT_DCONN);
+        init_b_st(chanp, 0);
+        chanp->b_st->lli.l4l3(chanp->b_st, DL_ESTABLISH | REQUEST, NULL);
+}
+
+static void
 lli_prep_dialout(struct FsmInst *fi, int event, void *arg)
 {
 	struct Channel *chanp = fi->userdata;
 
-	FsmChangeState(fi, ST_OUT_WAIT_D);
 	FsmDelTimer(&chanp->drel_timer, 60);
 	FsmDelTimer(&chanp->dial_timer, 73);
 	chanp->l2_active_protocol = chanp->l2_protocol;
 	chanp->incoming = 0;
-	if (test_bit(FLG_ESTAB_D, &chanp->Flags)) {
-		FsmEvent(fi, EV_DLEST, NULL);
-	} else {
-		chanp->Flags = 0;
-		if (EV_RESUME == event)
-			test_and_set_bit(FLG_RESUME, &chanp->Flags);
-		test_and_set_bit(FLG_START_D, &chanp->Flags);
-		chanp->d_st->lli.l4l3(chanp->d_st, DL_ESTABLISH | REQUEST, NULL);
-	}
-}
 
-static void
-lli_do_dialout(struct FsmInst *fi, int event, void *arg)
-{
-	struct Channel *chanp = fi->userdata;
-	int ev;
-
-	FsmChangeState(fi, ST_OUT_DIAL);
-	chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan);
-	if (test_and_clear_bit(FLG_RESUME, &chanp->Flags))
-		ev = CC_RESUME | REQUEST;
-	else
-		ev = CC_SETUP | REQUEST;
-	if (chanp->leased) {
-		FsmEvent(&chanp->fi, EV_SETUP_CNF, NULL);
-	} else {
-		test_and_set_bit(FLG_ESTAB_D, &chanp->Flags);
-		chanp->d_st->lli.l4l3(chanp->d_st, ev, chanp);
-		test_and_set_bit(FLG_CALL_SEND, &chanp->Flags);
-	}
+        chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan);
+        if (chanp->leased) {
+                lli_init_bchan_out(fi, event, arg);
+        } else {
+                FsmChangeState(fi, ST_OUT_DIAL);
+                chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP | REQUEST, chanp);
+        }
 }
 
 static void
-lli_init_bchan_out(struct FsmInst *fi, int event, void *arg)
+lli_resume(struct FsmInst *fi, int event, void *arg)
 {
 	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
 
-	FsmChangeState(fi, ST_WAIT_BCONN);
-	test_and_set_bit(FLG_LL_DCONN, &chanp->Flags);
-	if (chanp->debug & 1)
-		link_debug(chanp, 0, "STAT_DCONN");
-	ic.driver = chanp->cs->myid;
-	ic.command = ISDN_STAT_DCONN;
-	ic.arg = chanp->chan;
-	chanp->cs->iif.statcallb(&ic);
-	init_b_st(chanp, 0);
-	test_and_set_bit(FLG_START_B, &chanp->Flags);
-	chanp->b_st->lli.l4l3(chanp->b_st, DL_ESTABLISH | REQUEST, NULL);
+        FsmDelTimer(&chanp->drel_timer, 60);
+        FsmDelTimer(&chanp->dial_timer, 73);
+        chanp->l2_active_protocol = chanp->l2_protocol;
+        chanp->incoming = 0;
+ 
+        chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan);
+        if (chanp->leased) {
+                lli_init_bchan_out(fi, event, arg);
+        } else {
+                FsmChangeState(fi, ST_OUT_DIAL);
+                chanp->d_st->lli.l4l3(chanp->d_st, CC_RESUME | REQUEST, chanp);
+        }
 }
 
 static void
@@ -438,12 +439,15 @@
 	struct Channel *chanp = fi->userdata;
 	isdn_ctrl ic;
 
+
 	FsmChangeState(fi, ST_ACTIVE);
 	chanp->data_open = !0;
-	test_and_set_bit(FLG_CONNECT_B, &chanp->Flags);
+	if (chanp->bcs->conmsg)
+		strcpy(ic.parm.num, chanp->bcs->conmsg);
+	else
+		ic.parm.num[0] = 0;
 	if (chanp->debug & 1)
-		link_debug(chanp, 0, "STAT_BCONN");
-	test_and_set_bit(FLG_LL_BCONN, &chanp->Flags);
+		link_debug(chanp, 0, "STAT_BCONN %s", ic.parm.num);
 	ic.driver = chanp->cs->myid;
 	ic.command = ISDN_STAT_BCONN;
 	ic.arg = chanp->chan;
@@ -451,6 +455,7 @@
 	chanp->cs->cardmsg(chanp->cs, MDL_INFO_CONN, (void *) (long)chanp->chan);
 }
 
+
 /*
  * RESUME
  */
@@ -458,27 +463,6 @@
 /* incomming call */
 
 static void
-lli_start_dchan(struct FsmInst *fi, int event, void *arg)
-{
-	struct Channel *chanp = fi->userdata;
-
-	FsmChangeState(fi, ST_IN_WAIT_D);
-	FsmDelTimer(&chanp->drel_timer, 61);
-	if (event == EV_ACCEPTD)
-		test_and_set_bit(FLG_DO_CONNECT, &chanp->Flags);
-	else if (event == EV_HANGUP) {
-		test_and_set_bit(FLG_DO_HANGUP, &chanp->Flags);
-#ifdef ALERT_REJECT
-		test_and_set_bit(FLG_DO_ALERT, &chanp->Flags);
-#endif
-	}
-	if (test_bit(FLG_ESTAB_D, &chanp->Flags)) {
-		FsmEvent(fi, EV_DLEST, NULL);
-	} else if (!test_and_set_bit(FLG_START_D, &chanp->Flags))
-		chanp->d_st->lli.l4l3(chanp->d_st, DL_ESTABLISH | REQUEST, NULL);
-}
-
-static void
 lli_deliver_call(struct FsmInst *fi, int event, void *arg)
 {
 	struct Channel *chanp = fi->userdata;
@@ -493,11 +477,11 @@
 	 */
 	if (1) { /* for only one TEI */
 		FsmChangeState(fi, ST_IN_WAIT_LL);
-		test_and_set_bit(FLG_CALL_REC, &chanp->Flags);
 		if (chanp->debug & 1)
-			link_debug(chanp, 0, "STAT_ICALL");
+			link_debug(chanp, 0, (chanp->chan < 2) ? "STAT_ICALL" : "STAT_ICALLW");
 		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_ICALL;
+		ic.command = ((chanp->chan < 2) ? ISDN_STAT_ICALL : ISDN_STAT_ICALLW);
+
 		ic.arg = chanp->chan;
 		/*
 		 * No need to return "unknown" for calls without OAD,
@@ -507,118 +491,95 @@
 		ret = chanp->cs->iif.statcallb(&ic);
 		if (chanp->debug & 1)
 			link_debug(chanp, 1, "statcallb ret=%d", ret);
+
 		switch (ret) {
-			case 1:	/* OK, anybody likes this call */
+			case 1:	/* OK, someone likes this call */
 				FsmDelTimer(&chanp->drel_timer, 61);
-				if (test_bit(FLG_ESTAB_D, &chanp->Flags)) {
-					FsmChangeState(fi, ST_IN_ALERT_SEND);
-					test_and_set_bit(FLG_CALL_ALERT, &chanp->Flags);
-					chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc);
-				} else {
-					test_and_set_bit(FLG_DO_ALERT, &chanp->Flags);
-					FsmChangeState(fi, ST_IN_WAIT_D);
-					test_and_set_bit(FLG_START_D, &chanp->Flags);
-					chanp->d_st->lli.l4l3(chanp->d_st,
-						DL_ESTABLISH | REQUEST, NULL);
-				}
+				FsmChangeState(fi, ST_IN_ALERT_SENT);
+				chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc);
+				break;
+	      	        case 4: /* direct redirect */
+		        case 3: /* Proceeding desired */
+				FsmDelTimer(&chanp->drel_timer, 61);
+				FsmChangeState(fi, ST_IN_PROCEED_SEND);
+                                chanp->d_st->lli.l4l3(chanp->d_st, CC_PROCEED_SEND | REQUEST, chanp->proc);
+                                if (ret == 4)
+				 { chanp->setup = ic.parm.setup;
+				   chanp->d_st->lli.l4l3(chanp->d_st, CC_REDIR | REQUEST, chanp->proc);
+                                 }   
 				break;
 			case 2:	/* Rejecting Call */
-				test_and_clear_bit(FLG_CALL_REC, &chanp->Flags);
 				break;
 			case 0:	/* OK, nobody likes this call */
 			default:	/* statcallb problems */
 				chanp->d_st->lli.l4l3(chanp->d_st, CC_IGNORE | REQUEST, chanp->proc);
 				chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
 				FsmChangeState(fi, ST_NULL);
-				if (test_bit(FLG_ESTAB_D, &chanp->Flags) &&
-					!test_bit(FLG_PTP, &chanp->d_st->l2.flag))
-					FsmRestartTimer(&chanp->drel_timer, DREL_TIMER_VALUE, EV_SHUTDOWN_D, NULL, 61);
 				break;
 		}
 	} else {
 		chanp->d_st->lli.l4l3(chanp->d_st, CC_IGNORE | REQUEST, chanp->proc);
 		chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
-		FsmChangeState(fi, ST_NULL);
-		if (test_bit(FLG_ESTAB_D, &chanp->Flags) &&
-			!test_bit(FLG_PTP, &chanp->d_st->l2.flag))
-			FsmRestartTimer(&chanp->drel_timer, DREL_TIMER_VALUE, EV_SHUTDOWN_D, NULL, 62);
 	}
 }
 
 static void
-lli_establish_d(struct FsmInst *fi, int event, void *arg)
+lli_send_dconnect(struct FsmInst *fi, int event, void *arg)
 {
-	/* This establish the D-channel for pending L3 messages
-	 * without blocking the channel
-	 */
 	struct Channel *chanp = fi->userdata;
 
-	test_and_set_bit(FLG_DO_ESTAB, &chanp->Flags);
-	FsmChangeState(fi, ST_IN_WAIT_D);
-	test_and_set_bit(FLG_START_D, &chanp->Flags);
-	chanp->d_st->lli.l4l3(chanp->d_st, DL_ESTABLISH | REQUEST, NULL);
+	FsmChangeState(fi, ST_IN_WAIT_CONN_ACK);
+	chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP | RESPONSE, chanp->proc);
 }
 
 static void
-lli_do_action(struct FsmInst *fi, int event, void *arg)
+lli_send_alert(struct FsmInst *fi, int event, void *arg)
 {
 	struct Channel *chanp = fi->userdata;
 
-	test_and_set_bit(FLG_ESTAB_D, &chanp->Flags);
-	if (chanp->leased) {
-		FsmChangeState(fi, ST_IN_WAIT_CONN_ACK);
-		test_and_clear_bit(FLG_DO_ALERT, &chanp->Flags);
-		test_and_clear_bit(FLG_DO_CONNECT, &chanp->Flags);
-		FsmEvent(&chanp->fi, EV_SETUP_CMPL_IND, NULL);
-	} else if (test_and_clear_bit(FLG_DO_CONNECT, &chanp->Flags) &&
-		!test_bit(FLG_DO_HANGUP, &chanp->Flags)) {
-		FsmChangeState(fi, ST_IN_WAIT_CONN_ACK);
-		test_and_clear_bit(FLG_DO_ALERT, &chanp->Flags);
-		chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP | RESPONSE, chanp->proc);
-	} else if (test_and_clear_bit(FLG_DO_ALERT, &chanp->Flags)) {
-		if (test_bit(FLG_DO_HANGUP, &chanp->Flags))
-			FsmRestartTimer(&chanp->drel_timer, 40, EV_HANGUP, NULL, 63);
-		FsmChangeState(fi, ST_IN_ALERT_SEND);
-		test_and_set_bit(FLG_CALL_ALERT, &chanp->Flags);
-		chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc);
-	} else if (test_and_clear_bit(FLG_DO_HANGUP, &chanp->Flags)) {
-		FsmChangeState(fi, ST_WAIT_DRELEASE);
-		chanp->proc->para.cause = 0x15;		/* Call Rejected */
-		chanp->d_st->lli.l4l3(chanp->d_st, CC_REJECT | REQUEST, chanp->proc);
-		test_and_set_bit(FLG_DISC_SEND, &chanp->Flags);
-	}
+	FsmChangeState(fi, ST_IN_ALERT_SENT);
+	chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc);
 }
 
 static void
-lli_send_dconnect(struct FsmInst *fi, int event, void *arg)
+lli_send_redir(struct FsmInst *fi, int event, void *arg)
 {
 	struct Channel *chanp = fi->userdata;
 
-	FsmChangeState(fi, ST_IN_WAIT_CONN_ACK);
-	chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP | RESPONSE, chanp->proc);
+	chanp->d_st->lli.l4l3(chanp->d_st, CC_REDIR | REQUEST, chanp->proc);
 }
 
 static void
 lli_init_bchan_in(struct FsmInst *fi, int event, void *arg)
 {
 	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
 
 	FsmChangeState(fi, ST_WAIT_BCONN);
-	test_and_set_bit(FLG_LL_DCONN, &chanp->Flags);
 	if (chanp->debug & 1)
 		link_debug(chanp, 0, "STAT_DCONN");
-	ic.driver = chanp->cs->myid;
-	ic.command = ISDN_STAT_DCONN;
-	ic.arg = chanp->chan;
-	chanp->cs->iif.statcallb(&ic);
+	HL_LL(chanp, ISDN_STAT_DCONN);
 	chanp->l2_active_protocol = chanp->l2_protocol;
 	chanp->incoming = !0;
 	init_b_st(chanp, !0);
-	test_and_set_bit(FLG_START_B, &chanp->Flags);
 	chanp->b_st->lli.l4l3(chanp->b_st, DL_ESTABLISH | REQUEST, NULL);
 }
 
+static void
+lli_setup_rsp(struct FsmInst *fi, int event, void *arg)
+{
+        struct Channel *chanp = fi->userdata;
+ 
+        if (chanp->leased) {
+                lli_init_bchan_in(fi, event, arg);
+        } else {
+                FsmChangeState(fi, ST_IN_WAIT_CONN_ACK);
+#ifdef WANT_ALERT
+                chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc);
+#endif
+               chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP | RESPONSE, chanp->proc);
+       }
+}
+
 /* Call suspend */
 
 static void
@@ -632,82 +593,52 @@
 /* Call clearing */
 
 static void
-lli_cancel_call(struct FsmInst *fi, int event, void *arg)
+lli_disconnect_req(struct FsmInst *fi, int event, void *arg)
 {
 	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
 
 	FsmChangeState(fi, ST_WAIT_DRELEASE);
-	if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) {
-		if (chanp->debug & 1)
-			link_debug(chanp, 0, "STAT_BHUP");
-		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_BHUP;
-		ic.arg = chanp->chan;
-		chanp->cs->iif.statcallb(&ic);
-	}
-	if (test_and_clear_bit(FLG_START_B, &chanp->Flags))
-		release_b_st(chanp);
-	chanp->proc->para.cause = 0x10;		/* Normal Call Clearing */
+	chanp->proc->para.cause = 0x10;	/* Normal Call Clearing */
 	chanp->d_st->lli.l4l3(chanp->d_st, CC_DISCONNECT | REQUEST, chanp->proc);
-	test_and_set_bit(FLG_DISC_SEND, &chanp->Flags);
 }
 
 static void
-lli_shutdown_d(struct FsmInst *fi, int event, void *arg)
+lli_disconnect_reject(struct FsmInst *fi, int event, void *arg)
 {
-	struct Channel *chanp = fi->userdata;
+        struct Channel *chanp = fi->userdata;
 
-	FsmDelTimer(&chanp->drel_timer, 62);
-	if (test_bit(FLG_PTP, &chanp->d_st->l2.flag)) {
-		FsmChangeState(fi, ST_NULL);
-	} else {
-		if (!test_bit(FLG_TWO_DCHAN, &chanp->cs->HW_Flags)) {
-			if (chanp->chan) {
-				if (chanp->cs->channel[0].fi.state != ST_NULL)
-					return;
-			} else {
-				if (chanp->cs->channel[1].fi.state != ST_NULL)
-					return;
-			}
-		}
-		FsmChangeState(fi, ST_WAIT_DSHUTDOWN);
-		test_and_clear_bit(FLG_ESTAB_D, &chanp->Flags);
-		chanp->d_st->lli.l4l3(chanp->d_st, DL_RELEASE | REQUEST, NULL);
-	}
+        FsmChangeState(fi, ST_WAIT_DRELEASE);
+        chanp->proc->para.cause = 0x15;         /* Call Rejected */
+        chanp->d_st->lli.l4l3(chanp->d_st, CC_DISCONNECT | REQUEST, chanp->proc);
 }
 
 static void
-lli_timeout_d(struct FsmInst *fi, int event, void *arg)
+lli_dhup_close(struct FsmInst *fi, int event, void *arg)
 {
-	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
+        struct Channel *chanp = fi->userdata;
 
-	test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags);
-	if (chanp->debug & 1)
-		link_debug(chanp, 0, "STAT_DHUP");
-	lli_deliver_cause(chanp, &ic);
-	ic.driver = chanp->cs->myid;
-	ic.command = ISDN_STAT_DHUP;
-	ic.arg = chanp->chan;
-	chanp->cs->iif.statcallb(&ic);
-	FsmChangeState(fi, ST_NULL);
-	chanp->Flags = 0;
-	test_and_set_bit(FLG_ESTAB_D, &chanp->Flags);
-	if (!test_bit(FLG_PTP, &chanp->d_st->l2.flag))
-		FsmAddTimer(&chanp->drel_timer, DREL_TIMER_VALUE, EV_SHUTDOWN_D, NULL, 60);
-	chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
+        if (chanp->debug & 1)
+                link_debug(chanp, 0, "STAT_DHUP");
+        lli_deliver_cause(chanp);
+        HL_LL(chanp, ISDN_STAT_DHUP);
+ 
+        lli_close(fi);
 }
 
 static void
-lli_go_null(struct FsmInst *fi, int event, void *arg)
+lli_reject_req(struct FsmInst *fi, int event, void *arg)
 {
-	struct Channel *chanp = fi->userdata;
+        struct Channel *chanp = fi->userdata;
 
-	FsmChangeState(fi, ST_NULL);
-	chanp->Flags = 0;
-	FsmDelTimer(&chanp->drel_timer, 63);
-	chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
+#ifndef ALERT_REJECT
+        chanp->proc->para.cause = 0x15;         /* Call Rejected */
+        chanp->d_st->lli.l4l3(chanp->d_st, CC_REJECT | REQUEST, chanp->proc);
+        lli_dhup_close(fi, event, arg);
+#else
+        FsmRestartTimer(&chanp->drel_timer, 40, EV_HANGUP, NULL, 63);
+        FsmChangeState(fi, ST_IN_ALERT_SENT);
+        chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc);
+#endif
 }
 
 static void
@@ -717,30 +648,15 @@
 
 	chanp->data_open = 0;
 	FsmChangeState(fi, ST_WAIT_BRELEASE);
-	test_and_clear_bit(FLG_CONNECT_B, &chanp->Flags);
 	chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL);
 }
 
 static void
-lli_send_d_disc(struct FsmInst *fi, int event, void *arg)
+lli_start_disc(struct FsmInst *fi, int event, void *arg)
 {
 	struct Channel *chanp = fi->userdata;
 	isdn_ctrl ic;
 
-	if (test_bit(FLG_DISC_REC, &chanp->Flags) ||
-		test_bit(FLG_REL_REC, &chanp->Flags))
-		return;
-	FsmChangeState(fi, ST_WAIT_DRELEASE);
-	if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) {
-		if (chanp->debug & 1)
-			link_debug(chanp, 0, "STAT_BHUP");
-		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_BHUP;
-		ic.arg = chanp->chan;
-		chanp->cs->iif.statcallb(&ic);
-	}
-	if (test_and_clear_bit(FLG_START_B, &chanp->Flags))
-		release_b_st(chanp);
 	if (chanp->leased) {
 		ic.command = ISDN_STAT_CAUSE;
 		ic.arg = chanp->chan;
@@ -748,43 +664,46 @@
 		chanp->cs->iif.statcallb(&ic);
 		if (chanp->debug & 1)
 			link_debug(chanp, 0, "STAT_DHUP");
-		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_DHUP;
-		ic.arg = chanp->chan;
-		chanp->cs->iif.statcallb(&ic);
-		FsmChangeState(fi, ST_WAIT_DSHUTDOWN);
-		test_and_clear_bit(FLG_ESTAB_D, &chanp->Flags);
-		chanp->d_st->lli.l4l3(chanp->d_st, DL_RELEASE | REQUEST, NULL);
+		HL_LL(chanp, ISDN_STAT_DHUP);
+		lli_close(fi);
 	} else {
-		if (test_and_clear_bit(FLG_DO_HANGUP, &chanp->Flags))
-			chanp->proc->para.cause = 0x15;		/* Call Reject */
-		else
-			chanp->proc->para.cause = 0x10;		/* Normal Call Clearing */
-		chanp->d_st->lli.l4l3(chanp->d_st, CC_DISCONNECT | REQUEST, chanp->proc);
-		test_and_set_bit(FLG_DISC_SEND, &chanp->Flags);
+	        lli_disconnect_req(fi, event, arg);
 	}
 }
 
 static void
-lli_released_bchan(struct FsmInst *fi, int event, void *arg)
+lli_rel_b_disc(struct FsmInst *fi, int event, void *arg)
 {
-	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
+        struct Channel *chanp = fi->userdata;
+ 
+        release_b_st(chanp);
+        lli_start_disc(fi, event, arg);
+}
 
-	FsmChangeState(fi, ST_WAIT_DCOMMAND);
-	chanp->data_open = 0;
-	if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) {
-		if (chanp->debug & 1)
-			link_debug(chanp, 0, "STAT_BHUP");
-		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_BHUP;
-		ic.arg = chanp->chan;
-		chanp->cs->iif.statcallb(&ic);
-	}
-	release_b_st(chanp);
-	test_and_clear_bit(FLG_START_B, &chanp->Flags);
+static void
+lli_bhup_disc(struct FsmInst *fi, int event, void *arg)
+{
+        struct Channel *chanp = fi->userdata;
+  
+        if (chanp->debug & 1)
+                link_debug(chanp, 0, "STAT_BHUP");
+        HL_LL(chanp, ISDN_STAT_BHUP);
+ 
+        lli_rel_b_disc(fi, event, arg);
 }
 
+static void
+lli_bhup_rel_b(struct FsmInst *fi, int event, void *arg)
+{
+        struct Channel *chanp = fi->userdata;
+
+        FsmChangeState(fi, ST_WAIT_DCOMMAND);
+        chanp->data_open = 0;
+                if (chanp->debug & 1)
+                link_debug(chanp, 0, "STAT_BHUP");
+        HL_LL(chanp, ISDN_STAT_BHUP);
+        release_b_st(chanp);
+}
 
 static void
 lli_release_bchan(struct FsmInst *fi, int event, void *arg)
@@ -792,387 +711,235 @@
 	struct Channel *chanp = fi->userdata;
 
 	chanp->data_open = 0;
-	test_and_set_bit(FLG_DISC_REC, &chanp->Flags);
 	FsmChangeState(fi, ST_WAIT_BREL_DISC);
-	test_and_clear_bit(FLG_CONNECT_B, &chanp->Flags);
 	chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL);
 }
 
+
 static void
-lli_received_d_rel(struct FsmInst *fi, int event, void *arg)
+lli_rel_b_dhup(struct FsmInst *fi, int event, void *arg)
 {
-	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
+        struct Channel *chanp = fi->userdata;
 
-	chanp->data_open = 0;
-	FsmChangeState(fi, ST_NULL);
-	test_and_set_bit(FLG_REL_REC, &chanp->Flags);
-	if (test_and_clear_bit(FLG_CONNECT_B, &chanp->Flags)) {
-		chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL);
-	}
-	if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) {
-		if (chanp->debug & 1)
-			link_debug(chanp, 0, "STAT_BHUP");
-		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_BHUP;
-		ic.arg = chanp->chan;
-		chanp->cs->iif.statcallb(&ic);
-	}
-	if (test_and_clear_bit(FLG_START_B, &chanp->Flags))
-		release_b_st(chanp);
-	if (chanp->debug & 1)
-		link_debug(chanp, 0, "STAT_DHUP");
-	lli_deliver_cause(chanp, &ic);
-	ic.driver = chanp->cs->myid;
-	ic.command = ISDN_STAT_DHUP;
-	ic.arg = chanp->chan;
-	chanp->cs->iif.statcallb(&ic);
-	test_and_clear_bit(FLG_DISC_SEND, &chanp->Flags);
-	test_and_clear_bit(FLG_CALL_REC, &chanp->Flags);
-	test_and_clear_bit(FLG_CALL_ALERT, &chanp->Flags);
-	test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags);
-	test_and_clear_bit(FLG_CALL_SEND, &chanp->Flags);
-	lli_timeout_d(fi, event, arg);
+        release_b_st(chanp);
+        lli_dhup_close(fi, event, arg);
 }
 
 static void
-lli_received_d_relcnf(struct FsmInst *fi, int event, void *arg)
+lli_bhup_dhup(struct FsmInst *fi, int event, void *arg)
 {
-	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
+        struct Channel *chanp = fi->userdata;
 
-	chanp->data_open = 0;
-	FsmChangeState(fi, ST_NULL);
-	if (test_and_clear_bit(FLG_CONNECT_B, &chanp->Flags)) {
-		chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL);
-	}
-	if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) {
-		if (chanp->debug & 1)
-			link_debug(chanp, 0, "STAT_BHUP");
-		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_BHUP;
-		ic.arg = chanp->chan;
-		chanp->cs->iif.statcallb(&ic);
-	}
-	if (test_and_clear_bit(FLG_START_B, &chanp->Flags))
-		release_b_st(chanp);
-	if (chanp->debug & 1)
-		link_debug(chanp, 0, "STAT_DHUP");
-	lli_deliver_cause(chanp, &ic);
-	ic.driver = chanp->cs->myid;
-	ic.command = ISDN_STAT_DHUP;
-	ic.arg = chanp->chan;
-	chanp->cs->iif.statcallb(&ic);
-	test_and_clear_bit(FLG_DISC_SEND, &chanp->Flags);
-	test_and_clear_bit(FLG_CALL_REC, &chanp->Flags);
-	test_and_clear_bit(FLG_CALL_ALERT, &chanp->Flags);
-	test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags);
-	test_and_clear_bit(FLG_CALL_SEND, &chanp->Flags);
-	lli_timeout_d(fi, event, arg);
+        if (chanp->debug & 1)
+                link_debug(chanp, 0, "STAT_BHUP");
+        HL_LL(chanp, ISDN_STAT_BHUP);
+ 
+        lli_rel_b_dhup(fi, event, arg);
 }
 
 static void
-lli_received_d_disc(struct FsmInst *fi, int event, void *arg)
+lli_abort(struct FsmInst *fi, int event, void *arg)
 {
-	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
+        struct Channel *chanp = fi->userdata;
 
-	chanp->data_open = 0;
-	FsmChangeState(fi, ST_WAIT_D_REL_CNF);
-	test_and_set_bit(FLG_DISC_REC, &chanp->Flags);
-	if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) {
-		if (chanp->debug & 1)
-			link_debug(chanp, 0, "STAT_BHUP");
-		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_BHUP;
-		ic.arg = chanp->chan;
-		chanp->cs->iif.statcallb(&ic);
-	}
-	if (test_and_clear_bit(FLG_START_B, &chanp->Flags))
-		release_b_st(chanp);
-	if (chanp->debug & 1)
-		link_debug(chanp, 0, "STAT_DHUP");
-	lli_deliver_cause(chanp, &ic);
-	ic.driver = chanp->cs->myid;
-	ic.command = ISDN_STAT_DHUP;
-	ic.arg = chanp->chan;
-	chanp->cs->iif.statcallb(&ic);
-	test_and_clear_bit(FLG_CALL_ALERT, &chanp->Flags);
-	test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags);
-	test_and_clear_bit(FLG_CALL_SEND, &chanp->Flags);
-	chanp->d_st->lli.l4l3(chanp->d_st, CC_RELEASE | REQUEST, chanp->proc);
+        chanp->data_open = 0;
+        chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL);
+ 
+        lli_bhup_dhup(fi, event, arg);
 }
-
-/* processing charge info */
+ 
 static void
-lli_charge_info(struct FsmInst *fi, int event, void *arg)
+lli_release_req(struct FsmInst *fi, int event, void *arg)
 {
-	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
-
-	ic.driver = chanp->cs->myid;
-	ic.command = ISDN_STAT_CINF;
-	ic.arg = chanp->chan;
-	sprintf(ic.parm.num, "%d", chanp->proc->para.chargeinfo);
-	chanp->cs->iif.statcallb(&ic);
+        struct Channel *chanp = fi->userdata;
+ 
+        FsmChangeState(fi, ST_WAIT_D_REL_CNF);
+        chanp->d_st->lli.l4l3(chanp->d_st, CC_RELEASE | REQUEST, chanp->proc);
 }
 
-/* error procedures */
-
 static void
-lli_no_dchan(struct FsmInst *fi, int event, void *arg)
+lli_rel_b_release_req(struct FsmInst *fi, int event, void *arg)
 {
-	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
-
-	if (chanp->debug & 1)
-		link_debug(chanp, 0, "STAT_NODCH");
-	ic.driver = chanp->cs->myid;
-	ic.command = ISDN_STAT_NODCH;
-	ic.arg = chanp->chan;
-	chanp->cs->iif.statcallb(&ic);
-	chanp->Flags = 0;
-	FsmChangeState(fi, ST_NULL);
-	chanp->d_st->lli.l4l3(chanp->d_st, DL_RELEASE | REQUEST, NULL);
+        struct Channel *chanp = fi->userdata;
+ 
+        release_b_st(chanp);
+        lli_release_req(fi, event, arg);
 }
 
 static void
-lli_no_dchan_ready(struct FsmInst *fi, int event, void *arg)
+lli_bhup_release_req(struct FsmInst *fi, int event, void *arg)
 {
-	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
-
-	if (chanp->debug & 1)
-		link_debug(chanp, 0, "STAT_DHUP");
-	ic.driver = chanp->cs->myid;
-	ic.command = ISDN_STAT_DHUP;
-	ic.arg = chanp->chan;
-	chanp->cs->iif.statcallb(&ic);
+        struct Channel *chanp = fi->userdata;
+ 
+        if (chanp->debug & 1)
+                link_debug(chanp, 0, "STAT_BHUP");
+        HL_LL(chanp, ISDN_STAT_BHUP);
+ 
+        lli_rel_b_release_req(fi, event, arg);
 }
 
+
+/* processing charge info */
 static void
-lli_no_dchan_in(struct FsmInst *fi, int event, void *arg)
+lli_charge_info(struct FsmInst *fi, int event, void *arg)
 {
 	struct Channel *chanp = fi->userdata;
 	isdn_ctrl ic;
 
-	if (chanp->debug & 1)
-		link_debug(chanp, 0, "STAT_DHUP");
 	ic.driver = chanp->cs->myid;
-	ic.command = ISDN_STAT_DHUP;
+	ic.command = ISDN_STAT_CINF;
 	ic.arg = chanp->chan;
+	sprintf(ic.parm.num, "%d", chanp->proc->para.chargeinfo);
 	chanp->cs->iif.statcallb(&ic);
-	chanp->d_st->lli.l4l3(chanp->d_st, CC_DLRL | REQUEST, chanp->proc);
-	chanp->Flags = 0;
-	FsmChangeState(fi, ST_NULL);
-	chanp->d_st->lli.l4l3(chanp->d_st, DL_RELEASE | REQUEST, NULL);
 }
 
+/* error procedures */
+
 static void
-lli_no_setup_rsp(struct FsmInst *fi, int event, void *arg)
+lli_dchan_not_ready(struct FsmInst *fi, int event, void *arg)
 {
 	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
 
-	FsmChangeState(fi, ST_NULL);
-	test_and_clear_bit(FLG_CALL_SEND, &chanp->Flags);
 	if (chanp->debug & 1)
 		link_debug(chanp, 0, "STAT_DHUP");
-	ic.driver = chanp->cs->myid;
-	ic.command = ISDN_STAT_DHUP;
-	ic.arg = chanp->chan;
-	chanp->cs->iif.statcallb(&ic);
-	lli_shutdown_d(fi, event, arg);
+        HL_LL(chanp, ISDN_STAT_DHUP); 
 }
 
 static void
-lli_setup_err(struct FsmInst *fi, int event, void *arg)
+lli_no_setup_rsp(struct FsmInst *fi, int event, void *arg)
 {
 	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
 
-	FsmChangeState(fi, ST_WAIT_DRELEASE);
-	test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags);
 	if (chanp->debug & 1)
 		link_debug(chanp, 0, "STAT_DHUP");
-	lli_deliver_cause(chanp, &ic);
-	ic.driver = chanp->cs->myid;
-	ic.command = ISDN_STAT_DHUP;
-	ic.arg = chanp->chan;
-	chanp->cs->iif.statcallb(&ic);
-	test_and_set_bit(FLG_DISC_SEND, &chanp->Flags);	/* DISCONN was sent from L3 */
+	HL_LL(chanp, ISDN_STAT_DHUP);
+        lli_close(fi); 
 }
 
 static void
-lli_connect_err(struct FsmInst *fi, int event, void *arg)
+lli_error(struct FsmInst *fi, int event, void *arg)
 {
-	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
-
-	FsmChangeState(fi, ST_WAIT_DRELEASE);
-	test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags);
-	if (chanp->debug & 1)
-		link_debug(chanp, 0, "STAT_DHUP");
-	lli_deliver_cause(chanp, &ic);
-	ic.driver = chanp->cs->myid;
-	ic.command = ISDN_STAT_DHUP;
-	ic.arg = chanp->chan;
-	chanp->cs->iif.statcallb(&ic);
-	test_and_set_bit(FLG_DISC_SEND, &chanp->Flags);	/* DISCONN was sent from L3 */
+        FsmChangeState(fi, ST_WAIT_DRELEASE);
 }
 
 static void
-lli_got_dlrl(struct FsmInst *fi, int event, void *arg)
-{
-	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
-
-	chanp->data_open = 0;
-	FsmChangeState(fi, ST_NULL);
-	if (test_and_clear_bit(FLG_CONNECT_B, &chanp->Flags)) {
-		chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL);
-	}
-	if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) {
-		if (chanp->debug & 1)
-			link_debug(chanp, 0, "STAT_BHUP");
-		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_BHUP;
-		ic.arg = chanp->chan;
-		chanp->cs->iif.statcallb(&ic);
-	}
-	if (test_and_clear_bit(FLG_START_B, &chanp->Flags))
-		release_b_st(chanp);
-	if (chanp->leased) {
-		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_CAUSE;
-		ic.arg = chanp->chan;
-		sprintf(ic.parm.num, "L%02X%02X", 0, 0x2f);
-		chanp->cs->iif.statcallb(&ic);
-		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_DHUP;
-		ic.arg = chanp->chan;
-		chanp->cs->iif.statcallb(&ic);
-		chanp->Flags = 0;
-	} else {
-		test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags);
-		if (chanp->debug & 1)
-			link_debug(chanp, 0, "STAT_DHUP");
-		if (chanp->cs->protocol == ISDN_PTYPE_EURO) {
-			chanp->proc->para.cause = 0x2f;
-			chanp->proc->para.loc = 0;
-		} else {
-			chanp->proc->para.cause = 0x70;
-			chanp->proc->para.loc = 0;
-		}
-		lli_deliver_cause(chanp, &ic);
-		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_DHUP;
-		ic.arg = chanp->chan;
-		chanp->cs->iif.statcallb(&ic);
-		chanp->d_st->lli.l4l3(chanp->d_st, CC_DLRL | REQUEST, chanp->proc);
-		chanp->Flags = 0;
-		chanp->d_st->lli.l4l3(chanp->d_st, DL_RELEASE | REQUEST, NULL);
-	}
-	chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
-}
-
-/* *INDENT-OFF* */
-static struct FsmNode fnlist[] HISAX_INITDATA =
-{
-	{ST_NULL,		EV_DIAL,		lli_prep_dialout},
-	{ST_NULL,		EV_RESUME,		lli_prep_dialout},
-	{ST_NULL,		EV_SETUP_IND,		lli_deliver_call},
-	{ST_NULL,		EV_SHUTDOWN_D,		lli_shutdown_d},
-	{ST_NULL,		EV_DLRL,		lli_go_null},
-	{ST_NULL,		EV_DLEST,		lli_d_established},
-	{ST_NULL,		EV_ESTABLISH,		lli_establish_d},
-	{ST_OUT_WAIT_D,		EV_DLEST,		lli_do_dialout},
-	{ST_OUT_WAIT_D,		EV_DLRL,		lli_no_dchan},
-	{ST_OUT_WAIT_D,		EV_HANGUP,		lli_no_dchan},
-	{ST_IN_WAIT_D,		EV_DLEST,		lli_do_action},
-	{ST_IN_WAIT_D,		EV_DLRL,		lli_no_dchan_in},
-	{ST_IN_WAIT_D,		EV_ACCEPTD,		lli_start_dchan},
-	{ST_IN_WAIT_D,		EV_HANGUP,		lli_start_dchan},
-	{ST_OUT_DIAL,		EV_SETUP_CNF,		lli_init_bchan_out},
-	{ST_OUT_DIAL,		EV_HANGUP,		lli_cancel_call},
-	{ST_OUT_DIAL,		EV_DISCONNECT_IND,	lli_received_d_disc},
-	{ST_OUT_DIAL,		EV_RELEASE_IND,		lli_received_d_rel},
-	{ST_OUT_DIAL,		EV_RELEASE_CNF,		lli_received_d_relcnf},
-	{ST_OUT_DIAL,		EV_NOSETUP_RSP,		lli_no_setup_rsp},
-	{ST_OUT_DIAL,		EV_SETUP_ERR,		lli_setup_err},
-	{ST_OUT_DIAL,		EV_DLRL,		lli_got_dlrl},
-	{ST_IN_WAIT_LL,		EV_DLEST,		lli_d_established},
-	{ST_IN_WAIT_LL,		EV_DLRL,		lli_d_released},
-	{ST_IN_WAIT_LL,		EV_ACCEPTD,		lli_start_dchan},
-	{ST_IN_WAIT_LL,		EV_HANGUP,		lli_start_dchan},
-	{ST_IN_WAIT_LL,		EV_DISCONNECT_IND,	lli_received_d_disc},
-	{ST_IN_WAIT_LL,		EV_RELEASE_IND,		lli_received_d_rel},
-	{ST_IN_WAIT_LL,		EV_RELEASE_CNF,		lli_received_d_relcnf},
-	{ST_IN_ALERT_SEND,	EV_SETUP_CMPL_IND,	lli_init_bchan_in},
-	{ST_IN_ALERT_SEND,	EV_ACCEPTD,		lli_send_dconnect},
-	{ST_IN_ALERT_SEND,	EV_HANGUP,		lli_send_d_disc},
-	{ST_IN_ALERT_SEND,	EV_DISCONNECT_IND,	lli_received_d_disc},
-	{ST_IN_ALERT_SEND,	EV_RELEASE_IND,		lli_received_d_rel},
-	{ST_IN_ALERT_SEND,	EV_RELEASE_CNF,		lli_received_d_relcnf},
-	{ST_IN_ALERT_SEND,	EV_DLRL,		lli_got_dlrl},
-	{ST_IN_WAIT_CONN_ACK,	EV_SETUP_CMPL_IND,	lli_init_bchan_in},
-	{ST_IN_WAIT_CONN_ACK,	EV_HANGUP,		lli_send_d_disc},
-	{ST_IN_WAIT_CONN_ACK,	EV_DISCONNECT_IND,	lli_received_d_disc},
-	{ST_IN_WAIT_CONN_ACK,	EV_RELEASE_IND,		lli_received_d_rel},
-	{ST_IN_WAIT_CONN_ACK,	EV_RELEASE_CNF,		lli_received_d_relcnf},
-	{ST_IN_WAIT_CONN_ACK,	EV_CONNECT_ERR,		lli_connect_err},
-	{ST_IN_WAIT_CONN_ACK,	EV_DLRL,		lli_got_dlrl},
-	{ST_WAIT_BCONN,		EV_BC_EST,		lli_go_active},
-	{ST_WAIT_BCONN,		EV_BC_REL,		lli_send_d_disc},
-	{ST_WAIT_BCONN,		EV_HANGUP,		lli_send_d_disc},
-	{ST_WAIT_BCONN,		EV_DISCONNECT_IND,	lli_received_d_disc},
-	{ST_WAIT_BCONN,		EV_RELEASE_IND,		lli_received_d_rel},
-	{ST_WAIT_BCONN,		EV_RELEASE_CNF,		lli_received_d_relcnf},
-	{ST_WAIT_BCONN,		EV_DLRL,		lli_got_dlrl},
-	{ST_WAIT_BCONN,		EV_CINF,		lli_charge_info},
-	{ST_ACTIVE,		EV_CINF,		lli_charge_info},
-	{ST_ACTIVE,		EV_BC_REL,		lli_released_bchan},
-	{ST_ACTIVE,		EV_SUSPEND,		lli_suspend},
-	{ST_ACTIVE,		EV_HANGUP,		lli_disconn_bchan},
-	{ST_ACTIVE,		EV_DISCONNECT_IND,	lli_release_bchan},
-	{ST_ACTIVE,		EV_RELEASE_CNF,		lli_received_d_relcnf},
-	{ST_ACTIVE,		EV_RELEASE_IND,		lli_received_d_rel},
-	{ST_ACTIVE,		EV_DLRL,		lli_got_dlrl},
-	{ST_WAIT_BRELEASE,	EV_BC_REL,		lli_send_d_disc},
-	{ST_WAIT_BRELEASE,	EV_DISCONNECT_IND,	lli_received_d_disc},
-	{ST_WAIT_BRELEASE,	EV_RELEASE_CNF,		lli_received_d_relcnf},
-	{ST_WAIT_BRELEASE,	EV_RELEASE_IND,		lli_received_d_rel},
-	{ST_WAIT_BRELEASE,	EV_DLRL,		lli_got_dlrl},
-	{ST_WAIT_BREL_DISC,	EV_BC_REL,		lli_received_d_disc},
-	{ST_WAIT_BREL_DISC,	EV_RELEASE_CNF,		lli_received_d_relcnf},
-	{ST_WAIT_BREL_DISC,	EV_RELEASE_IND,		lli_received_d_rel},
-	{ST_WAIT_BREL_DISC,	EV_DLRL,		lli_got_dlrl},
-	{ST_WAIT_DCOMMAND,	EV_HANGUP,		lli_send_d_disc},
-	{ST_WAIT_DCOMMAND,	EV_DISCONNECT_IND,	lli_received_d_disc},
-	{ST_WAIT_DCOMMAND,	EV_RELEASE_CNF,		lli_received_d_relcnf},
-	{ST_WAIT_DCOMMAND,	EV_RELEASE_IND,		lli_received_d_rel},
-	{ST_WAIT_DCOMMAND,	EV_DLRL,		lli_got_dlrl},
-	{ST_WAIT_DRELEASE,	EV_RELEASE_IND,		lli_timeout_d},
-	{ST_WAIT_DRELEASE,	EV_RELEASE_CNF,		lli_timeout_d},
-	{ST_WAIT_DRELEASE,	EV_RELEASE_ERR,		lli_timeout_d},
-	{ST_WAIT_DRELEASE,	EV_DIAL,		lli_no_dchan_ready},
-	{ST_WAIT_DRELEASE,	EV_DLRL,		lli_got_dlrl},
-	{ST_WAIT_D_REL_CNF,	EV_RELEASE_CNF,		lli_timeout_d},
-	{ST_WAIT_D_REL_CNF,	EV_RELEASE_ERR,		lli_timeout_d},
-/* ETS 300-104 16.1 */
-	{ST_WAIT_D_REL_CNF,     EV_RELEASE_IND,         lli_timeout_d},
-	{ST_WAIT_D_REL_CNF,	EV_DIAL,		lli_no_dchan_ready},
-	{ST_WAIT_D_REL_CNF,	EV_DLRL,		lli_got_dlrl},
-	{ST_WAIT_DSHUTDOWN,	EV_DLRL,		lli_go_null},
-	{ST_WAIT_DSHUTDOWN,	EV_DLEST,		lli_d_established},
-	{ST_WAIT_DSHUTDOWN,	EV_DIAL,		lli_prep_dialout},
-	{ST_WAIT_DSHUTDOWN,	EV_RESUME,		lli_prep_dialout},
-	{ST_WAIT_DSHUTDOWN,	EV_SETUP_IND,		lli_deliver_call},
+lli_failure_l(struct FsmInst *fi, int event, void *arg)
+{
+        struct Channel *chanp = fi->userdata;
+        isdn_ctrl ic;
+
+        FsmChangeState(fi, ST_NULL);
+        ic.driver = chanp->cs->myid;
+        ic.command = ISDN_STAT_CAUSE;
+        ic.arg = chanp->chan;
+        sprintf(ic.parm.num, "L%02X%02X", 0, 0x2f);
+        chanp->cs->iif.statcallb(&ic);
+        HL_LL(chanp, ISDN_STAT_DHUP);
+        chanp->Flags = 0;
+        chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
+}
+
+static void
+lli_rel_b_fail(struct FsmInst *fi, int event, void *arg)
+{
+        struct Channel *chanp = fi->userdata;
+
+        release_b_st(chanp);
+        lli_failure_l(fi, event, arg);
+}
+
+static void
+lli_bhup_fail(struct FsmInst *fi, int event, void *arg)
+{
+        struct Channel *chanp = fi->userdata;
+
+        if (chanp->debug & 1)
+                link_debug(chanp, 0, "STAT_BHUP");
+        HL_LL(chanp, ISDN_STAT_BHUP);
+ 
+        lli_rel_b_fail(fi, event, arg);
+}
+
+static void
+lli_failure_a(struct FsmInst *fi, int event, void *arg)
+{
+        struct Channel *chanp = fi->userdata;
+
+        chanp->data_open = 0;
+        chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL);
+ 
+        lli_bhup_fail(fi, event, arg);
+}
+
+  /* *INDENT-OFF* */
+  static struct FsmNode fnlist[] HISAX_INITDATA =
+  {
+        {ST_NULL,               EV_DIAL,                lli_prep_dialout},
+        {ST_NULL,               EV_RESUME,              lli_resume},
+        {ST_NULL,               EV_SETUP_IND,           lli_deliver_call},
+        {ST_NULL,               EV_LEASED,              lli_leased_in},
+        {ST_OUT_DIAL,           EV_SETUP_CNF,           lli_init_bchan_out},
+        {ST_OUT_DIAL,           EV_HANGUP,              lli_disconnect_req},
+        {ST_OUT_DIAL,           EV_DISCONNECT_IND,      lli_release_req},
+        {ST_OUT_DIAL,           EV_RELEASE,             lli_dhup_close},
+        {ST_OUT_DIAL,           EV_NOSETUP_RSP,         lli_no_setup_rsp},
+        {ST_OUT_DIAL,           EV_SETUP_ERR,           lli_error},
+        {ST_IN_WAIT_LL,         EV_LEASED_REL,          lli_failure_l},
+        {ST_IN_WAIT_LL,         EV_ACCEPTD,             lli_setup_rsp},
+        {ST_IN_WAIT_LL,         EV_HANGUP,              lli_reject_req},
+        {ST_IN_WAIT_LL,         EV_DISCONNECT_IND,      lli_release_req},
+        {ST_IN_WAIT_LL,         EV_RELEASE,             lli_dhup_close},
+        {ST_IN_ALERT_SENT,      EV_SETUP_CMPL_IND,      lli_init_bchan_in},
+        {ST_IN_ALERT_SENT,      EV_ACCEPTD,             lli_send_dconnect},
+        {ST_IN_ALERT_SENT,      EV_HANGUP,              lli_disconnect_reject},
+        {ST_IN_ALERT_SENT,      EV_DISCONNECT_IND,      lli_release_req},
+        {ST_IN_ALERT_SENT,      EV_RELEASE,             lli_dhup_close},
+	{ST_IN_ALERT_SENT,	EV_REDIR,		lli_send_redir},
+	{ST_IN_PROCEED_SEND,	EV_REDIR,		lli_send_redir},
+	{ST_IN_PROCEED_SEND,	EV_ALERT,		lli_send_alert},
+	{ST_IN_PROCEED_SEND,	EV_ACCEPTD,		lli_send_dconnect},
+	{ST_IN_PROCEED_SEND,	EV_HANGUP,		lli_disconnect_reject},
+	{ST_IN_PROCEED_SEND,	EV_DISCONNECT_IND,	lli_dhup_close},
+        {ST_IN_ALERT_SENT,      EV_RELEASE,             lli_dhup_close},
+        {ST_IN_WAIT_CONN_ACK,   EV_SETUP_CMPL_IND,      lli_init_bchan_in},
+        {ST_IN_WAIT_CONN_ACK,   EV_HANGUP,              lli_disconnect_req},
+        {ST_IN_WAIT_CONN_ACK,   EV_DISCONNECT_IND,      lli_release_req},
+        {ST_IN_WAIT_CONN_ACK,   EV_RELEASE,             lli_dhup_close},
+        {ST_IN_WAIT_CONN_ACK,   EV_CONNECT_ERR,         lli_error},
+        {ST_WAIT_BCONN,         EV_BC_EST,              lli_go_active},
+        {ST_WAIT_BCONN,         EV_BC_REL,              lli_rel_b_disc},
+        {ST_WAIT_BCONN,         EV_HANGUP,              lli_rel_b_disc},
+        {ST_WAIT_BCONN,         EV_DISCONNECT_IND,      lli_rel_b_release_req},
+        {ST_WAIT_BCONN,         EV_RELEASE,             lli_rel_b_dhup},
+        {ST_WAIT_BCONN,         EV_LEASED_REL,          lli_rel_b_fail},
+        {ST_WAIT_BCONN,         EV_CINF,                lli_charge_info},
+        {ST_ACTIVE,             EV_CINF,                lli_charge_info},
+        {ST_ACTIVE,             EV_BC_REL,              lli_bhup_rel_b},
+        {ST_ACTIVE,             EV_SUSPEND,             lli_suspend},
+        {ST_ACTIVE,             EV_HANGUP,              lli_disconn_bchan},
+        {ST_ACTIVE,             EV_DISCONNECT_IND,      lli_release_bchan},
+        {ST_ACTIVE,             EV_RELEASE,             lli_abort},
+        {ST_ACTIVE,             EV_LEASED_REL,          lli_failure_a},
+        {ST_WAIT_BRELEASE,      EV_BC_REL,              lli_bhup_disc},
+        {ST_WAIT_BRELEASE,      EV_DISCONNECT_IND,      lli_bhup_release_req},
+        {ST_WAIT_BRELEASE,      EV_RELEASE,             lli_bhup_dhup},
+        {ST_WAIT_BRELEASE,      EV_LEASED_REL,          lli_bhup_fail},
+        {ST_WAIT_BREL_DISC,     EV_BC_REL,              lli_bhup_release_req},
+        {ST_WAIT_BREL_DISC,     EV_RELEASE,             lli_bhup_dhup},
+        {ST_WAIT_DCOMMAND,      EV_HANGUP,              lli_start_disc},
+        {ST_WAIT_DCOMMAND,      EV_DISCONNECT_IND,      lli_release_req},
+        {ST_WAIT_DCOMMAND,      EV_RELEASE,             lli_dhup_close},
+        {ST_WAIT_DCOMMAND,      EV_LEASED_REL,          lli_failure_l},
+        {ST_WAIT_DRELEASE,      EV_RELEASE,             lli_dhup_close},
+        {ST_WAIT_DRELEASE,      EV_DIAL,                lli_dchan_not_ready},
+  /* ETS 300-104 16.1 */
+        {ST_WAIT_D_REL_CNF,     EV_RELEASE,             lli_dhup_close},
+        {ST_WAIT_D_REL_CNF,     EV_DIAL,                lli_dchan_not_ready},
 };
-/* *INDENT-ON* */
+  /* *INDENT-ON* */
 
 
-#define FNCOUNT (sizeof(fnlist)/sizeof(struct FsmNode))
+  #define FNCOUNT (sizeof(fnlist)/sizeof(struct FsmNode))
 
 HISAX_INITFUNC(void
 CallcNew(void))
@@ -1195,21 +962,23 @@
 {
 	struct PStack *st = chanp->b_st;
 
-	chanp->bcs->BC_Close(chanp->bcs);
-	switch (chanp->l2_active_protocol) {
-		case (ISDN_PROTO_L2_X75I):
-			releasestack_isdnl2(st);
-			break;
-		case (ISDN_PROTO_L2_HDLC):
-		case (ISDN_PROTO_L2_TRANS):
-//		case (ISDN_PROTO_L2_MODEM):
-			releasestack_transl2(st);
-			break;
-	}
+        if(test_and_clear_bit(FLG_START_B, &chanp->Flags)) {
+                chanp->bcs->BC_Close(chanp->bcs);
+                switch (chanp->l2_active_protocol) {
+			case (ISDN_PROTO_L2_X75I):
+				releasestack_isdnl2(st);
+				break;
+			case (ISDN_PROTO_L2_HDLC):
+			case (ISDN_PROTO_L2_TRANS):
+			case (ISDN_PROTO_L2_MODEM):
+                                releasestack_transl2(st);
+                                break;
+                }
+        } 
 }
 
 struct Channel
-*selectfreechannel(struct PStack *st)
+*selectfreechannel(struct PStack *st, int bch)
 {
 	struct IsdnCardState *cs = st->l1.hardware;
 	struct Channel *chanp = st->lli.userdata;
@@ -1219,74 +988,60 @@
 		i=1;
 	else
 		i=0;
-	while (i<2) {
+
+        if (!bch) 
+         { i = 2; /* virtual channel */
+           chanp += 2;
+         }
+
+	while (i < ((bch) ? cs->chanlimit : (2 + MAX_WAITING_CALLS))) {
 		if (chanp->fi.state == ST_NULL)
 			return (chanp);
 		chanp++;
 		i++;
 	}
-	return (NULL);
-}
-
-int
-is_activ(struct PStack *st)
-{
-	struct IsdnCardState *cs = st->l1.hardware;
-	struct Channel *chanp = st->lli.userdata;
-	int i;
 
-	if (test_bit(FLG_TWO_DCHAN, &cs->HW_Flags))
-		i=1;
-	else
-		i=0;
-	while (i<2) {
-		if (test_bit(FLG_ESTAB_D, &chanp->Flags))
-			return (1);
+        if (bch) /* number of channels is limited */ 
+         { i = 2; /* virtual channel */
+           chanp = st->lli.userdata;
+	   chanp += i;
+	   while (i < (2 + MAX_WAITING_CALLS)) {
+		if (chanp->fi.state == ST_NULL)
+			return (chanp);
 		chanp++;
 		i++;
-	}
-	return (0);
+	   }
+         }
+	return (NULL);
 }
 
+static void stat_redir_result(struct IsdnCardState *cs, int chan, ulong result)
+{	isdn_ctrl ic;
+  
+	ic.driver = cs->myid;
+	ic.command = ISDN_STAT_REDIR;
+	ic.arg = chan; 
+	(ulong)(ic.parm.num[0]) = result;
+	cs->iif.statcallb(&ic);
+} /* stat_redir_result */
+
 static void
 dchan_l3l4(struct PStack *st, int pr, void *arg)
 {
 	struct l3_process *pc = arg;
-	struct IsdnCardState *cs = st->l1.hardware;
+        struct IsdnCardState *cs = st->l1.hardware;
 	struct Channel *chanp;
-	int event;
 
-	switch (pr) {
-		case (DL_ESTABLISH | INDICATION):
-			event = EV_DLEST;
-			break;
-		case (DL_RELEASE | INDICATION):
-			event = EV_DLRL;
-			break;
-		default:
-			event = -1;
-			break;
-	}
-	if (event >= 0) {
-		int i;
-
-		chanp = st->lli.userdata;
-		if (test_bit(FLG_TWO_DCHAN, &cs->HW_Flags))
-			i = 1;
-		else
-			i = 0;
-		while (i < 2) {
-			FsmEvent(&chanp->fi, event, NULL);
-			chanp++;
-			i++;
-		}
-		return;
-	} else if (pr == (CC_SETUP | INDICATION)) {
-		if (!(chanp = selectfreechannel(pc->st))) {
-			pc->st->lli.l4l3(pc->st, CC_DLRL | REQUEST, pc);
-		} else {
-			chanp->proc = pc;
-			pc->chan = chanp;
+        if(!pc)
+                return;
+ 
+        if (pr == (CC_SETUP | INDICATION)) {
+                if (!(chanp = selectfreechannel(pc->st, pc->para.bchannel))) {
+                        pc->para.cause = 0x11;          /* User busy */
+                        pc->st->lli.l4l3(pc->st, CC_REJECT | REQUEST, pc);
+                } else {
+                        chanp->proc = pc;
+                        pc->chan = chanp;
 			FsmEvent(&chanp->fi, EV_SETUP_IND, NULL);
 		}
 		return;
@@ -1299,19 +1054,19 @@
 			FsmEvent(&chanp->fi, EV_DISCONNECT_IND, NULL);
 			break;
 		case (CC_RELEASE | CONFIRM):
-			FsmEvent(&chanp->fi, EV_RELEASE_CNF, NULL);
+			FsmEvent(&chanp->fi, EV_RELEASE, NULL);
 			break;
 		case (CC_SUSPEND | CONFIRM):
-			FsmEvent(&chanp->fi, EV_RELEASE_CNF, NULL);
+			FsmEvent(&chanp->fi, EV_RELEASE, NULL);
 			break;
 		case (CC_RESUME | CONFIRM):
 			FsmEvent(&chanp->fi, EV_SETUP_CNF, NULL);
 			break;
 		case (CC_RESUME_ERR):
-			FsmEvent(&chanp->fi, EV_RELEASE_CNF, NULL);
+			FsmEvent(&chanp->fi, EV_RELEASE, NULL);
 			break;
 		case (CC_RELEASE | INDICATION):
-			FsmEvent(&chanp->fi, EV_RELEASE_IND, NULL);
+			FsmEvent(&chanp->fi, EV_RELEASE, NULL);
 			break;
 		case (CC_SETUP_COMPL | INDICATION):
 			FsmEvent(&chanp->fi, EV_SETUP_CMPL_IND, NULL);
@@ -1332,15 +1087,21 @@
 			FsmEvent(&chanp->fi, EV_CONNECT_ERR, NULL);
 			break;
 		case (CC_RELEASE_ERR):
-			FsmEvent(&chanp->fi, EV_RELEASE_ERR, NULL);
+			FsmEvent(&chanp->fi, EV_RELEASE, NULL);
 			break;
+		case (CC_PROCEED_SEND | INDICATION):
 		case (CC_PROCEEDING | INDICATION):
 		case (CC_ALERTING | INDICATION):
+		case (CC_PROGRESS | INDICATION):
+		case (CC_NOTIFY | INDICATION):
 			break;
+		case (CC_REDIR | INDICATION):
+			stat_redir_result(cs, chanp->chan, pc->redir_result); 
+			break;                         
 		default:
 			if (chanp->debug & 0x800) {
 				HiSax_putstatus(chanp->cs, "Ch",
-					"%d L3->L4 unknown primitiv %x",
+					"%d L3->L4 unknown primitiv %#x",
 					chanp->chan, pr);
 			}
 	}
@@ -1406,6 +1167,7 @@
 	(*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;
@@ -1446,14 +1208,19 @@
 
 int
 CallcNewChan(struct IsdnCardState *csta)
-{
+{       int i;
+
 	chancount += 2;
 	init_chan(0, csta);
 	init_chan(1, csta);
 	printk(KERN_INFO "HiSax: 2 channels added\n");
+
+	for (i = 0; i < MAX_WAITING_CALLS; i++) 
+		init_chan(i+2,csta);
+	printk(KERN_INFO "HiSax: MAX_WAITING_CALLS added\n");        
+
 	if (test_bit(FLG_PTP, &csta->channel->d_st->l2.flag)) {
 		printk(KERN_INFO "LAYER2 WATCHING ESTABLISH\n");
-		test_and_set_bit(FLG_START_D, &csta->channel->Flags);
 		csta->channel->d_st->lli.l4l3(csta->channel->d_st,
 			DL_ESTABLISH | REQUEST, NULL);
 	}
@@ -1482,14 +1249,13 @@
 	for (i = 0; i < 2; i++) {
 		FsmDelTimer(&csta->channel[i].drel_timer, 74);
 		FsmDelTimer(&csta->channel[i].dial_timer, 75);
-		if (i || test_bit(FLG_TWO_DCHAN, &csta->HW_Flags))
-			release_d_st(csta->channel + i);
-		if (csta->channel[i].b_st) {
-			if (test_and_clear_bit(FLG_START_B, &csta->channel[i].Flags))
-				release_b_st(csta->channel + i);
-			kfree(csta->channel[i].b_st);
-			csta->channel[i].b_st = NULL;
-		} else
+                if (i || test_bit(FLG_TWO_DCHAN, &csta->HW_Flags))
+                        release_d_st(csta->channel + i);
+                if (csta->channel[i].b_st) {
+                        release_b_st(csta->channel + i);
+                        kfree(csta->channel[i].b_st);
+                        csta->channel[i].b_st = NULL;
+                } else
 			printk(KERN_WARNING "CallcFreeChan b_st ch%d allready freed\n", i);
 		if (i || test_bit(FLG_TWO_DCHAN, &csta->HW_Flags)) {
 			release_d_st(csta->channel + i);
@@ -1509,7 +1275,7 @@
 			if (chanp->data_open)
 				chanp->cs->iif.rcvcallb_skb(chanp->cs->myid, chanp->chan, skb);
 			else {
-				dev_kfree_skb(skb);
+				idev_kfree_skb(skb, FREE_READ);
 			}
 			break;
 		case (DL_ESTABLISH | INDICATION):
@@ -1521,7 +1287,7 @@
 			FsmEvent(&chanp->fi, EV_BC_REL, NULL);
 			break;
 		default:
-			printk(KERN_WARNING "lldata_handler unknown primitive %x\n",
+			printk(KERN_WARNING "lldata_handler unknown primitive %#x\n",
 			       pr);
 			break;
 	}
@@ -1539,7 +1305,7 @@
 				chanp->cs->iif.rcvcallb_skb(chanp->cs->myid, chanp->chan, skb);
 			else {
 				link_debug(chanp, 0, "channel not open");
-				dev_kfree_skb(skb);
+				idev_kfree_skb(skb, FREE_READ);
 			}
 			break;
 		case (PH_ACTIVATE | INDICATION):
@@ -1551,7 +1317,7 @@
 			FsmEvent(&chanp->fi, EV_BC_REL, NULL);
 			break;
 		default:
-			printk(KERN_WARNING "lltrans_handler unknown primitive %x\n",
+			printk(KERN_WARNING "lltrans_handler unknown primitive %#x\n",
 			       pr);
 			break;
 	}
@@ -1566,7 +1332,7 @@
 	ic.driver = chanp->cs->myid;
 	ic.command = ISDN_STAT_BSENT;
 	ic.arg = chanp->chan;
-//	ic.parm.length = len;
+	ic.parm.length = len;
 	chanp->cs->iif.statcallb(&ic);
 }
 
@@ -1590,12 +1356,11 @@
 		case (ISDN_PROTO_L2_TRANS):
 			st->l1.mode = L1_MODE_TRANS;
 			break;
-#if 0
 		case (ISDN_PROTO_L2_MODEM):
-			st->l1.mode = L1_MODE_MODEM;
+			st->l1.mode = L1_MODE_V32;
 			break;
-#endif
 	}
+	chanp->bcs->conmsg = NULL;
 	if (chanp->bcs->BC_SetStack(st, chanp->bcs))
 		return (-1);
 	st->l2.flag = 0;
@@ -1622,7 +1387,7 @@
 			break;
 		case (ISDN_PROTO_L2_HDLC):
 		case (ISDN_PROTO_L2_TRANS):
-//		case (ISDN_PROTO_L2_MODEM):
+		case (ISDN_PROTO_L2_MODEM):
 			st->l1.l1l2 = lltrans_handler;
 			st->lli.userdata = chanp;
 			st->lli.l1writewakeup = ll_writewakeup;
@@ -1630,6 +1395,8 @@
 			setstack_l3bc(st, chanp);
 			break;
 	}
+        test_and_set_bit(FLG_START_B, &chanp->Flags);
+ 
 	return (0);
 }
 
@@ -1642,7 +1409,7 @@
 	switch (pr) {
 		case (DL_DATA | REQUEST):
 			link_debug(chanp, 0, "leased line d-channel DATA");
-			dev_kfree_skb(skb);
+			idev_kfree_skb(skb, FREE_READ);
 			break;
 		case (DL_ESTABLISH | REQUEST):
 			st->l2.l2l1(st, PH_ACTIVATE | REQUEST, NULL);
@@ -1650,7 +1417,7 @@
 		case (DL_RELEASE | REQUEST):
 			break;
 		default:
-			printk(KERN_WARNING "transd_l4l3 unknown primitive %x\n",
+			printk(KERN_WARNING "transd_l4l3 unknown primitive %#x\n",
 			       pr);
 			break;
 	}
@@ -1661,16 +1428,16 @@
 {
 	struct Channel *chanp = (struct Channel *) st->lli.userdata;
 	struct sk_buff *skb = arg;
-	int i,event = EV_DLRL;
+	int i,event = EV_LEASED_REL;
 
 	switch (pr) {
 		case (PH_DATA | INDICATION):
 			link_debug(chanp, 0, "leased line d-channel DATA");
-			dev_kfree_skb(skb);
+			idev_kfree_skb(skb, FREE_READ);
 			break;
 		case (PH_ACTIVATE | INDICATION):
 		case (PH_ACTIVATE | CONFIRM):
-			event = EV_DLEST;
+			event = EV_LEASED;
 		case (PH_DEACTIVATE | INDICATION):
 		case (PH_DEACTIVATE | CONFIRM):
 			if (test_bit(FLG_TWO_DCHAN, &chanp->cs->HW_Flags))
@@ -1685,7 +1452,7 @@
 			break;
 		default:
 			printk(KERN_WARNING
-				"transd_l1l2 unknown primitive %x\n", pr);
+				"transd_l1l2 unknown primitive %#x\n", pr);
 			break;
 	}
 }
@@ -1701,7 +1468,7 @@
 	int i;
 	struct Channel *chanp = csta->channel;
 
-	for (i = 0; i < 2; i++) {
+	for (i = 0; i < (2 + MAX_WAITING_CALLS) ; i++) {
 		chanp[i].debug = debugflags;
 		chanp[i].fi.debug = debugflags & 2;
 		chanp[i].d_st->l2.l2m.debug = debugflags & 8;
@@ -1774,10 +1541,40 @@
 	}
 }
 
+
+/***************************************************************/
+/* Limit the available number of channels for the current card */
+/***************************************************************/
+static int 
+set_channel_limit(struct IsdnCardState *cs, int chanmax)
+{ isdn_ctrl ic;
+  int i, ii;
+  
+  if ((chanmax < 0) || (chanmax > 2))
+    return(-EINVAL);
+  cs->chanlimit = 0;
+  for (ii = 0; ii < 2; ii++) {
+    ic.driver = cs->myid;
+    ic.command = ISDN_STAT_DISCH;
+    ic.arg = ii;
+    if (ii >= chanmax)
+      ic.parm.num[0] = 0; /* disabled */
+    else
+      ic.parm.num[0] = 1; /* enabled */
+    i = cs->iif.statcallb(&ic); 
+    if (i) return(-EINVAL);
+    if (ii < chanmax) 
+      cs->chanlimit++;
+  }
+  return(0);
+} /* set_channel_limit */
+
+
 int
 HiSax_command(isdn_ctrl * ic)
 {
 	struct IsdnCardState *csta = hisax_findcard(ic->driver);
+	struct PStack *st;
 	struct Channel *chanp;
 	int i;
 	u_int num;
@@ -1868,7 +1665,7 @@
 			HiSax_mod_inc_use_count();
 #ifdef MODULE
 			if (csta->channel[0].debug & 0x400)
-				HiSax_putstatus(csta, "   LOCK ", "modcnt %x",
+				HiSax_putstatus(csta, "   LOCK ", "modcnt %lx",
 					MOD_USE_COUNT);
 #endif				/* MODULE */
 			break;
@@ -1876,7 +1673,7 @@
 			HiSax_mod_dec_use_count();
 #ifdef MODULE
 			if (csta->channel[0].debug & 0x400)
-				HiSax_putstatus(csta, " UNLOCK ", "modcnt %x",
+				HiSax_putstatus(csta, " UNLOCK ", "modcnt %lx",
 					MOD_USE_COUNT);
 #endif				/* MODULE */
 			break;
@@ -1949,8 +1746,6 @@
 						HiSax_putstatus(csta, "set card ", "in PTP mode");
 						printk(KERN_DEBUG "HiSax: set card in PTP mode\n");
 						printk(KERN_INFO "LAYER2 WATCHING ESTABLISH\n");
-						test_and_set_bit(FLG_START_D, &csta->channel[0].Flags);
-						test_and_set_bit(FLG_START_D, &csta->channel[1].Flags);
 						csta->channel[0].d_st->lli.l4l3(csta->channel[0].d_st,
 							DL_ESTABLISH | REQUEST, NULL);
 					} else {
@@ -1969,6 +1764,8 @@
 					HiSax_putstatus(csta, "set card ", "in FIXED TEI (%d) mode", num);
 					printk(KERN_DEBUG "HiSax: set card in FIXED TEI (%d) mode\n",
 						num);
+					chanp->d_st->lli.l4l3(chanp->d_st,
+						DL_ESTABLISH | REQUEST, NULL);
 					break;
 				case (9): /* load firmware */
 					memcpy(&adr, ic->parm.num, sizeof(ulong));
@@ -1977,8 +1774,7 @@
 					break;
 #ifdef MODULE
 				case (55):
-					while ( MOD_USE_COUNT > 0)
-						MOD_DEC_USE_COUNT;
+					MOD_USE_COUNT = 0;
 					HiSax_mod_inc_use_count();
 					break;
 #endif				/* MODULE */
@@ -2001,12 +1797,58 @@
 					printk(KERN_DEBUG "HiSax: l3 debugging flags card %d set to %x\n",
 						csta->cardnr + 1, *(unsigned int *) ic->parm.num);
 					break;
+			        case  (10):
+				        i = *(unsigned int *) ic->parm.num;
+					if ((i < 0) || (i > 2))
+					  return(-EINVAL); /* invalid number */
+					return(set_channel_limit(csta, i));
+				        break;
+			        case  (12):
+				        i = *(unsigned int *) ic->parm.num;
+#ifdef CONFIG_HISAX_HFC_PCI
+					if (csta->typ != ISDN_CTYPE_HFC_PCI)
+					  return(-EINVAL);
+					return(hfcpci_set_echo(csta,i));    
+#else
+					return(-EINVAL);    
+#endif
+				        break;
 				default:
 					printk(KERN_DEBUG "HiSax: invalid ioclt %d\n",
 					       (int) ic->arg);
 					return (-EINVAL);
 			}
 			break;
+		
+		case (ISDN_CMD_PROCEED):
+			chanp = csta->channel + ic->arg;
+			if (chanp->debug & 1)
+				link_debug(chanp, 1, "PROCEED");
+			FsmEvent(&chanp->fi, EV_PROCEED, NULL);
+			break;
+
+		case (ISDN_CMD_ALERT):
+			chanp = csta->channel + ic->arg;
+			if (chanp->debug & 1)
+				link_debug(chanp, 1, "ALERT");
+			FsmEvent(&chanp->fi, EV_ALERT, NULL);
+			break;
+
+		case (ISDN_CMD_REDIR):
+			chanp = csta->channel + ic->arg;
+			if (chanp->debug & 1)
+				link_debug(chanp, 1, "REDIR");
+			chanp->setup = ic->parm.setup;
+			FsmEvent(&chanp->fi, EV_REDIR, NULL);
+			break;
+
+		/* protocol specific io commands */
+	        case (ISDN_CMD_PROT_IO):
+			for (st = csta->stlist; st; st = st->next)
+				if (st->protocol == (ic->arg & 0xFF))
+					return(st->lli.l4l3_proto(st, ic));
+			return(-EINVAL);                     
+			break;
 		default:
 			break;
 	}
@@ -2049,7 +1891,8 @@
 			if (chanp->debug & 0x800)
 				link_debug(chanp, 1, "writebuf: no buffers for %d bytes", len);
 			return 0;
-		}
+		} else if (chanp->debug & 0x800)
+			link_debug(chanp, 1, "writebuf %d/%d/%d", len, chanp->bcs->tx_cnt,MAX_DATA_MEM);
 		save_flags(flags);
 		cli();
 		nskb = skb_clone(skb, GFP_ATOMIC);
@@ -2062,7 +1905,7 @@
 				chanp->bcs->tx_cnt += len;
 				st->l2.l2l1(st, PH_DATA | REQUEST, nskb);
 			}
-			dev_kfree_skb(skb);
+			idev_kfree_skb(skb, FREE_WRITE);
 		} else
 			len = 0;
 		restore_flags(flags);
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/cert.c linux/drivers/isdn/hisax/cert.c
--- v2.3.13/linux/drivers/isdn/hisax/cert.c	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/hisax/cert.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: cert.c,v 2.1 1998/11/15 23:51:15 keil Exp $
+/* $Id: cert.c,v 2.2 1999/08/07 17:35:05 keil Exp $
 
  * Author       Karsten Keil (keil@isdn4linux.de)
  *
@@ -7,6 +7,9 @@
  *		../../../Documentation/isdn/HiSax.cert
  *
  * $Log: cert.c,v $
+ * Revision 2.2  1999/08/07 17:35:05  keil
+ * approval for Eicon Technology Diva 2.01 PCI
+ *
  * Revision 2.1  1998/11/15 23:51:15  keil
  * certification stuff
  *
@@ -29,6 +32,7 @@
 		printk(KERN_INFO "HiSax: Approval registration numbers:\n");
 		printk(KERN_INFO "HiSax: German D133361J CETECOM ICT Services GmbH\n");
 		printk(KERN_INFO "HiSax: EU (D133362J) CETECOM ICT Services GmbH\n");
+		printk(KERN_INFO "HiSax: Approved with Eicon Technology Diva 2.01 PCI cards\n");
 	}
 	return(0);
 #endif
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/config.c linux/drivers/isdn/hisax/config.c
--- v2.3.13/linux/drivers/isdn/hisax/config.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/isdn/hisax/config.c	Thu Aug 12 09:42:33 1999
@@ -1,10 +1,33 @@
-/* $Id: config.c,v 2.23 1999/02/17 10:53:02 cpetig Exp $
+/* $Id: config.c,v 2.30 1999/08/05 20:43:14 keil Exp $
 
  * Author       Karsten Keil (keil@isdn4linux.de)
  *              based on the teles driver from Jan den Ouden
  *
  *
  * $Log: config.c,v $
+ * Revision 2.30  1999/08/05 20:43:14  keil
+ * ISAR analog modem support
+ *
+ * Revision 2.29  1999/07/21 14:46:00  keil
+ * changes from EICON certification
+ *
+ * Revision 2.28  1999/07/14 12:38:36  werner
+ * Added changes for echo channel handling
+ *
+ * Revision 2.27  1999/07/12 21:05:00  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 2.26  1999/07/08 21:27:17  keil
+ * version 3.2
+ *
+ * Revision 2.25  1999/07/05 23:51:44  werner
+ * Allow limiting of available HiSax B-chans per card. Controlled by hisaxctrl
+ * hisaxctrl id 10 <nr. of chans 0-2>
+ *
+ * Revision 2.24  1999/07/01 08:11:26  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 2.23  1999/02/17 10:53:02  cpetig
  * Added Hisax_closecard to exported symbols.
  * As indicated by Oliver Schoett <os@sdm.de>.
@@ -139,7 +162,13 @@
  *   26 AVM A1 PCMCIA (Fritz)   p0=irq p1=iobase
  *   27 AVM PnP/PCI 		p0=irq p1=iobase (PCI no parameter)
  *   28 Sedlbauer Speed Fax+ 	p0=irq p1=iobase (from isapnp setup)
- *
+ *   29 Siemens I-Surf          p0=irq p1=iobase p2=memory (from isapnp setup)   
+ *   30 ACER P10                p0=irq p1=iobase (from isapnp setup)   
+ *   31 HST Saphir              p0=irq  p1=iobase
+ *   32 Telekom A4T             none
+ *   33 Scitel Quadro		p0=subcontroller (4*S0, subctrl 1...4)
+ *   34	Gazel ISDN cards
+ *   35 HFC 2BDS0 PCI           none
  * protocol can be either ISDN_PTYPE_EURO or ISDN_PTYPE_1TR6 or ISDN_PTYPE_NI1
  *
  *
@@ -152,15 +181,27 @@
  "Sedlbauer Speed Card", "USR Sportster", "ith mic Linux", "Elsa PCI",
  "Compaq ISA", "NETjet", "Teles PCI", "Sedlbauer Speed Star (PCMCIA)",
  "AMD 7930", "NICCY", "S0Box", "AVM A1 (PCMCIA)", "AVM Fritz PnP/PCI",
- "Sedlbauer Speed Fax +"
+ "Sedlbauer Speed Fax +", "Siemens I-Surf", "Acer P10", "HST Saphir",
+ "Telekom A4T", "Scitel Quadro", "Gazel", "HFC 2BDS0 PCI",
 };
 
+void HiSax_closecard(int cardnr);
+
 #ifdef CONFIG_HISAX_ELSA
 #define DEFAULT_CARD ISDN_CTYPE_ELSA
 #define DEFAULT_CFG {0,0,0,0}
 int elsa_init_pcmcia(void*, int, int*, int);
+#ifdef COMPAT_HAS_NEW_SYMTAB
 EXPORT_SYMBOL(elsa_init_pcmcia);
-#endif
+#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
 #undef DEFAULT_CARD
 #undef DEFAULT_CFG
@@ -174,8 +215,17 @@
 #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);
-#endif
+#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
 #undef DEFAULT_CARD
@@ -190,12 +240,14 @@
 #define DEFAULT_CARD ISDN_CTYPE_16_3
 #define DEFAULT_CFG {15,0x180,0,0}
 #endif
+
 #ifdef CONFIG_HISAX_S0BOX
 #undef DEFAULT_CARD
 #undef DEFAULT_CFG
 #define DEFAULT_CARD ISDN_CTYPE_S0BOX
 #define DEFAULT_CFG {7,0x378,0,0}
 #endif
+
 #ifdef CONFIG_HISAX_16_0
 #undef DEFAULT_CARD
 #undef DEFAULT_CFG
@@ -244,8 +296,16 @@
 #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);
-#endif
+#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
 #undef DEFAULT_CARD
@@ -268,13 +328,21 @@
 #define DEFAULT_CFG {0,0,0,0}
 #endif
 
-#ifdef CONFIG_HISAX_TELES3C
+#ifdef CONFIG_HISAX_HFCS
 #undef DEFAULT_CARD
 #undef DEFAULT_CFG
 #define DEFAULT_CARD ISDN_CTYPE_TELES3C
 #define DEFAULT_CFG {5,0x500,0,0}
 #endif
 
+#ifdef CONFIG_HISAX_HFC_PCI
+#undef DEFAULT_CARD
+#undef DEFAULT_CFG
+#define DEFAULT_CARD ISDN_CTYPE_HFC_PCI
+#define DEFAULT_CFG {0,0,0,0}
+#endif
+
+
 #ifdef CONFIG_HISAX_AMD7930
 #undef DEFAULT_CARD
 #undef DEFAULT_CFG
@@ -289,6 +357,41 @@
 #define DEFAULT_CFG {0,0x0,0,0}
 #endif
 
+#ifdef CONFIG_HISAX_ISURF
+#undef DEFAULT_CARD
+#undef DEFAULT_CFG
+#define DEFAULT_CARD ISDN_CTYPE_ISURF
+#define DEFAULT_CFG {5,0x100,0xc8000,0}
+#endif
+
+#ifdef CONFIG_HISAX_HSTSAPHIR
+#undef DEFAULT_CARD
+#undef DEFAULT_CFG
+#define DEFAULT_CARD ISDN_CTYPE_HSTSAPHIR
+#define DEFAULT_CFG {5,0x250,0,0}
+#endif
+
+#ifdef CONFIG_HISAX_BKM_A4T            
+#undef DEFAULT_CARD
+#undef DEFAULT_CFG
+#define DEFAULT_CARD ISDN_CTYPE_BKM_A4T
+#define DEFAULT_CFG {0,0x0,0,0}
+#endif
+
+#ifdef CONFIG_HISAX_SCT_QUADRO
+#undef DEFAULT_CARD
+#undef DEFAULT_CFG
+#define DEFAULT_CARD ISDN_CTYPE_SCT_QUADRO
+#define DEFAULT_CFG {1,0x0,0,0}
+#endif
+
+#ifdef CONFIG_HISAX_GAZEL
+#undef DEFAULT_CARD
+#undef DEFAULT_CFG
+#define DEFAULT_CARD ISDN_CTYPE_GAZEL
+#define DEFAULT_CFG {15,0x180,0,0}
+#endif
+
 #ifdef CONFIG_HISAX_1TR6
 #define DEFAULT_PROTO ISDN_PTYPE_1TR6
 #define DEFAULT_PROTO_NAME "1TR6"
@@ -366,6 +469,7 @@
 {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");
@@ -377,7 +481,7 @@
 MODULE_PARM(io0, "1-8i");
 MODULE_PARM(io1, "1-8i");
 #endif /* CONFIG_HISAX_16_3 */
-
+#endif /* COMPAT_HAS_NEW_SYMTAB */
 #endif /* MODULE */
 
 int nrcards;
@@ -410,9 +514,9 @@
 
 	printk(KERN_INFO "HiSax: Linux Driver for passive ISDN cards\n");
 #ifdef MODULE
-	printk(KERN_INFO "HiSax: Version 3.1a (module)\n");
+	printk(KERN_INFO "HiSax: Version 3.3 (module)\n");
 #else
-	printk(KERN_INFO "HiSax: Version 3.1a (kernel)\n");
+	printk(KERN_INFO "HiSax: Version 3.3 (kernel)\n");
 #endif
 	strcpy(tmp, l1_revision);
 	printk(KERN_INFO "HiSax: Layer1 Revision %s\n", HiSax_getrev(tmp));
@@ -442,8 +546,8 @@
 #ifdef MODULE
 #define HiSax_init init_module
 #else
-void __init 
-HiSax_setup(char *str, int *ints)
+__initfunc(void
+HiSax_setup(char *str, int *ints))
 {
 	int i, j, argc;
 
@@ -552,8 +656,12 @@
 extern int setup_netjet(struct IsdnCard *card);
 #endif
 
-#if CARD_TELES3C
-extern int setup_t163c(struct IsdnCard *card);
+#if CARD_HFCS
+extern int setup_hfcs(struct IsdnCard *card);
+#endif
+
+#if CARD_HFC_PCI
+extern int setup_hfcpci(struct IsdnCard *card);
 #endif
 
 #if CARD_AMD7930
@@ -564,6 +672,30 @@
 extern int setup_niccy(struct IsdnCard *card);
 #endif
 
+#if CARD_ISURF
+extern int setup_isurf(struct IsdnCard *card);
+#endif
+
+#if CARD_HSTSAPHIR
+extern int setup_saphir(struct IsdnCard *card);
+#endif
+
+#if CARD_TESTEMU
+extern int setup_testemu(struct IsdnCard *card);
+#endif
+
+#if	CARD_BKM_A4T
+extern int setup_bkm_a4t(struct IsdnCard *card);
+#endif
+
+#if	CARD_SCT_QUADRO
+extern int setup_sct_quadro(struct IsdnCard *card);
+#endif
+
+#if CARD_GAZEL
+extern int setup_gazel(struct IsdnCard *card);
+#endif
+
 /*
  * Find card with given driverId
  */
@@ -579,6 +711,18 @@
 	return (NULL);
 }
 
+/*
+ * Find card with given card number
+ */
+struct IsdnCardState
+*hisax_get_card(int cardnr)
+{
+	if ((cardnr <= nrcards) && (cardnr>0))
+		if (cards[cardnr-1].cs)
+			return (cards[cardnr-1].cs);
+	return (NULL);
+}
+
 int
 HiSax_readstatus(u_char * buf, int len, int user, int id, int channel)
 {
@@ -782,23 +926,18 @@
 		csta->bcs->BC_Close(csta->bcs);
 	}
 
+	discard_queue(&csta->rq);
+	discard_queue(&csta->sq);
 	if (csta->rcvbuf) {
 		kfree(csta->rcvbuf);
 		csta->rcvbuf = NULL;
 	}
-	discard_queue(&csta->rq);
-	discard_queue(&csta->sq);
 	if (csta->tx_skb) {
-		dev_kfree_skb(csta->tx_skb);
+		idev_kfree_skb(csta->tx_skb, FREE_WRITE);
 		csta->tx_skb = NULL;
 	}
-	if (csta->mon_rx) {
-		kfree(csta->mon_rx);
-		csta->mon_rx = NULL;
-	}
-	if (csta->mon_tx) {
-		kfree(csta->mon_tx);
-		csta->mon_tx = NULL;
+	if (csta->DC_Close != NULL) {
+		csta->DC_Close(csta);
 	}
 	csta->cardmsg(csta, CARD_RELEASE, NULL);
 	if (csta->dbusytimer.function != NULL)
@@ -811,12 +950,14 @@
 	int irq_cnt, cnt = 3;
 	long flags;
 
+	if (!cs->irq)
+		return(cs->cardmsg(cs, CARD_INIT, NULL));
 	save_flags(flags);
 	cli();
 	irq_cnt = kstat_irqs(cs->irq);
 	printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ], cs->irq,
 		irq_cnt);
-	if (cs->cardmsg(cs, CARD_SETIRQ, NULL)) {
+	if (request_irq(cs->irq, cs->irq_func, cs->irq_flags, "HiSax", cs)) {
 		printk(KERN_WARNING "HiSax: couldn't get interrupt %d\n",
 			cs->irq);
 		restore_flags(flags);
@@ -827,7 +968,7 @@
 		sti();
 		current->state = TASK_INTERRUPTIBLE;
 		/* Timeout 10ms */
-		schedule_timeout((10 * HZ) / 1000);
+		schedule_timeout((10*HZ)/1000);
 		restore_flags(flags);
 		printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ],
 			cs->irq, kstat_irqs(cs->irq));
@@ -871,198 +1012,229 @@
 	}
 	memset(cs, 0, sizeof(struct IsdnCardState));
 	card->cs = cs;
+	cs->chanlimit = 2; /* maximum B-channel number */
+	cs->logecho = 0; /* No echo logging */
 	cs->cardnr = cardnr;
 	cs->debug = L1_DEB_WARN;
 	cs->HW_Flags = 0;
 	cs->busy_flag = busy_flag;
+	cs->irq_flags = I4L_IRQ_FLAG;
 #if TEI_PER_CARD
 #else
 	test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
 #endif
 	cs->protocol = card->protocol;
 
-	if ((card->typ > 0) && (card->typ < 31)) {
-		if (!((1 << card->typ) & SUPORTED_CARDS)) {
+	if ((card->typ > 0) && (card->typ <= ISDN_CTYPE_COUNT)) {
+		if (!(cs->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC))) {
 			printk(KERN_WARNING
-			     "HiSax: Support for %s Card not selected\n",
-			       CardType[card->typ]);
+				"HiSax: No memory for dlog(card %d)\n",
+				cardnr + 1);
 			restore_flags(flags);
 			return (0);
 		}
-	} else {
-		printk(KERN_WARNING
-		       "HiSax: Card Type %d out of range\n",
-		       card->typ);
-		restore_flags(flags);
-		return (0);
-	}
-	if (!(cs->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC))) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for dlog(card %d)\n",
-		       cardnr + 1);
-		restore_flags(flags);
-		return (0);
-	}
-	if (!(cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC))) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for status_buf(card %d)\n",
-		       cardnr + 1);
-		kfree(cs->dlog);
-		restore_flags(flags);
-		return (0);
-	}
-	cs->stlist = NULL;
-	cs->mon_tx = NULL;
-	cs->mon_rx = NULL;
-	cs->status_read = cs->status_buf;
-	cs->status_write = cs->status_buf;
-	cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1;
-	cs->typ = card->typ;
-	strcpy(cs->iif.id, id);
-	cs->iif.channels = 2;
-	cs->iif.maxbufsize = MAX_DATA_SIZE;
-	cs->iif.hl_hdrlen = MAX_HEADER_LEN;
-	cs->iif.features =
-	    ISDN_FEATURE_L2_X75I |
-	    ISDN_FEATURE_L2_HDLC |
-	    ISDN_FEATURE_L2_MODEM |
-	    ISDN_FEATURE_L2_TRANS |
-	    ISDN_FEATURE_L3_TRANS |
+		if (!(cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC))) {
+			printk(KERN_WARNING
+				"HiSax: No memory for status_buf(card %d)\n",
+				cardnr + 1);
+			kfree(cs->dlog);
+			restore_flags(flags);
+			return (0);
+		}
+		cs->stlist = NULL;
+		cs->status_read = cs->status_buf;
+		cs->status_write = cs->status_buf;
+		cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1;
+		cs->typ = card->typ;
+		strcpy(cs->iif.id, id);
+		cs->iif.channels = 2;
+		cs->iif.maxbufsize = MAX_DATA_SIZE;
+		cs->iif.hl_hdrlen = MAX_HEADER_LEN;
+		cs->iif.features =
+			ISDN_FEATURE_L2_X75I |
+			ISDN_FEATURE_L2_HDLC |
+			ISDN_FEATURE_L2_MODEM |
+			ISDN_FEATURE_L2_TRANS |
+			ISDN_FEATURE_L3_TRANS |
 #ifdef	CONFIG_HISAX_1TR6
-	    ISDN_FEATURE_P_1TR6 |
+			ISDN_FEATURE_P_1TR6 |
 #endif
 #ifdef	CONFIG_HISAX_EURO
-	    ISDN_FEATURE_P_EURO |
+			ISDN_FEATURE_P_EURO |
 #endif
-#ifdef        CONFIG_HISAX_NI1
-	    ISDN_FEATURE_P_NI1 |
+#ifdef	CONFIG_HISAX_NI1
+			ISDN_FEATURE_P_NI1 |
 #endif
-	    0;
+			0;
 
-	cs->iif.command = HiSax_command;
-	cs->iif.writecmd = NULL;
-	cs->iif.writebuf_skb = HiSax_writebuf_skb;
-	cs->iif.readstat = HiSax_readstatus;
-	register_isdn(&cs->iif);
-	cs->myid = cs->iif.channels;
-	printk(KERN_INFO
-	       "HiSax: Card %d Protocol %s Id=%s (%d)\n", cardnr + 1,
-	       (card->protocol == ISDN_PTYPE_1TR6) ? "1TR6" :
-	       (card->protocol == ISDN_PTYPE_EURO) ? "EDSS1" :
-	       (card->protocol == ISDN_PTYPE_LEASED) ? "LEASED" :
-	       (card->protocol == ISDN_PTYPE_NI1) ? "NI1" :
-	       "NONE", cs->iif.id, cs->myid);
-	switch (card->typ) {
+		cs->iif.command = HiSax_command;
+		cs->iif.writecmd = NULL;
+		cs->iif.writebuf_skb = HiSax_writebuf_skb;
+		cs->iif.readstat = HiSax_readstatus;
+		register_isdn(&cs->iif);
+		cs->myid = cs->iif.channels;
+		printk(KERN_INFO
+			"HiSax: Card %d Protocol %s Id=%s (%d)\n", cardnr + 1,
+			(card->protocol == ISDN_PTYPE_1TR6) ? "1TR6" :
+			(card->protocol == ISDN_PTYPE_EURO) ? "EDSS1" :
+			(card->protocol == ISDN_PTYPE_LEASED) ? "LEASED" :
+			(card->protocol == ISDN_PTYPE_NI1) ? "NI1" :
+			"NONE", cs->iif.id, cs->myid);
+		switch (card->typ) {
 #if CARD_TELES0
-		case ISDN_CTYPE_16_0:
-		case ISDN_CTYPE_8_0:
-			ret = setup_teles0(card);
-			break;
+			case ISDN_CTYPE_16_0:
+			case ISDN_CTYPE_8_0:
+				ret = setup_teles0(card);
+				break;
 #endif
 #if CARD_TELES3
-		case ISDN_CTYPE_16_3:
-		case ISDN_CTYPE_PNP:
-		case ISDN_CTYPE_TELESPCMCIA:
-		case ISDN_CTYPE_COMPAQ_ISA:
-			ret = setup_teles3(card);
-			break;
+			case ISDN_CTYPE_16_3:
+			case ISDN_CTYPE_PNP:
+			case ISDN_CTYPE_TELESPCMCIA:
+			case ISDN_CTYPE_COMPAQ_ISA:
+				ret = setup_teles3(card);
+				break;
 #endif
 #if CARD_S0BOX
-		case ISDN_CTYPE_S0BOX:
-			ret = setup_s0box(card);
-			break;
+			case ISDN_CTYPE_S0BOX:
+				ret = setup_s0box(card);
+				break;
 #endif
 #if CARD_TELESPCI
-		case ISDN_CTYPE_TELESPCI:
-			ret = setup_telespci(card);
-			break;
+			case ISDN_CTYPE_TELESPCI:
+				ret = setup_telespci(card);
+				break;
 #endif
 #if CARD_AVM_A1
-		case ISDN_CTYPE_A1:
-			ret = setup_avm_a1(card);
-			break;
+			case ISDN_CTYPE_A1:
+				ret = setup_avm_a1(card);
+				break;
 #endif
 #if CARD_AVM_A1_PCMCIA
-		case ISDN_CTYPE_A1_PCMCIA:
-			ret = setup_avm_a1_pcmcia(card);
-			break;
+			case ISDN_CTYPE_A1_PCMCIA:
+				ret = setup_avm_a1_pcmcia(card);
+				break;
 #endif
 #if CARD_FRITZPCI
-		case ISDN_CTYPE_FRITZPCI:
-			ret = setup_avm_pcipnp(card);
-			break;
+			case ISDN_CTYPE_FRITZPCI:
+				ret = setup_avm_pcipnp(card);
+				break;
 #endif
 #if CARD_ELSA
-		case ISDN_CTYPE_ELSA:
-		case ISDN_CTYPE_ELSA_PNP:
-		case ISDN_CTYPE_ELSA_PCMCIA:
-		case ISDN_CTYPE_ELSA_PCI:
-			ret = setup_elsa(card);
-			break;
+			case ISDN_CTYPE_ELSA:
+			case ISDN_CTYPE_ELSA_PNP:
+			case ISDN_CTYPE_ELSA_PCMCIA:
+			case ISDN_CTYPE_ELSA_PCI:
+				ret = setup_elsa(card);
+				break;
 #endif
 #if CARD_IX1MICROR2
-		case ISDN_CTYPE_IX1MICROR2:
-			ret = setup_ix1micro(card);
-			break;
+			case ISDN_CTYPE_IX1MICROR2:
+				ret = setup_ix1micro(card);
+				break;
 #endif
 #if CARD_DIEHLDIVA
-		case ISDN_CTYPE_DIEHLDIVA:
-			ret = setup_diva(card);
-			break;
+			case ISDN_CTYPE_DIEHLDIVA:
+				ret = setup_diva(card);
+				break;
 #endif
 #if CARD_ASUSCOM
-		case ISDN_CTYPE_ASUSCOM:
-			ret = setup_asuscom(card);
-			break;
+			case ISDN_CTYPE_ASUSCOM:
+				ret = setup_asuscom(card);
+				break;
 #endif
 #if CARD_TELEINT
-		case ISDN_CTYPE_TELEINT:
-			ret = setup_TeleInt(card);
-			break;
+			case ISDN_CTYPE_TELEINT:
+				ret = setup_TeleInt(card);
+				break;
 #endif
 #if CARD_SEDLBAUER
-		case ISDN_CTYPE_SEDLBAUER:
-		case ISDN_CTYPE_SEDLBAUER_PCMCIA:
-		case ISDN_CTYPE_SEDLBAUER_FAX:
-			ret = setup_sedlbauer(card);
-			break;
+			case ISDN_CTYPE_SEDLBAUER:
+			case ISDN_CTYPE_SEDLBAUER_PCMCIA:
+			case ISDN_CTYPE_SEDLBAUER_FAX:
+				ret = setup_sedlbauer(card);
+				break;
 #endif
 #if CARD_SPORTSTER
-		case ISDN_CTYPE_SPORTSTER:
-			ret = setup_sportster(card);
-			break;
+			case ISDN_CTYPE_SPORTSTER:
+				ret = setup_sportster(card);
+				break;
 #endif
 #if CARD_MIC
-		case ISDN_CTYPE_MIC:
-			ret = setup_mic(card);
-			break;
+			case ISDN_CTYPE_MIC:
+				ret = setup_mic(card);
+				break;
 #endif
 #if CARD_NETJET
-		case ISDN_CTYPE_NETJET:
-			ret = setup_netjet(card);
-			break;
+			case ISDN_CTYPE_NETJET:
+				ret = setup_netjet(card);
+				break;
 #endif
-#if CARD_TELES3C
-		case ISDN_CTYPE_TELES3C:
-			ret = setup_t163c(card);
-			break;
+#if CARD_HFCS
+			case ISDN_CTYPE_TELES3C:
+			case ISDN_CTYPE_ACERP10:
+				ret = setup_hfcs(card);
+				break;
+#endif
+#if CARD_HFC_PCI
+		        case ISDN_CTYPE_HFC_PCI: 
+				ret = setup_hfcpci(card);
+				break;
 #endif
 #if CARD_NICCY
-		case ISDN_CTYPE_NICCY:
-			ret = setup_niccy(card);
-			break;
+			case ISDN_CTYPE_NICCY:
+				ret = setup_niccy(card);
+				break;
 #endif
 #if CARD_AMD7930
-		case ISDN_CTYPE_AMD7930:
-			ret = setup_amd7930(card);
+			case ISDN_CTYPE_AMD7930:
+				ret = setup_amd7930(card);
+				break;
+#endif
+#if CARD_ISURF
+			case ISDN_CTYPE_ISURF:
+				ret = setup_isurf(card);
+				break;
+#endif
+#if CARD_HSTSAPHIR
+			case ISDN_CTYPE_HSTSAPHIR:
+				ret = setup_saphir(card);
+				break;
+#endif
+#if CARD_TESTEMU
+			case ISDN_CTYPE_TESTEMU:
+				ret = setup_testemu(card);
+				break;
+#endif
+#if	CARD_BKM_A4T       
+           	case ISDN_CTYPE_BKM_A4T:
+	        	ret = setup_bkm_a4t(card);
 			break;
 #endif
+#if	CARD_SCT_QUADRO
+	        case ISDN_CTYPE_SCT_QUADRO:
+    			ret = setup_sct_quadro(card);
+			break;
+#endif
+#if CARD_GAZEL
+ 		case ISDN_CTYPE_GAZEL:
+ 			ret = setup_gazel(card);
+ 			break;
+#endif
 		default:
-			printk(KERN_WARNING "HiSax: Unknown Card Typ %d\n",
-			       card->typ);
+			printk(KERN_WARNING
+				"HiSax: Support for %s Card not selected\n",
+				CardType[card->typ]);
 			ll_unload(cs);
 			restore_flags(flags);
 			return (0);
+		}
+	} else {
+		printk(KERN_WARNING
+		       "HiSax: Card Type %d out of range\n",
+		       card->typ);
+		restore_flags(flags);
+		return (0);
 	}
 	if (!ret) {
 		ll_unload(cs);
@@ -1168,7 +1340,8 @@
 		ll_stop(cards[cardnr].cs);
 		release_tei(cards[cardnr].cs);
 		closecard(cardnr);
-		free_irq(cards[cardnr].cs->irq, cards[cardnr].cs);
+		if (cards[cardnr].cs->irq)
+			free_irq(cards[cardnr].cs->irq, cards[cardnr].cs);
 		kfree((void *) cards[cardnr].cs);
 		cards[cardnr].cs = NULL;
 	}
@@ -1180,8 +1353,6 @@
 	nrcards--;
 }
 
-EXPORT_SYMBOL(HiSax_closecard);
-
 void
 HiSax_reportcard(int cardnr)
 {
@@ -1202,11 +1373,13 @@
 		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);
@@ -1236,8 +1409,8 @@
 }
 
 
-int __init 
-HiSax_init(void)
+__initfunc(int
+HiSax_init(void))
 {
 	int i;
 
@@ -1246,18 +1419,27 @@
 #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
@@ -1318,16 +1500,29 @@
 			case ISDN_CTYPE_SPORTSTER:
 			case ISDN_CTYPE_MIC:
 			case ISDN_CTYPE_TELES3C:
+			case ISDN_CTYPE_ACERP10:
 			case ISDN_CTYPE_S0BOX:
 			case ISDN_CTYPE_FRITZPCI:
+			case ISDN_CTYPE_HSTSAPHIR:
+			case ISDN_CTYPE_GAZEL:
+				cards[i].para[0] = irq[i];
+				cards[i].para[1] = io[i];
+				break;
+			case ISDN_CTYPE_ISURF:
 				cards[i].para[0] = irq[i];
 				cards[i].para[1] = io[i];
+				cards[i].para[2] = mem[i];
 				break;
 			case ISDN_CTYPE_ELSA_PCI:
 			case ISDN_CTYPE_NETJET:
 			case ISDN_CTYPE_AMD7930:
 			case ISDN_CTYPE_TELESPCI:
 				break;
+			case ISDN_CTYPE_BKM_A4T:
+	  		   	break;
+			case ISDN_CTYPE_SCT_QUADRO:
+	          	cards[i].para[0] = irq[i];
+				break;
 		}
 	}
 	if (!nzproto) {
@@ -1353,11 +1548,13 @@
 	Isdnl1New();
 	if (HiSax_inithardware(NULL)) {
 		/* Install only, if at least one card found */
-		/* No symbols to export, hide all symbols */
-
 #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
+#endif /* COMPAT_HAS_NEW_SYMTAB */
+#endif /* MODULE */
 		return (0);
 	} else {
 		Isdnl1Free();
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/diva.c linux/drivers/isdn/hisax/diva.c
--- v2.3.13/linux/drivers/isdn/hisax/diva.c	Mon Aug  9 14:59:20 1999
+++ linux/drivers/isdn/hisax/diva.c	Thu Aug 12 09:42:33 1999
@@ -1,13 +1,36 @@
-/* $Id: diva.c,v 1.10 1998/11/15 23:54:31 keil Exp $
+/* $Id: diva.c,v 1.16 1999/08/11 21:01:25 keil Exp $
 
  * diva.c     low level stuff for Eicon.Diehl Diva Family ISDN cards
  *
  * Author     Karsten Keil (keil@isdn4linux.de)
  *
- * Thanks to Eicon Technology Diehl GmbH & Co. oHG for documents and informations
+ *		This file is (c) under GNU PUBLIC LICENSE
+ *		For changes and modifications please read
+ *		../../../Documentation/isdn/HiSax.cert
+ *
+ * Thanks to Eicon Technology for documents and informations
  *
  *
  * $Log: diva.c,v $
+ * Revision 1.16  1999/08/11 21:01:25  keil
+ * new PCI codefix
+ *
+ * Revision 1.15  1999/08/10 16:01:49  calle
+ * struct pci_dev changed in 2.3.13. Made the necessary changes.
+ *
+ * Revision 1.14  1999/08/07 17:35:08  keil
+ * approval for Eicon Technology Diva 2.01 PCI
+ *
+ * Revision 1.13  1999/07/21 14:46:07  keil
+ * changes from EICON certification
+ *
+ * Revision 1.12  1999/07/12 21:05:04  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 1.11  1999/07/01 08:11:29  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 1.10  1998/11/15 23:54:31  keil
  * changes from 2.0
  *
@@ -51,10 +74,13 @@
 #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.10 $";
+const char *Diva_revision = "$Revision: 1.16 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -75,6 +101,7 @@
 #define DIVA_ISA	1
 #define DIVA_PCI	2
 #define DIVA_IPAC_ISA	3
+#define DIVA_IPAC_PCI	4
 
 /* PCI stuff */
 #define PCI_VENDOR_EICON_DIEHL	0x1133
@@ -82,10 +109,12 @@
 #define PCI_DIVA20_ID		0xe002
 #define PCI_DIVA20PRO_U_ID	0xe003
 #define PCI_DIVA20_U_ID		0xe004
+#define PCI_DIVA_201		0xe005
 
 /* CTRL (Read) */
 #define DIVA_IRQ_STAT	0x01
 #define DIVA_EEPROM_SDA	0x02
+
 /* CTRL (Write) */
 #define DIVA_IRQ_REQ	0x01
 #define DIVA_RESET	0x08
@@ -96,6 +125,13 @@
 #define DIVA_ISA_LED_B	0x40
 #define DIVA_IRQ_CLR	0x80
 
+/* Siemens PITA */
+#define PITA_MISC_REG		0x1c
+#define PITA_PARA_SOFTRESET	0x01000000
+#define PITA_PARA_MPX_MODE	0x04000000
+#define PITA_INT0_ENABLE	0x00020000
+#define PITA_INT0_STATUS	0x00000002
+
 static inline u_char
 readreg(unsigned int ale, unsigned int adr, u_char off)
 {
@@ -140,6 +176,22 @@
 	outsb(adr, data, size);
 }
 
+static inline u_char
+memreadreg(unsigned long adr, u_char off)
+{
+	return(0xff & *((unsigned int *)
+		(((unsigned int *)adr) + off)));
+}
+
+static inline void
+memwritereg(unsigned long adr, u_char off, u_char data)
+{
+	register u_char *p;
+	
+	p = (unsigned char *)(((unsigned int *)adr) + off);
+	*p = data;
+}
+
 /* Interface functions */
 
 static u_char
@@ -204,6 +256,44 @@
 		cs->hw.diva.hscx, offset + (hscx ? 0x40 : 0), value);
 }
 
+static u_char
+MemReadISAC_IPAC(struct IsdnCardState *cs, u_char offset)
+{
+	return (memreadreg(cs->hw.diva.cfg_reg, offset+0x80));
+}
+
+static void
+MemWriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+	memwritereg(cs->hw.diva.cfg_reg, offset|0x80, value);
+}
+
+static void
+MemReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
+{
+	while(size--)
+		*data++ = memreadreg(cs->hw.diva.cfg_reg, 0x80);
+}
+
+static void
+MemWriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
+{
+	while(size--)
+		memwritereg(cs->hw.diva.cfg_reg, 0x80, *data++);
+}
+
+static u_char
+MemReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
+{
+	return(memreadreg(cs->hw.diva.cfg_reg, offset + (hscx ? 0x40 : 0)));
+}
+
+static void
+MemWriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
+{
+	memwritereg(cs->hw.diva.cfg_reg, offset + (hscx ? 0x40 : 0), value);
+}
+
 /*
  * fast interrupt HSCX stuff goes here
  */
@@ -225,8 +315,8 @@
 diva_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u_char val, sval, stat = 0;
-	int cnt=8;
+	u_char val, sval;
+	int cnt=5;
 
 	if (!cs) {
 		printk(KERN_WARNING "Diva: Spurious interrupt!\n");
@@ -234,44 +324,36 @@
 	}
 	while (((sval = bytein(cs->hw.diva.ctrl)) & DIVA_IRQ_REQ) && cnt) {
 		val = readreg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_ISTA + 0x40);
-		if (val) {
+		if (val)
 			hscx_int_main(cs, val);
-			stat |= 1;
-		}
 		val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_ISTA);
-		if (val) {
+		if (val)
 			isac_interrupt(cs, val);
-			stat |= 2;
-		}
 		cnt--;
 	}
 	if (!cnt)
 		printk(KERN_WARNING "Diva: IRQ LOOP\n");
-	if (stat & 1) {
-		writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK, 0xFF);
-		writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK + 0x40, 0xFF);
-		writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK, 0x0);
-		writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK + 0x40, 0x0);
-	}
-	if (stat & 2) {
-		writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_MASK, 0xFF);
-		writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_MASK, 0x0);
-	}
+	writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK, 0xFF);
+	writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK + 0x40, 0xFF);
+	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_MASK, 0x0);
+	writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK, 0x0);
+	writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK + 0x40, 0x0);
 }
 
 static void
-diva_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
+diva_irq_ipac_isa(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char ista,val;
-	int icnt=20;
+	int icnt=5;
 
 	if (!cs) {
 		printk(KERN_WARNING "Diva: Spurious interrupt!\n");
 		return;
 	}
 	ista = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ISTA);
-Start_IPAC:
+Start_IPACISA:
 	if (cs->debug & L1_DEB_IPAC)
 		debugl1(cs, "IPAC ISTA %02X", ista);
 	if (ista & 0x0f) {
@@ -298,7 +380,7 @@
 	ista  = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ISTA);
 	if ((ista & 0x3f) && icnt) {
 		icnt--;
-		goto Start_IPAC;
+		goto Start_IPACISA;
 	}
 	if (!icnt)
 		printk(KERN_WARNING "DIVA IPAC IRQ LOOP\n");
@@ -306,13 +388,348 @@
 	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xC0);
 }
 
+static inline void
+MemwaitforCEC(struct IsdnCardState *cs, int hscx)
+{
+	int to = 50;
+
+	while ((MemReadHSCX(cs, hscx, HSCX_STAR) & 0x04) && to) {
+		udelay(1);
+		to--;
+	}
+	if (!to)
+		printk(KERN_WARNING "HiSax: waitforCEC timeout\n");
+}
+
+
+static inline void
+MemwaitforXFW(struct IsdnCardState *cs, int hscx)
+{
+	int to = 50;
+
+	while ((!(MemReadHSCX(cs, hscx, HSCX_STAR) & 0x44) == 0x40) && to) {
+		udelay(1);
+		to--;
+	}
+	if (!to)
+		printk(KERN_WARNING "HiSax: waitforXFW timeout\n");
+}
+
+static inline void
+MemWriteHSCXCMDR(struct IsdnCardState *cs, int hscx, u_char data)
+{
+	long flags;
+
+	save_flags(flags);
+	cli();
+	MemwaitforCEC(cs, hscx);
+	MemWriteHSCX(cs, hscx, HSCX_CMDR, data);
+	restore_flags(flags);
+}
+
+static void
+Memhscx_empty_fifo(struct BCState *bcs, int count)
+{
+	u_char *ptr;
+	struct IsdnCardState *cs = bcs->cs;
+	long flags;
+	int cnt;
+
+	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+		debugl1(cs, "hscx_empty_fifo");
+
+	if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) {
+		if (cs->debug & L1_DEB_WARN)
+			debugl1(cs, "hscx_empty_fifo: incoming packet too large");
+		MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80);
+		bcs->hw.hscx.rcvidx = 0;
+		return;
+	}
+	save_flags(flags);
+	cli();
+	ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
+	cnt = count;
+	while (cnt--)
+		*ptr++ = memreadreg(cs->hw.diva.cfg_reg, bcs->hw.hscx.hscx ? 0x40 : 0);
+	MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80);
+	ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
+	bcs->hw.hscx.rcvidx += count;
+	restore_flags(flags);
+	if (cs->debug & L1_DEB_HSCX_FIFO) {
+		char *t = bcs->blog;
+
+		t += sprintf(t, "hscx_empty_fifo %c cnt %d",
+			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
+		QuickHex(t, ptr, count);
+		debugl1(cs, bcs->blog);
+	}
+}
+
+static void
+Memhscx_fill_fifo(struct BCState *bcs)
+{
+	struct IsdnCardState *cs = bcs->cs;
+	int more, count, cnt;
+	int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
+	u_char *ptr,*p;
+	long flags;
+
+
+	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+		debugl1(cs, "hscx_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 > fifo_size) {
+		more = !0;
+		count = fifo_size;
+	} else
+		count = bcs->tx_skb->len;
+	cnt = count;
+	MemwaitforXFW(cs, bcs->hw.hscx.hscx);
+	save_flags(flags);
+	cli();
+	p = ptr = bcs->tx_skb->data;
+	skb_pull(bcs->tx_skb, count);
+	bcs->tx_cnt -= count;
+	bcs->hw.hscx.count += count;
+	while(cnt--)
+		memwritereg(cs->hw.diva.cfg_reg, bcs->hw.hscx.hscx ? 0x40 : 0,
+			*p++);
+	MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, more ? 0x8 : 0xa);
+	restore_flags(flags);
+	if (cs->debug & L1_DEB_HSCX_FIFO) {
+		char *t = bcs->blog;
+
+		t += sprintf(t, "hscx_fill_fifo %c cnt %d",
+			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
+		QuickHex(t, ptr, count);
+		debugl1(cs, bcs->blog);
+	}
+}
+
+static inline void
+Memhscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
+{
+	u_char r;
+	struct BCState *bcs = cs->bcs + hscx;
+	struct sk_buff *skb;
+	int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
+	int count;
+
+	if (!test_bit(BC_FLG_INIT, &bcs->Flag))
+		return;
+
+	if (val & 0x80) {	/* RME */
+		r = MemReadHSCX(cs, hscx, HSCX_RSTA);
+		if ((r & 0xf0) != 0xa0) {
+			if (!(r & 0x80))
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "HSCX invalid frame");
+			if ((r & 0x40) && bcs->mode)
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "HSCX RDO mode=%d",
+						bcs->mode);
+			if (!(r & 0x20))
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "HSCX CRC error");
+			MemWriteHSCXCMDR(cs, hscx, 0x80);
+		} else {
+			count = MemReadHSCX(cs, hscx, HSCX_RBCL) & (
+				test_bit(HW_IPAC, &cs->HW_Flags)? 0x3f: 0x1f);
+			if (count == 0)
+				count = fifo_size;
+			Memhscx_empty_fifo(bcs, count);
+			if ((count = bcs->hw.hscx.rcvidx - 1) > 0) {
+				if (cs->debug & L1_DEB_HSCX_FIFO)
+					debugl1(cs, "HX Frame %d", count);
+				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);
+				}
+			}
+		}
+		bcs->hw.hscx.rcvidx = 0;
+		hscx_sched_event(bcs, B_RCVBUFREADY);
+	}
+	if (val & 0x40) {	/* RPF */
+		Memhscx_empty_fifo(bcs, fifo_size);
+		if (bcs->mode == L1_MODE_TRANS) {
+			/* receive audio data */
+			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);
+			}
+			bcs->hw.hscx.rcvidx = 0;
+			hscx_sched_event(bcs, B_RCVBUFREADY);
+		}
+	}
+	if (val & 0x10) {	/* XPR */
+		if (bcs->tx_skb) {
+			if (bcs->tx_skb->len) {
+				Memhscx_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.hscx.count);
+				idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+				bcs->hw.hscx.count = 0; 
+				bcs->tx_skb = NULL;
+			}
+		}
+		if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+			bcs->hw.hscx.count = 0;
+			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+			Memhscx_fill_fifo(bcs);
+		} else {
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+			hscx_sched_event(bcs, B_XMTBUFREADY);
+		}
+	}
+}
+
+static inline void
+Memhscx_int_main(struct IsdnCardState *cs, u_char val)
+{
+
+	u_char exval;
+	struct BCState *bcs;
+
+	if (val & 0x01) {
+		bcs = cs->bcs + 1;
+		exval = MemReadHSCX(cs, 1, HSCX_EXIR);
+		if (exval & 0x40) {
+			if (bcs->mode == 1)
+				Memhscx_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.hscx.count);
+					bcs->tx_cnt += bcs->hw.hscx.count;
+					bcs->hw.hscx.count = 0;
+				}
+				MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "HSCX B EXIR %x Lost TX", exval);
+			}
+		} else if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX B EXIR %x", exval);
+	}
+	if (val & 0xf8) {
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX B interrupt %x", val);
+		Memhscx_interrupt(cs, val, 1);
+	}
+	if (val & 0x02) {
+		bcs = cs->bcs;
+		exval = MemReadHSCX(cs, 0, HSCX_EXIR);
+		if (exval & 0x40) {
+			if (bcs->mode == L1_MODE_TRANS)
+				Memhscx_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.hscx.count);
+					bcs->tx_cnt += bcs->hw.hscx.count;
+					bcs->hw.hscx.count = 0;
+				}
+				MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "HSCX A EXIR %x Lost TX", exval);
+			}
+		} else if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX A EXIR %x", exval);
+	}
+	if (val & 0x04) {
+		exval = MemReadHSCX(cs, 0, HSCX_ISTA);
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX A interrupt %x", exval);
+		Memhscx_interrupt(cs, exval, 0);
+	}
+}
+
+static void
+diva_irq_ipac_pci(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char ista,val;
+	int icnt=5;
+	u_char *cfg;
+
+	if (!cs) {
+		printk(KERN_WARNING "Diva: Spurious interrupt!\n");
+		return;
+	}
+	cfg = (u_char *) cs->hw.diva.pci_cfg;
+	val = *cfg;
+	if (!(val & PITA_INT0_STATUS))
+		return; /* other shared IRQ */
+	*cfg = PITA_INT0_STATUS; /* Reset pending INT0 */
+	ista = memreadreg(cs->hw.diva.cfg_reg, IPAC_ISTA);
+Start_IPACPCI:
+	if (cs->debug & L1_DEB_IPAC)
+		debugl1(cs, "IPAC ISTA %02X", ista);
+	if (ista & 0x0f) {
+		val = memreadreg(cs->hw.diva.cfg_reg, HSCX_ISTA + 0x40);
+		if (ista & 0x01)
+			val |= 0x01;
+		if (ista & 0x04)
+			val |= 0x02;
+		if (ista & 0x08)
+			val |= 0x04;
+		if (val)
+			Memhscx_int_main(cs, val);
+	}
+	if (ista & 0x20) {
+		val = 0xfe & memreadreg(cs->hw.diva.cfg_reg, ISAC_ISTA + 0x80);
+		if (val) {
+			isac_interrupt(cs, val);
+		}
+	}
+	if (ista & 0x10) {
+		val = 0x01;
+		isac_interrupt(cs, val);
+	}
+	ista  = memreadreg(cs->hw.diva.cfg_reg, IPAC_ISTA);
+	if ((ista & 0x3f) && icnt) {
+		icnt--;
+		goto Start_IPACPCI;
+	}
+	if (!icnt)
+		printk(KERN_WARNING "DIVA IPAC PCI IRQ LOOP\n");
+	memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xFF);
+	memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xC0);
+}
 
 void
 release_io_diva(struct IsdnCardState *cs)
 {
 	int bytecnt;
 
-	if (cs->subtyp != DIVA_IPAC_ISA) {
+	if (cs->subtyp == DIVA_IPAC_PCI) {
+		u_int *cfg = (unsigned int *)cs->hw.diva.pci_cfg;
+
+		*cfg = 0; /* disable INT0/1 */ 
+		*cfg = 2; /* reset pending INT0 */
+		iounmap((void *)cs->hw.diva.cfg_reg);
+		iounmap((void *)cs->hw.diva.pci_cfg);
+		return;
+	} else if (cs->subtyp != DIVA_IPAC_ISA) {
 		del_timer(&cs->hw.diva.tl);
 		if (cs->hw.diva.cfg_reg)
 			byteout(cs->hw.diva.ctrl, 0); /* LED off, Reset */
@@ -336,24 +753,37 @@
 	if (cs->subtyp == DIVA_IPAC_ISA) {
 		writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x20);
 		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
+		schedule_timeout((10*HZ)/1000);
 		writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x00);
 		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
+		schedule_timeout((10*HZ)/1000);
 		writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xc0);
-	} else {
+	} 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;
+		schedule_timeout((10*HZ)/1000);
+		*ireg = PITA_PARA_MPX_MODE;
+		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;
-		schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
+		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;
-		schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
+		schedule_timeout((10*HZ)/1000);
 		if (cs->subtyp == DIVA_ISA)
 			cs->hw.diva.ctrl_reg |= DIVA_ISA_LED_A;
-		else
+		else {
+			/* Workaround PCI9060 */
+			byteout(cs->hw.diva.pci_cfg + 0x69, 9);
 			cs->hw.diva.ctrl_reg |= DIVA_PCI_LED_A;
+		}
 		byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
 	}
 	restore_flags(flags);
@@ -366,7 +796,7 @@
 {
 	int blink = 0;
 
-	if (cs->subtyp == DIVA_IPAC_ISA)
+	if ((cs->subtyp == DIVA_IPAC_ISA) || (cs->subtyp == DIVA_IPAC_PCI))
 		return;
 	del_timer(&cs->hw.diva.tl);
 	if (cs->hw.diva.status & DIVA_ASSIGN)
@@ -399,7 +829,7 @@
 static int
 Diva_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
-	u_int irq_flag = I4L_IRQ_FLAG;
+	u_int *ireg;
 
 	switch (mt) {
 		case CARD_RESET:
@@ -408,17 +838,11 @@
 		case CARD_RELEASE:
 			release_io_diva(cs);
 			return(0);
-		case CARD_SETIRQ:
-			if (cs->subtyp == DIVA_PCI)
-				irq_flag |= SA_SHIRQ;
-			if (cs->subtyp == DIVA_IPAC_ISA) {
-				return(request_irq(cs->irq, &diva_interrupt_ipac,
-						irq_flag, "HiSax", cs));
-			} else {
-				return(request_irq(cs->irq, &diva_interrupt,
-						irq_flag, "HiSax", cs));
-			}
 		case CARD_INIT:
+			if (cs->subtyp == DIVA_IPAC_PCI) {
+				ireg = (unsigned int *)cs->hw.diva.pci_cfg;
+				*ireg = PITA_INT0_ENABLE;
+			}
 			inithscxisac(cs, 3);
 			return(0);
 		case CARD_TEST:
@@ -451,16 +875,21 @@
 			}
 			break;
 	}
-	if (cs->subtyp != DIVA_IPAC_ISA)
+	if ((cs->subtyp != DIVA_IPAC_ISA) && (cs->subtyp != DIVA_IPAC_PCI))
 		diva_led_handler(cs);
 	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;
@@ -478,7 +907,7 @@
 		val = readreg(cs->hw.diva.cfg_reg + DIVA_IPAC_ADR,
 			cs->hw.diva.cfg_reg + DIVA_IPAC_DATA, IPAC_ID);
 		printk(KERN_INFO "Diva: IPAC version %x\n", val);
-		if (val == 1) {
+		if ((val == 1) || (val==2)) {
 			cs->subtyp = DIVA_IPAC_ISA;
 			cs->hw.diva.ctrl = 0;
 			cs->hw.diva.isac = card->para[1] + DIVA_IPAC_DATA;
@@ -498,6 +927,7 @@
 		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);
@@ -506,20 +936,26 @@
 		cs->subtyp = 0;
 		if ((dev_diva = pci_find_device(PCI_VENDOR_EICON_DIEHL,
 			PCI_DIVA20_ID, dev_diva))) {
-				cs->subtyp = DIVA_PCI;
-			/* get IRQ */
+			cs->subtyp = DIVA_PCI;
 			cs->irq = dev_diva->irq;
-			/* get IO address */
-			cs->hw.diva.cfg_reg = dev_diva->resource[2].start
+			cs->hw.diva.cfg_reg = get_pcibase(dev_diva, 2)
 				& 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;
-			/* get IRQ */
+			cs->subtyp = DIVA_PCI;
 			cs->irq = dev_diva_u->irq;
-			/* get IO address */
-			cs->hw.diva.cfg_reg = dev_diva_u->resource[2].start
+			cs->hw.diva.cfg_reg = get_pcibase(dev_diva_u, 2)
 				& 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)
+					& PCI_BASE_ADDRESS_IO_MASK), 4096);
+			cs->hw.diva.cfg_reg =
+				(ulong) ioremap((get_pcibase(dev_diva201, 1)
+					& PCI_BASE_ADDRESS_IO_MASK), 4096);
 		} else {
 			printk(KERN_WARNING "Diva: No PCI card found\n");
 			return(0);
@@ -534,35 +970,112 @@
 			printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n");
 			return(0);
 		}
-		cs->hw.diva.ctrl = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL;
-		cs->hw.diva.isac = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_DATA;
-		cs->hw.diva.hscx = cs->hw.diva.cfg_reg + DIVA_HSCX_DATA;
-		cs->hw.diva.isac_adr = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_ADR;
-		cs->hw.diva.hscx_adr = cs->hw.diva.cfg_reg + DIVA_HSCX_ADR;
-		bytecnt = 32;
+#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");
 		printk(KERN_WARNING "Diva: unable to config DIVA PCI\n");
 		return (0);
 #endif /* CONFIG_PCI */
+		if (cs->subtyp == DIVA_IPAC_PCI) {
+			cs->hw.diva.ctrl = 0;
+			cs->hw.diva.isac = 0;
+			cs->hw.diva.hscx = 0;
+			cs->hw.diva.isac_adr = 0;
+			cs->hw.diva.hscx_adr = 0;
+			test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+			bytecnt = 0;
+		} else {
+			cs->hw.diva.ctrl = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL;
+			cs->hw.diva.isac = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_DATA;
+			cs->hw.diva.hscx = cs->hw.diva.cfg_reg + DIVA_HSCX_DATA;
+			cs->hw.diva.isac_adr = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_ADR;
+			cs->hw.diva.hscx_adr = cs->hw.diva.cfg_reg + DIVA_HSCX_ADR;
+			bytecnt = 32;
+		}
 	}
 
 	printk(KERN_INFO
-		"Diva: %s card configured at 0x%x IRQ %d\n",
+		"Diva: %s card configured at %#lx IRQ %d\n",
 		(cs->subtyp == DIVA_PCI) ? "PCI" :
-		(cs->subtyp == DIVA_ISA) ? "ISA" : "IPAC",
+		(cs->subtyp == DIVA_ISA) ? "ISA" : 
+		(cs->subtyp == DIVA_IPAC_ISA) ? "IPAC ISA" : "IPAC PCI",
 		cs->hw.diva.cfg_reg, cs->irq);
-	if (check_region(cs->hw.diva.cfg_reg, bytecnt)) {
-		printk(KERN_WARNING
-		       "HiSax: %s config port %x-%x already in use\n",
-		       CardType[card->typ],
-		       cs->hw.diva.cfg_reg,
-		       cs->hw.diva.cfg_reg + bytecnt);
-		return (0);
-	} else {
-		request_region(cs->hw.diva.cfg_reg, bytecnt, "diva isdn");
+	if ((cs->subtyp == DIVA_IPAC_PCI) || (cs->subtyp == DIVA_PCI))
+		printk(KERN_INFO "Diva: %s PCI space at %#lx\n",
+			(cs->subtyp == DIVA_PCI) ? "PCI" : "IPAC PCI",
+			cs->hw.diva.pci_cfg);
+	if (cs->subtyp != DIVA_IPAC_PCI) {
+		if (check_region(cs->hw.diva.cfg_reg, bytecnt)) {
+			printk(KERN_WARNING
+			       "HiSax: %s config port %lx-%lx already in use\n",
+			       CardType[card->typ],
+			       cs->hw.diva.cfg_reg,
+			       cs->hw.diva.cfg_reg + bytecnt);
+			return (0);
+		} else {
+			request_region(cs->hw.diva.cfg_reg, bytecnt, "diva isdn");
+		}
 	}
-
 	reset_diva(cs);
 	cs->BC_Read_Reg  = &ReadHSCX;
 	cs->BC_Write_Reg = &WriteHSCX;
@@ -573,9 +1086,21 @@
 		cs->writeisac = &WriteISAC_IPAC;
 		cs->readisacfifo  = &ReadISACfifo_IPAC;
 		cs->writeisacfifo = &WriteISACfifo_IPAC;
+		cs->irq_func = &diva_irq_ipac_isa;
 		val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ID);
 		printk(KERN_INFO "Diva: IPAC version %x\n", val);
-	} else {
+	} else if (cs->subtyp == DIVA_IPAC_PCI) {
+		cs->readisac  = &MemReadISAC_IPAC;
+		cs->writeisac = &MemWriteISAC_IPAC;
+		cs->readisacfifo  = &MemReadISACfifo_IPAC;
+		cs->writeisacfifo = &MemWriteISACfifo_IPAC;
+		cs->BC_Read_Reg  = &MemReadHSCX;
+		cs->BC_Write_Reg = &MemWriteHSCX;
+		cs->BC_Send_Data = &Memhscx_fill_fifo;
+		cs->irq_func = &diva_irq_ipac_pci;
+		val = memreadreg(cs->hw.diva.cfg_reg, IPAC_ID);
+		printk(KERN_INFO "Diva: IPAC version %x\n", val);
+	} else { /* DIVA 2.0 */
 		cs->hw.diva.tl.function = (void *) diva_led_handler;
 		cs->hw.diva.tl.data = (long) cs;
 		init_timer(&cs->hw.diva.tl);
@@ -583,6 +1108,7 @@
 		cs->writeisac = &WriteISAC;
 		cs->readisacfifo  = &ReadISACfifo;
 		cs->writeisacfifo = &WriteISACfifo;
+		cs->irq_func = &diva_interrupt;
 		ISACVersion(cs, "Diva:");
 		if (HscxVersion(cs, "Diva:")) {
 			printk(KERN_WARNING
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/elsa.c linux/drivers/isdn/hisax/elsa.c
--- v2.3.13/linux/drivers/isdn/hisax/elsa.c	Mon Aug  9 14:59:20 1999
+++ linux/drivers/isdn/hisax/elsa.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: elsa.c,v 2.12 1998/11/15 23:54:35 keil Exp $
+/* $Id: elsa.c,v 2.17 1999/08/11 20:57:40 keil Exp $
 
  * elsa.c     low level stuff for Elsa isdn cards
  *
@@ -13,8 +13,26 @@
  *              Klaus Lichtenwalder (Klaus.Lichtenwalder@WebForum.DE)
  *              for ELSA PCMCIA support
  *
- *
  * $Log: elsa.c,v $
+ * Revision 2.17  1999/08/11 20:57:40  keil
+ * bugfix IPAC version 1.1
+ * new PCI codefix
+ *
+ * Revision 2.16  1999/08/10 16:01:51  calle
+ * struct pci_dev changed in 2.3.13. Made the necessary changes.
+ *
+ * Revision 2.15  1999/08/09 19:25:21  keil
+ * Support (alpha version) for the '98 model of ELSA Microlink ISDN/MC
+ * by Christer Weinigel, Cendio Systems AB <wingel@cendio.se>
+ * Add support for IPAC 1.2
+ *
+ * Revision 2.14  1999/07/12 21:05:07  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 2.13  1999/07/01 08:11:31  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 2.12  1998/11/15 23:54:35  keil
  * changes from 2.0
  *
@@ -70,16 +88,19 @@
 #include "hscx.h"
 #include "isdnl1.h"
 #include <linux/pci.h>
-
-//#define KDEBUG_DEF
-//#include "../kdebug.h"
+#ifndef COMPAT_HAS_NEW_PCI
+#include <linux/bios32.h>
+#endif
+#include <linux/serial.h>
+#include <linux/serial_reg.h>
 
 extern const char *CardType[];
 
-static const char *Elsa_revision = "$Revision: 2.12 $";
+const char *Elsa_revision = "$Revision: 2.17 $";
 const char *Elsa_Types[] =
 {"None", "PC", "PCC-8", "PCC-16", "PCF", "PCF-Pro",
- "PCMCIA", "QS 1000", "QS 3000", "QS 1000 PCI", "QS 3000 PCI"};
+ "PCMCIA", "QS 1000", "QS 3000", "QS 1000 PCI", "QS 3000 PCI", 
+ "PCMCIA-IPAC" };
 
 const char *ITACVer[] =
 {"?0?", "?1?", "?2?", "?3?", "?4?", "V2.2",
@@ -109,6 +130,7 @@
 #define ELSA_QS3000  8
 #define ELSA_QS1000PCI 9
 #define ELSA_QS3000PCI 10
+#define ELSA_PCMCIA_IPAC 11
 
 /* PCI stuff */
 #define PCI_VENDOR_ELSA	0x1048
@@ -158,16 +180,26 @@
 #define ELSA_IPAC_LINE_LED	0x40	/* Bit 6 Gelbe LED */
 #define ELSA_IPAC_STAT_LED	0x80	/* Bit 7 Gruene LED */
 
-const u_char ARCOFI_VERSION[] = {2,0xa0,0};
-const u_char ARCOFI_COP_5[] = {4,0xa1,0x25,0xbb,0x4a}; /* GTX */
-const u_char ARCOFI_COP_6[] = {6,0xa1,0x26,0,0,0x82,0x7c}; /* GRL GRH */
-const u_char ARCOFI_COP_7[] = {4,0xa1,0x27,0x80,0x80}; /* GZ */
-const u_char ARCOFI_COP_8[] = {10,0xa1,0x28,0x49,0x31,0x8,0x13,0x6e,0x88,0x2a,0x61}; /* TX */
-const u_char ARCOFI_COP_9[] = {10,0xa1,0x29,0x80,0xcb,0xe9,0x88,0x00,0xc8,0xd8,0x80}; /* RX */
-const u_char ARCOFI_XOP_0[] = {2,0xa1,0x30}; /* PWR Down */
-const u_char ARCOFI_XOP_1[] = {2,0xa1,0x31}; /* PWR UP */
-const u_char ARCOFI_XOP_F[] = {2,0xa1,0x3f}; /* Normal OP */
-const u_char ARCOFI_SOP_F[] = {10,0xa1,0x1f,0x00,0x50,0x10,0x00,0x00,0x80,0x02,0x12};
+static struct arcofi_msg ARCOFI_XOP_F =
+	{NULL,0,2,{0xa1,0x3f,0,0,0,0,0,0,0,0}}; /* Normal OP */
+static struct arcofi_msg ARCOFI_XOP_1 =
+	{&ARCOFI_XOP_F,0,2,{0xa1,0x31,0,0,0,0,0,0,0,0}}; /* PWR UP */
+static struct arcofi_msg ARCOFI_SOP_F = 
+	{&ARCOFI_XOP_1,0,10,{0xa1,0x1f,0x00,0x50,0x10,0x00,0x00,0x80,0x02,0x12}};
+static struct arcofi_msg ARCOFI_COP_9 =
+	{&ARCOFI_SOP_F,0,10,{0xa1,0x29,0x80,0xcb,0xe9,0x88,0x00,0xc8,0xd8,0x80}}; /* RX */
+static struct arcofi_msg ARCOFI_COP_8 =
+	{&ARCOFI_COP_9,0,10,{0xa1,0x28,0x49,0x31,0x8,0x13,0x6e,0x88,0x2a,0x61}}; /* TX */
+static struct arcofi_msg ARCOFI_COP_7 =
+	{&ARCOFI_COP_8,0,4,{0xa1,0x27,0x80,0x80,0,0,0,0,0,0}}; /* GZ */
+static struct arcofi_msg ARCOFI_COP_6 =
+	{&ARCOFI_COP_7,0,6,{0xa1,0x26,0,0,0x82,0x7c,0,0,0,0}}; /* GRL GRH */
+static struct arcofi_msg ARCOFI_COP_5 =
+	{&ARCOFI_COP_6,0,4,{0xa1,0x25,0xbb,0x4a,0,0,0,0,0,0}}; /* GTX */
+static struct arcofi_msg ARCOFI_VERSION =
+	{NULL,1,2,{0xa0,0,0,0,0,0,0,0,0,0}};
+static struct arcofi_msg ARCOFI_XOP_0 =
+	{NULL,0,2,{0xa1,0x30,0,0,0,0,0,0,0,0}}; /* PWR Down */
 
 static void set_arcofi(struct IsdnCardState *cs, int bc);
 
@@ -343,7 +375,7 @@
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char val;
-	int icnt=20;
+	int icnt=5;
 
 	if (!cs) {
 		printk(KERN_WARNING "Elsa: Spurious interrupt!\n");
@@ -420,15 +452,17 @@
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char ista,val;
-	int icnt=20;
+	int icnt=5;
 
 	if (!cs) {
 		printk(KERN_WARNING "Elsa: Spurious interrupt!\n");
 		return;
 	}
-	val = bytein(cs->hw.elsa.cfg + 0x4c); /* PCI IRQ */
-	if (!(val & ELSA_PCI_IRQ_MASK))
-		return;
+	if (cs->subtyp == ELSA_QS1000PCI || cs->subtyp == ELSA_QS3000PCI) {
+		val = bytein(cs->hw.elsa.cfg + 0x4c); /* PCI IRQ */
+		if (!(val & ELSA_PCI_IRQ_MASK))
+			return;
+	}
 #if ARCOFI_USE
 	if (cs->hw.elsa.MFlag) {
 		val = serial_inp(cs, UART_IIR);
@@ -480,6 +514,7 @@
 	int bytecnt = 8;
 
 	del_timer(&cs->hw.elsa.tl);
+	clear_arcofi(cs);
 	if (cs->hw.elsa.ctrl)
 		byteout(cs->hw.elsa.ctrl, 0);	/* LEDs Out */
 	if (cs->subtyp == ELSA_QS1000PCI) {
@@ -493,6 +528,9 @@
 		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff);
 		release_region(cs->hw.elsa.cfg, 0x80);
 	}
+ 	if (cs->subtyp == ELSA_PCMCIA_IPAC) {
+		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff);
+ 	}
 	if ((cs->subtyp == ELSA_PCFPRO) ||
 		(cs->subtyp == ELSA_QS3000) ||
 		(cs->subtyp == ELSA_PCF) ||
@@ -527,19 +565,25 @@
 		if (cs->hw.elsa.trig)
 			byteout(cs->hw.elsa.trig, 0xff);
 	}
-	if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI)) {
+	if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI) || (cs->subtyp == ELSA_PCMCIA_IPAC)) {
 		save_flags(flags);
 		sti();
 		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_POTA2, 0x20);
 		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
+		schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
 		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_POTA2, 0x00);
 		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
 		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xc0);
+		schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
 		restore_flags(flags);
-		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ACFG, 0x0);
-		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_AOE, 0x3c);
+		if (cs->subtyp != ELSA_PCMCIA_IPAC) {
+			writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ACFG, 0x0);
+			writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_AOE, 0x3c);
+		} else {
+			writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_PCFG, 0x10);
+			writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ACFG, 0x4);
+			writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_AOE, 0xf8);
+		}
 		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff);
 		if (cs->subtyp == ELSA_QS1000PCI)
 			byteout(cs->hw.elsa.cfg + 0x4c, 0x41); /* enable ELSA PCI IRQ */
@@ -549,40 +593,10 @@
 }
 
 static void
-init_arcofi(struct IsdnCardState *cs) {
-	send_arcofi(cs, ARCOFI_XOP_0, 1, 0);
-/*	send_arcofi(cs, ARCOFI_XOP_F, 1);
-*/
-}
-
-#define ARCDEL 500
-
-static void
 set_arcofi(struct IsdnCardState *cs, int bc) {
-	long flags;
-
-	debugl1(cs,"set_arcofi bc=%d", bc);
-	save_flags(flags);
-	sti();
-	send_arcofi(cs, ARCOFI_XOP_0, bc, 0);
-	udelay(ARCDEL);
-	send_arcofi(cs, ARCOFI_COP_5, bc, 0);
-	udelay(ARCDEL);
-	send_arcofi(cs, ARCOFI_COP_6, bc, 0);
-	udelay(ARCDEL);
-	send_arcofi(cs, ARCOFI_COP_7, bc, 0);
-	udelay(ARCDEL);
-	send_arcofi(cs, ARCOFI_COP_8, bc, 0);
-	udelay(ARCDEL);
-	send_arcofi(cs, ARCOFI_COP_9, bc, 0);
-	udelay(ARCDEL);
-	send_arcofi(cs, ARCOFI_SOP_F, bc, 0);
-	udelay(ARCDEL);
-	send_arcofi(cs, ARCOFI_XOP_1, bc, 0);
-	udelay(ARCDEL);
-	send_arcofi(cs, ARCOFI_XOP_F, bc, 0);
-	restore_flags(flags);
-	debugl1(cs,"end set_arcofi bc=%d", bc);
+	cs->dc.isac.arcofi_bc = bc;
+	arcofi_fsm(cs, ARCOFI_START, &ARCOFI_COP_5);
+	interruptible_sleep_on(&cs->dc.isac.arcofi_wait);
 }
 
 static int
@@ -594,23 +608,24 @@
 	char *t;
 	u_char *p;
 
-	if (!cs->mon_tx)
-		if (!(cs->mon_tx=kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) {
+	if (!cs->dc.isac.mon_tx)
+		if (!(cs->dc.isac.mon_tx=kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) {
 			if (cs->debug & L1_DEB_WARN)
 				debugl1(cs, "ISAC MON TX out of buffers!");
 			return(0);
 		}
-	send_arcofi(cs, ARCOFI_VERSION, 0, 1);
-	if (test_and_clear_bit(HW_MON1_TX_END, &cs->HW_Flags)) {
-		if (test_and_clear_bit(HW_MON1_RX_END, &cs->HW_Flags)) {
-			debugl1(cs, "Arcofi response received %d bytes", cs->mon_rxp);
-			p = cs->mon_rx;
+	cs->dc.isac.arcofi_bc = 0;
+	arcofi_fsm(cs, ARCOFI_START, &ARCOFI_VERSION);
+	interruptible_sleep_on(&cs->dc.isac.arcofi_wait);
+	if (!test_and_clear_bit(FLG_ARCOFI_ERROR, &cs->HW_Flags)) {
+			debugl1(cs, "Arcofi response received %d bytes", cs->dc.isac.mon_rxp);
+			p = cs->dc.isac.mon_rx;
 			t = tmp;
 			t += sprintf(tmp, "Arcofi data");
-			QuickHex(t, p, cs->mon_rxp);
+			QuickHex(t, p, cs->dc.isac.mon_rxp);
 			debugl1(cs, tmp);
-			if ((cs->mon_rxp == 2) && (cs->mon_rx[0] == 0xa0)) {
-				switch(cs->mon_rx[1]) {
+			if ((cs->dc.isac.mon_rxp == 2) && (cs->dc.isac.mon_rx[0] == 0xa0)) {
+				switch(cs->dc.isac.mon_rx[1]) {
 					case 0x80:
 						debugl1(cs, "Arcofi 2160 detected");
 						arcofi_present = 1;
@@ -629,9 +644,8 @@
 				}
 			} else
 				debugl1(cs, "undefined Monitor response");
-			cs->mon_rxp = 0;
-		}
-	} else if (cs->mon_tx) {
+			cs->dc.isac.mon_rxp = 0;
+	} else if (cs->dc.isac.mon_tx) {
 		debugl1(cs, "Arcofi not detected");
 	}
 	if (arcofi_present) {
@@ -672,7 +686,8 @@
 				"Elsa: %s detected modem at 0x%x\n",
 				Elsa_Types[cs->subtyp],
 				cs->hw.elsa.base+8);
-		init_arcofi(cs);
+		arcofi_fsm(cs, ARCOFI_START, &ARCOFI_XOP_0);
+		interruptible_sleep_on(&cs->dc.isac.arcofi_wait);
 		return(1);
 	}
 #endif
@@ -684,7 +699,7 @@
 {
 	int blink = 0;
 
-	if (cs->subtyp == ELSA_PCMCIA)
+	if (cs->subtyp == ELSA_PCMCIA || cs->subtyp == ELSA_PCMCIA_IPAC)
 		return;
 	del_timer(&cs->hw.elsa.tl);
 	if (cs->hw.elsa.status & ELSA_ASSIGN)
@@ -734,15 +749,6 @@
 		case CARD_RELEASE:
 			release_io_elsa(cs);
 			return(0);
-		case CARD_SETIRQ:
-			if ((cs->subtyp == ELSA_QS1000PCI) ||
-				(cs->subtyp == ELSA_QS3000PCI))
-				ret = request_irq(cs->irq, &elsa_interrupt_ipac,
-					I4L_IRQ_FLAG | SA_SHIRQ, "HiSax", cs);
-			else
-				ret = request_irq(cs->irq, &elsa_interrupt,
-					I4L_IRQ_FLAG, "HiSax", cs);
-			return(ret);
 		case CARD_INIT:
 			cs->debug |= L1_DEB_IPAC;
 			inithscxisac(cs, 1);
@@ -757,6 +763,7 @@
 			return(0);
 		case CARD_TEST:
 			if ((cs->subtyp == ELSA_PCMCIA) ||
+				(cs->subtyp == ELSA_PCMCIA_IPAC) ||
 				(cs->subtyp == ELSA_QS1000PCI)) {
 				return(0);
 			} else if (cs->subtyp == ELSA_QS3000PCI) {
@@ -770,7 +777,6 @@
 				byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);
 				byteout(cs->hw.elsa.timer, 0);
 				current->state = TASK_INTERRUPTIBLE;
-				/* Timeout 110ms */
 				schedule_timeout((110*HZ)/1000);
 				restore_flags(flags);
 				cs->hw.elsa.ctrl_reg &= ~ELSA_ENA_TIMER_INT;
@@ -908,8 +914,12 @@
 	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)
@@ -1004,10 +1014,19 @@
 	} else if (cs->typ == ISDN_CTYPE_ELSA_PCMCIA) {
 		cs->hw.elsa.base = card->para[1];
 		cs->irq = card->para[0];
-		cs->subtyp = ELSA_PCMCIA;
-		cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE_PCM;
-		cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC_PCM;
-		cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
+		val = readreg(cs->hw.elsa.base + 0, cs->hw.elsa.base + 2, IPAC_ID);
+		if ((val == 1) || (val == 2)) { /* IPAC version 1.1/1.2 */
+			cs->subtyp = ELSA_PCMCIA_IPAC;
+			cs->hw.elsa.ale = cs->hw.elsa.base + 0;
+			cs->hw.elsa.isac = cs->hw.elsa.base + 2;
+			cs->hw.elsa.hscx = cs->hw.elsa.base + 2;
+			test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+		} else {
+			cs->subtyp = ELSA_PCMCIA;
+			cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE_PCM;
+			cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC_PCM;
+			cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
+		}
 		cs->hw.elsa.timer = 0;
 		cs->hw.elsa.trig = 0;
 		cs->hw.elsa.ctrl = 0;
@@ -1018,6 +1037,7 @@
 		       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);
@@ -1027,17 +1047,17 @@
 			 dev_qs1000))) {
 				cs->subtyp = ELSA_QS1000PCI;
 			cs->irq = dev_qs1000->irq;
-			cs->hw.elsa.cfg = dev_qs1000->resource[1].start & 
+			cs->hw.elsa.cfg = get_pcibase(dev_qs1000, 1) & 
 				PCI_BASE_ADDRESS_IO_MASK;
-			cs->hw.elsa.base = dev_qs1000->resource[3].start & 
+			cs->hw.elsa.base = get_pcibase(dev_qs1000, 3) & 
 				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 = dev_qs3000->resource[1].start & 
+			cs->hw.elsa.cfg = get_pcibase(dev_qs3000, 1) & 
 				PCI_BASE_ADDRESS_IO_MASK;
-			cs->hw.elsa.base = dev_qs3000->resource[3].start & 
+			cs->hw.elsa.base = get_pcibase(dev_qs3000, 3) & 
 				PCI_BASE_ADDRESS_IO_MASK;
 		} else {
 			printk(KERN_WARNING "Elsa: No PCI card found\n");
@@ -1052,18 +1072,6 @@
 			printk(KERN_WARNING "Elsa: No IO-Adr for PCI card found\n");
 			return(0);
 		}
-		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; 
-		test_and_set_bit(HW_IPAC, &cs->HW_Flags);
-		cs->hw.elsa.timer = 0;
-		cs->hw.elsa.trig  = 0;
-		printk(KERN_INFO
-			"Elsa: %s defined at 0x%x/0x%x IRQ %d\n",
-			Elsa_Types[cs->subtyp],
-			cs->hw.elsa.base,
-			cs->hw.elsa.cfg,
-			cs->irq);
 		if ((cs->hw.elsa.cfg & 0xff) || (cs->hw.elsa.base & 0xf)) {
 			printk(KERN_WARNING "Elsa: You may have a wrong PCI bios\n");
 			printk(KERN_WARNING "Elsa: If your system hangs now, read\n");
@@ -1075,6 +1083,67 @@
 			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; 
+		test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+		cs->hw.elsa.timer = 0;
+		cs->hw.elsa.trig  = 0;
+		cs->irq_flags |= SA_SHIRQ;
+		printk(KERN_INFO
+		       "Elsa: %s defined at 0x%x/0x%x IRQ %d\n",
+		       Elsa_Types[cs->subtyp],
+		       cs->hw.elsa.base,
+		       cs->hw.elsa.cfg,
+		       cs->irq);
+#else
 		printk(KERN_WARNING "Elsa: Elsa PCI and NO_PCI_BIOS\n");
 		printk(KERN_WARNING "Elsa: unable to config Elsa PCI\n");
 		return (0);
@@ -1088,6 +1157,7 @@
 		case ELSA_PCC16:
 		case ELSA_QS1000:
 		case ELSA_PCMCIA:
+		case ELSA_PCMCIA_IPAC:
 			bytecnt = 8;
 			break;
 		case ELSA_PCFPRO:
@@ -1129,6 +1199,7 @@
 			request_region(cs->hw.elsa.cfg, 0x80, "elsa isdn pci");
 		}
 	}
+	init_arcofi(cs);
 	cs->hw.elsa.tl.function = (void *) elsa_led_handler;
 	cs->hw.elsa.tl.data = (long) cs;
 	init_timer(&cs->hw.elsa.tl);
@@ -1161,11 +1232,12 @@
 	cs->BC_Send_Data = &hscx_fill_fifo;
 	cs->cardmsg = &Elsa_card_msg;
 	reset_elsa(cs);
-	if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI)) {
+	if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI) || (cs->subtyp == ELSA_PCMCIA_IPAC)) {
 		cs->readisac = &ReadISAC_IPAC;
 		cs->writeisac = &WriteISAC_IPAC;
 		cs->readisacfifo = &ReadISACfifo_IPAC;
 		cs->writeisacfifo = &WriteISACfifo_IPAC;
+		cs->irq_func = &elsa_interrupt_ipac;
 		val = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ID);
 		printk(KERN_INFO "Elsa: IPAC version %x\n", val);
 	} else {
@@ -1173,6 +1245,7 @@
 		cs->writeisac = &WriteISAC;
 		cs->readisacfifo = &ReadISACfifo;
 		cs->writeisacfifo = &WriteISACfifo;
+		cs->irq_func = &elsa_interrupt;
 		ISACVersion(cs, "Elsa:");
 		if (HscxVersion(cs, "Elsa:")) {
 			printk(KERN_WARNING
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/elsa_ser.c linux/drivers/isdn/hisax/elsa_ser.c
--- v2.3.13/linux/drivers/isdn/hisax/elsa_ser.c	Tue Jun  1 23:25:48 1999
+++ linux/drivers/isdn/hisax/elsa_ser.c	Sun Aug 15 11:49:08 1999
@@ -298,7 +298,7 @@
 				(PACKET_NOACK != bcs->tx_skb->pkt_type))
 					bcs->st->lli.l1writewakeup(bcs->st,
 						bcs->hw.hscx.count);
-			dev_kfree_skb(bcs->tx_skb);
+			idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
 			bcs->tx_skb = NULL;
 		}
 	}
@@ -510,13 +510,13 @@
 			bcs->hw.hscx.rcvbuf = NULL;
 		}
 		while ((skb = skb_dequeue(&bcs->rqueue))) {
-			dev_kfree_skb(skb);
+			idev_kfree_skb(skb, FREE_READ);
 		}
 		while ((skb = skb_dequeue(&bcs->squeue))) {
-			dev_kfree_skb(skb);
+			idev_kfree_skb(skb, FREE_WRITE);
 		}
 		if (bcs->tx_skb) {
-			dev_kfree_skb(bcs->tx_skb);
+			idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
 			bcs->tx_skb = NULL;
 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 		}
@@ -664,7 +664,9 @@
 		st->l1.bcs->cs->hw.elsa.MFlag=2;
 	} else if (pr == (PH_DEACTIVATE | REQUEST)) {
 		test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-		send_arcofi(st->l1.bcs->cs, ARCOFI_XOP_0, st->l1.bc, 0);
+		st->l1.bcs->cs->dc.isac.arcofi_bc = st->l1.bc;
+		arcofi_fsm(st->l1.bcs->cs, ARCOFI_START, &ARCOFI_XOP_0);
+		interruptible_sleep_on(&st->l1.bcs->cs->dc.isac.arcofi_wait);
 		st->l1.bcs->cs->hw.elsa.MFlag=1;
 	} else {
 		printk(KERN_WARNING"ElsaSer: unknown pr %x\n", pr);
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/gazel.c linux/drivers/isdn/hisax/gazel.c
--- v2.3.13/linux/drivers/isdn/hisax/gazel.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/hisax/gazel.c	Sun Aug 15 11:49:08 1999
@@ -0,0 +1,752 @@
+/* $Id: gazel.c,v 2.5 1999/08/11 21:01:26 keil Exp $
+
+ * gazel.c     low level stuff for Gazel isdn cards
+ *
+ * Author       BeWan Systems
+ *              based on source code from Karsten Keil
+ *
+ * $Log: gazel.c,v $
+ * Revision 2.5  1999/08/11 21:01:26  keil
+ * new PCI codefix
+ *
+ * Revision 2.4  1999/08/10 16:01:54  calle
+ * struct pci_dev changed in 2.3.13. Made the necessary changes.
+ *
+ * Revision 2.3  1999/07/12 21:05:09  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 2.1  1999/07/08 21:26:17  keil
+ * new card
+ *
+ * Revision 1.0  1999/28/06
+ * Initial revision
+ *
+ */
+#include <linux/config.h>
+#define __NO_VERSION__
+#include "hisax.h"
+#include "isac.h"
+#include "hscx.h"
+#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.5 $";
+
+#define R647      1
+#define R685      2
+#define R753      3
+#define R742      4
+
+/* Gazel R685 stuff */
+#define GAZEL_MANUFACTURER     0x10b5
+#define GAZEL_R685             0x1030
+#define GAZEL_R753             0x1152
+#define GAZEL_DJINN_ITOO       0x1151
+
+#define PLX_CNTRL    0x50	/* registre de controle PLX */
+#define RESET_GAZEL  0x4
+#define RESET_9050   0x40000000
+#define PLX_INCSR    0x4C	/* registre d'IT du 9050 */
+#define INT_ISAC_EN  0x8	/* 1 = enable IT isac */
+#define INT_ISAC     0x20	/* 1 = IT isac en cours */
+#define INT_HSCX_EN  0x1	/* 1 = enable IT hscx */
+#define INT_HSCX     0x4	/* 1 = IT hscx en cours */
+#define INT_PCI_EN   0x40	/* 1 = enable IT PCI */
+#define INT_IPAC_EN  0x3	/* enable IT ipac */
+
+
+#define byteout(addr,val) outb(val,addr)
+#define bytein(addr) inb(addr)
+
+static inline u_char
+readreg(unsigned int adr, u_short off)
+{
+	return bytein(adr + off);
+}
+
+static inline void
+writereg(unsigned int adr, u_short off, u_char data)
+{
+	byteout(adr + off, data);
+}
+
+
+static inline void
+read_fifo(unsigned int adr, u_char * data, int size)
+{
+	insb(adr, data, size);
+}
+
+static void
+write_fifo(unsigned int adr, u_char * data, int size)
+{
+	outsb(adr, data, size);
+}
+
+static inline u_char
+readreg_ipac(unsigned int adr, u_short off)
+{
+	register u_char ret;
+	long flags;
+
+	save_flags(flags);
+	cli();
+	byteout(adr, off);
+	ret = bytein(adr + 4);
+	restore_flags(flags);
+	return ret;
+}
+
+static inline void
+writereg_ipac(unsigned int adr, u_short off, u_char data)
+{
+	long flags;
+
+	save_flags(flags);
+	cli();
+	byteout(adr, off);
+	byteout(adr + 4, data);
+	restore_flags(flags);
+}
+
+
+static inline void
+read_fifo_ipac(unsigned int adr, u_short off, u_char * data, int size)
+{
+	byteout(adr, off);
+	insb(adr + 4, data, size);
+}
+
+static void
+write_fifo_ipac(unsigned int adr, u_short off, u_char * data, int size)
+{
+	byteout(adr, off);
+	outsb(adr + 4, data, size);
+}
+
+/* Interface functions */
+
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
+{
+	u_short off2 = offset;
+
+	switch (cs->subtyp) {
+		case R647:
+			off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf));
+		case R685:
+			return (readreg(cs->hw.gazel.isac, off2));
+		case R753:
+		case R742:
+			return (readreg_ipac(cs->hw.gazel.ipac, 0x80 + off2));
+	}
+	return 0;
+}
+
+static void
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+	u_short off2 = offset;
+
+	switch (cs->subtyp) {
+		case R647:
+			off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf));
+		case R685:
+			writereg(cs->hw.gazel.isac, off2, value);
+			break;
+		case R753:
+		case R742:
+			writereg_ipac(cs->hw.gazel.ipac, 0x80 + off2, value);
+			break;
+	}
+}
+
+static void
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	switch (cs->subtyp) {
+		case R647:
+		case R685:
+			read_fifo(cs->hw.gazel.isacfifo, data, size);
+			break;
+		case R753:
+		case R742:
+			read_fifo_ipac(cs->hw.gazel.ipac, 0x80, data, size);
+			break;
+	}
+}
+
+static void
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	switch (cs->subtyp) {
+		case R647:
+		case R685:
+			write_fifo(cs->hw.gazel.isacfifo, data, size);
+			break;
+		case R753:
+		case R742:
+			write_fifo_ipac(cs->hw.gazel.ipac, 0x80, data, size);
+			break;
+	}
+}
+
+static void
+ReadHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size)
+{
+	switch (cs->subtyp) {
+		case R647:
+		case R685:
+			read_fifo(cs->hw.gazel.hscxfifo[hscx], data, size);
+			break;
+		case R753:
+		case R742:
+			read_fifo_ipac(cs->hw.gazel.ipac, hscx * 0x40, data, size);
+			break;
+	}
+}
+
+static void
+WriteHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size)
+{
+	switch (cs->subtyp) {
+		case R647:
+		case R685:
+			write_fifo(cs->hw.gazel.hscxfifo[hscx], data, size);
+			break;
+		case R753:
+		case R742:
+			write_fifo_ipac(cs->hw.gazel.ipac, hscx * 0x40, data, size);
+			break;
+	}
+}
+
+static u_char
+ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
+{
+	u_short off2 = offset;
+
+	switch (cs->subtyp) {
+		case R647:
+			off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf));
+		case R685:
+			return (readreg(cs->hw.gazel.hscx[hscx], off2));
+		case R753:
+		case R742:
+			return (readreg_ipac(cs->hw.gazel.ipac, hscx * 0x40 + off2));
+	}
+	return 0;
+}
+
+static void
+WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
+{
+	u_short off2 = offset;
+
+	switch (cs->subtyp) {
+		case R647:
+			off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf));
+		case R685:
+			writereg(cs->hw.gazel.hscx[hscx], off2, value);
+			break;
+		case R753:
+		case R742:
+			writereg_ipac(cs->hw.gazel.ipac, hscx * 0x40 + off2, value);
+			break;
+	}
+}
+
+/*
+ * fast interrupt HSCX stuff goes here
+ */
+
+#define READHSCX(cs, nr, reg) ReadHSCX(cs, nr, reg)
+#define WRITEHSCX(cs, nr, reg, data) WriteHSCX(cs, nr, reg, data)
+#define READHSCXFIFO(cs, nr, ptr, cnt) ReadHSCXfifo(cs, nr, ptr, cnt)
+#define WRITEHSCXFIFO(cs, nr, ptr, cnt) WriteHSCXfifo(cs, nr, ptr, cnt)
+
+#include "hscx_irq.c"
+
+static void
+gazel_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+{
+#define MAXCOUNT 5
+	struct IsdnCardState *cs = dev_id;
+	u_char valisac, valhscx;
+	int count = 0;
+
+	if (!cs) {
+		printk(KERN_WARNING "Gazel: Spurious interrupt!\n");
+		return;
+	}
+	do {
+		valhscx = ReadHSCX(cs, 1, HSCX_ISTA);
+		if (valhscx)
+			hscx_int_main(cs, valhscx);
+		valisac = ReadISAC(cs, ISAC_ISTA);
+		if (valisac)
+			isac_interrupt(cs, valisac);
+		count++;
+	} while ((valhscx || valisac) && (count < MAXCOUNT));
+
+	WriteHSCX(cs, 0, HSCX_MASK, 0xFF);
+	WriteHSCX(cs, 1, HSCX_MASK, 0xFF);
+	WriteISAC(cs, ISAC_MASK, 0xFF);
+	WriteISAC(cs, ISAC_MASK, 0x0);
+	WriteHSCX(cs, 0, HSCX_MASK, 0x0);
+	WriteHSCX(cs, 1, HSCX_MASK, 0x0);
+}
+
+
+static void
+gazel_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char ista, val;
+	int count = 0;
+
+	if (!cs) {
+		printk(KERN_WARNING "Gazel: Spurious interrupt!\n");
+		return;
+	}
+	ista = ReadISAC(cs, IPAC_ISTA - 0x80);
+	do {
+		if (ista & 0x0f) {
+			val = ReadHSCX(cs, 1, HSCX_ISTA);
+			if (ista & 0x01)
+				val |= 0x01;
+			if (ista & 0x04)
+				val |= 0x02;
+			if (ista & 0x08)
+				val |= 0x04;
+			if (val) {
+				hscx_int_main(cs, val);
+			}
+		}
+		if (ista & 0x20) {
+			val = 0xfe & ReadISAC(cs, ISAC_ISTA);
+			if (val) {
+				isac_interrupt(cs, val);
+			}
+		}
+		if (ista & 0x10) {
+			val = 0x01;
+			isac_interrupt(cs, val);
+		}
+		ista = ReadISAC(cs, IPAC_ISTA - 0x80);
+		count++;
+	}
+	while ((ista & 0x3f) && (count < MAXCOUNT));
+
+	WriteISAC(cs, IPAC_MASK - 0x80, 0xFF);
+	WriteISAC(cs, IPAC_MASK - 0x80, 0xC0);
+}
+void
+release_io_gazel(struct IsdnCardState *cs)
+{
+	unsigned int i;
+
+	switch (cs->subtyp) {
+		case R647:
+			for (i = 0x0000; i < 0xC000; i += 0x1000)
+				release_region(i + cs->hw.gazel.hscx[0], 16);
+			release_region(0xC000 + cs->hw.gazel.hscx[0], 1);
+			break;
+
+		case R685:
+			release_region(cs->hw.gazel.hscx[0], 0x100);
+			release_region(cs->hw.gazel.cfg_reg, 0x80);
+			break;
+
+		case R753:
+			release_region(cs->hw.gazel.ipac, 0x8);
+			release_region(cs->hw.gazel.cfg_reg, 0x80);
+			break;
+
+		case R742:
+			release_region(cs->hw.gazel.ipac, 8);
+			break;
+	}
+}
+
+static int
+reset_gazel(struct IsdnCardState *cs)
+{
+	long flags;
+	unsigned long plxcntrl, addr = cs->hw.gazel.cfg_reg;
+
+	switch (cs->subtyp) {
+		case R647:
+			save_flags(flags);
+			cli();
+			writereg(addr, 0, 0);
+			HZDELAY(10);
+			writereg(addr, 0, 1);
+			HZDELAY(2);
+			restore_flags(flags);
+			break;
+		case R685:
+			plxcntrl = inl(addr + PLX_CNTRL);
+			plxcntrl |= (RESET_9050 + RESET_GAZEL);
+			outl(plxcntrl, addr + PLX_CNTRL);
+			plxcntrl &= ~(RESET_9050 + RESET_GAZEL);
+			HZDELAY(4);
+			outl(plxcntrl, addr + PLX_CNTRL);
+			HZDELAY(10);
+			outb(INT_ISAC_EN + INT_HSCX_EN + INT_PCI_EN, addr + PLX_INCSR);
+			break;
+		case R753:
+			plxcntrl = inl(addr + PLX_CNTRL);
+			plxcntrl |= (RESET_9050 + RESET_GAZEL);
+			outl(plxcntrl, addr + PLX_CNTRL);
+			plxcntrl &= ~(RESET_9050 + RESET_GAZEL);
+			WriteISAC(cs, IPAC_POTA2 - 0x80, 0x20);
+			HZDELAY(4);
+			outl(plxcntrl, addr + PLX_CNTRL);
+			HZDELAY(10);
+			WriteISAC(cs, IPAC_POTA2 - 0x80, 0x00);
+			WriteISAC(cs, IPAC_ACFG - 0x80, 0xff);
+			WriteISAC(cs, IPAC_AOE - 0x80, 0x0);
+			WriteISAC(cs, IPAC_MASK - 0x80, 0xff);
+			WriteISAC(cs, IPAC_CONF - 0x80, 0x1);
+			outb(INT_IPAC_EN + INT_PCI_EN, addr + PLX_INCSR);
+			WriteISAC(cs, IPAC_MASK - 0x80, 0xc0);
+			break;
+		case R742:
+			WriteISAC(cs, IPAC_POTA2 - 0x80, 0x20);
+			HZDELAY(4);
+			WriteISAC(cs, IPAC_POTA2 - 0x80, 0x00);
+			WriteISAC(cs, IPAC_ACFG - 0x80, 0xff);
+			WriteISAC(cs, IPAC_AOE - 0x80, 0x0);
+			WriteISAC(cs, IPAC_MASK - 0x80, 0xff);
+			WriteISAC(cs, IPAC_CONF - 0x80, 0x1);
+			WriteISAC(cs, IPAC_MASK - 0x80, 0xc0);
+			break;
+	}
+	return (0);
+}
+
+static int
+Gazel_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+	switch (mt) {
+		case CARD_RESET:
+			reset_gazel(cs);
+			return (0);
+		case CARD_RELEASE:
+			release_io_gazel(cs);
+			return (0);
+		case CARD_INIT:
+			inithscxisac(cs, 1);
+			if ((cs->subtyp==R647)||(cs->subtyp==R685)) {
+				int i;
+				for (i=0;i<(2+MAX_WAITING_CALLS);i++) {
+					cs->bcs[i].hw.hscx.tsaxr0 = 0x1f;
+					cs->bcs[i].hw.hscx.tsaxr1 = 0x23;
+				}
+			}
+			return (0);
+		case CARD_TEST:
+			return (0);
+	}
+	return (0);
+}
+
+static int
+reserve_regions(struct IsdnCard *card, struct IsdnCardState *cs)
+{
+	unsigned int i, base = 0, adr = 0, len = 0;
+	long flags;
+
+	save_flags(flags);
+	cli();
+
+	switch (cs->subtyp) {
+		case R647:
+			base = cs->hw.gazel.hscx[0];
+			for (i = 0x0000; i < 0xC000; i += 0x1000) {
+				if (check_region(adr = (i + base), len = 16))
+					goto error;
+			}
+			if (check_region(adr = (0xC000 + base), len = 1))
+				goto error;
+
+			for (i = 0x0000; i < 0xC000; i += 0x1000)
+				request_region(i + base, 16, "gazel");
+			request_region(0xC000 + base, 1, "gazel");
+
+			break;
+
+		case R685:
+			if (check_region(adr = cs->hw.gazel.hscx[0], len = 0x100))
+				goto error;
+			if (check_region(adr = cs->hw.gazel.cfg_reg, len = 0x80))
+				goto error;
+
+			request_region(cs->hw.gazel.hscx[0], 0x100, "gazel");
+			request_region(cs->hw.gazel.cfg_reg, 0x80, "gazel");
+			break;
+
+		case R753:
+			if (check_region(adr = cs->hw.gazel.ipac, len = 0x8))
+				goto error;
+			if (check_region(adr = cs->hw.gazel.cfg_reg, len = 0x80))
+				goto error;
+
+			request_region(cs->hw.gazel.ipac, 0x8, "gazel");
+			request_region(cs->hw.gazel.cfg_reg, 0x80, "gazel");
+			break;
+
+		case R742:
+			if (check_region(adr = cs->hw.gazel.ipac, len = 0x8))
+				goto error;
+			request_region(cs->hw.gazel.ipac, 0x8, "gazel");
+			break;
+	}
+
+	restore_flags(flags);
+	return 0;
+
+      error:
+	restore_flags(flags);
+	printk(KERN_WARNING "Gazel: %s io ports 0x%x-0x%x already in use\n",
+	       CardType[cs->typ], adr, adr + len);
+	return 1;
+}
+
+static int
+setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs)
+{
+	printk(KERN_INFO "Gazel: ISA PnP card automatic recognition\n");
+	// we got an irq parameter, assume it is an ISA card
+	// R742 decodes address even in not started...
+	// R647 returns FF if not present or not started
+	// eventually needs improvment
+	if (readreg_ipac(card->para[1], IPAC_ID) == 1)
+		cs->subtyp = R742;
+	else
+		cs->subtyp = R647;
+
+	cs->hw.gazel.cfg_reg = card->para[1] + 0xC000;
+	cs->hw.gazel.ipac = card->para[1];
+	cs->hw.gazel.isac = card->para[1] + 0x8000;
+	cs->hw.gazel.hscx[0] = card->para[1];
+	cs->hw.gazel.hscx[1] = card->para[1] + 0x4000;
+	cs->irq = card->para[0];
+	cs->hw.gazel.isacfifo = cs->hw.gazel.isac;
+	cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0];
+	cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1];
+
+	switch (cs->subtyp) {
+		case R647:
+			printk(KERN_INFO "Gazel: Card ISA R647/R648 found\n");
+			cs->dc.isac.adf2 = 0x87;
+			printk(KERN_INFO
+				"Gazel: config irq:%d isac:0x%X  cfg:0x%X\n",
+				cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
+			printk(KERN_INFO
+				"Gazel: hscx A:0x%X  hscx B:0x%X\n",
+				cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
+
+			break;
+		case R742:
+			printk(KERN_INFO "Gazel: Card ISA R742 found\n");
+			test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+			printk(KERN_INFO
+			       "Gazel: config irq:%d ipac:0x%X\n",
+			       cs->irq, cs->hw.gazel.ipac);
+			break;
+	}
+
+	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)
+{
+	u_int pci_ioaddr0 = 0, pci_ioaddr1 = 0;
+	u_char pci_irq = 0, found;
+	u_int nbseek, seekcard;
+
+	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);
+			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 {
+			switch (seekcard) {
+				case GAZEL_R685:
+					seekcard = GAZEL_R753;
+					break;
+				case GAZEL_R753:
+					seekcard = GAZEL_DJINN_ITOO;
+					break;
+			}
+#ifndef COMPAT_HAS_NEW_PCI
+			pci_index = 0;
+#endif
+		}
+	}
+	if (!found) {
+		printk(KERN_WARNING "Gazel: No PCI card found\n");
+		return (1);
+	}
+	if (!pci_irq) {
+		printk(KERN_WARNING "Gazel: No IRQ for PCI card found\n");
+		return 1;
+	}
+	cs->hw.gazel.pciaddr[0] = pci_ioaddr0;
+	cs->hw.gazel.pciaddr[1] = pci_ioaddr1;
+
+	pci_ioaddr1 &= 0xfffe;
+	cs->hw.gazel.cfg_reg = pci_ioaddr0 & 0xfffe;
+	cs->hw.gazel.ipac = pci_ioaddr1;
+	cs->hw.gazel.isac = pci_ioaddr1 + 0x80;
+	cs->hw.gazel.hscx[0] = pci_ioaddr1;
+	cs->hw.gazel.hscx[1] = pci_ioaddr1 + 0x40;
+	cs->hw.gazel.isacfifo = cs->hw.gazel.isac;
+	cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0];
+	cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1];
+	cs->irq = pci_irq;
+	cs->irq_flags |= SA_SHIRQ;
+
+	switch (seekcard) {
+		case GAZEL_R685:
+			printk(KERN_INFO "Gazel: Card PCI R685 found\n");
+			cs->subtyp = R685;
+			cs->dc.isac.adf2 = 0x87;
+			printk(KERN_INFO
+			    "Gazel: config irq:%d isac:0x%X  cfg:0x%X\n",
+			cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
+			printk(KERN_INFO
+			       "Gazel: hscx A:0x%X  hscx B:0x%X\n",
+			     cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
+			break;
+		case GAZEL_R753:
+		case GAZEL_DJINN_ITOO:
+			printk(KERN_INFO "Gazel: Card PCI R753 found\n");
+			cs->subtyp = R753;
+			test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+			printk(KERN_INFO
+			    "Gazel: config irq:%d ipac:0x%X  cfg:0x%X\n",
+			cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg);
+			break;
+	}
+
+	return (0);
+}
+
+__initfunc(int
+	   setup_gazel(struct IsdnCard *card))
+{
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+	u_char val;
+
+	strcpy(tmp, gazel_revision);
+	printk(KERN_INFO "Gazel: Driver Revision %s\n", HiSax_getrev(tmp));
+
+	if (cs->typ != ISDN_CTYPE_GAZEL)
+		return (0);
+
+	if (card->para[0]) {
+		if (setup_gazelisa(card, cs))
+			return (0);
+	} else {
+
+#if CONFIG_PCI
+		if (setup_gazelpci(cs))
+			return (0);
+#else
+		printk(KERN_WARNING "Gazel: Card PCI requested and NO_PCI_BIOS, unable to config\n");
+		return (0);
+#endif				/* CONFIG_PCI */
+	}
+
+	if (reserve_regions(card, cs)) {
+		return (0);
+	}
+	if (reset_gazel(cs)) {
+		printk(KERN_WARNING "Gazel: wrong IRQ\n");
+		release_io_gazel(cs);
+		return (0);
+	}
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->BC_Read_Reg = &ReadHSCX;
+	cs->BC_Write_Reg = &WriteHSCX;
+	cs->BC_Send_Data = &hscx_fill_fifo;
+	cs->cardmsg = &Gazel_card_msg;
+
+	switch (cs->subtyp) {
+		case R647:
+		case R685:
+			cs->irq_func = &gazel_interrupt;
+			ISACVersion(cs, "Gazel:");
+			if (HscxVersion(cs, "Gazel:")) {
+				printk(KERN_WARNING
+				       "Gazel: wrong HSCX versions check IO address\n");
+				release_io_gazel(cs);
+				return (0);
+			}
+			break;
+		case R742:
+		case R753:
+			cs->irq_func = &gazel_interrupt_ipac;
+			val = ReadISAC(cs, IPAC_ID - 0x80);
+			printk(KERN_INFO "Gazel: IPAC version %x\n", val);
+			break;
+	}
+
+	return (1);
+}
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/hfc_2bds0.c linux/drivers/isdn/hisax/hfc_2bds0.c
--- v2.3.13/linux/drivers/isdn/hisax/hfc_2bds0.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/isdn/hisax/hfc_2bds0.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: hfc_2bds0.c,v 1.8 1998/11/15 23:54:40 keil Exp $
+/* $Id: hfc_2bds0.c,v 1.9 1999/07/01 08:11:35 keil Exp $
  *
  *  specific routines for CCD's HFC 2BDS0
  *
@@ -6,6 +6,9 @@
  *
  *
  * $Log: hfc_2bds0.c,v $
+ * Revision 1.9  1999/07/01 08:11:35  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 1.8  1998/11/15 23:54:40  keil
  * changes from 2.0
  *
@@ -264,6 +267,7 @@
 	} 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);
@@ -281,7 +285,7 @@
 			sti();
 			debugl1(cs, "RFIFO BUSY error");
 			printk(KERN_WARNING "HFC FIFO channel %d BUSY Error\n", bcs->channel);
-			dev_kfree_skb(skb);
+			idev_kfree_skb(skb, FREE_READ);
 			skb = NULL;
 		} else {
 			cli();
@@ -297,7 +301,7 @@
 					bcs->channel, chksum, stat);
 			if (stat) {
 				debugl1(cs, "FIFO CRC error");
-				dev_kfree_skb(skb);
+				idev_kfree_skb(skb, FREE_READ);
 				skb = NULL;
 			}
 		}
@@ -386,7 +390,7 @@
 		if (bcs->st->lli.l1writewakeup &&
 			(PACKET_NOACK != bcs->tx_skb->pkt_type))
 			bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len);
-		dev_kfree_skb(bcs->tx_skb);
+		idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
 		bcs->tx_skb = NULL;
 	}
 	WaitForBusy(cs);
@@ -588,7 +592,7 @@
 		discard_queue(&bcs->rqueue);
 		discard_queue(&bcs->squeue);
 		if (bcs->tx_skb) {
-			dev_kfree_skb(bcs->tx_skb);
+			idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
 			bcs->tx_skb = NULL;
 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 		}
@@ -642,7 +646,7 @@
 	}
 #endif
 	if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
-		switch (cs->ph_state) {
+		switch (cs->dc.hfcd.ph_state) {
 			case (0):
 				l1_msg(cs, HW_RESET | INDICATION, NULL);
 				break;
@@ -733,6 +737,7 @@
 			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();
@@ -747,7 +752,7 @@
 				sti();
 				debugl1(cs, "RFIFO D BUSY error");
 				printk(KERN_WARNING "HFC DFIFO channel BUSY Error\n");
-				dev_kfree_skb(skb);
+				idev_kfree_skb(skb, FREE_READ);
 				skb = NULL;
 			} else {
 				cli();
@@ -763,7 +768,7 @@
 						chksum, stat);
 				if (stat) {
 					debugl1(cs, "FIFO CRC error");
-					dev_kfree_skb(skb);
+					idev_kfree_skb(skb, FREE_READ);
 					skb = NULL;
 				} else {
 					skb_queue_tail(&cs->rq, skb);
@@ -860,7 +865,7 @@
 	cli();
 	WaitNoBusy(cs);
 	ReadReg(cs, HFCD_DATA, HFCD_FIFO | HFCD_F1_INC | HFCD_SEND);
-	dev_kfree_skb(cs->tx_skb);
+	idev_kfree_skb(cs->tx_skb, FREE_WRITE);
 	cs->tx_skb = NULL;
 	sti();
 	WaitForBusy(cs);
@@ -895,9 +900,9 @@
 	if (val & 0x40) { /* TE state machine irq */
 		exval = cs->readisac(cs, HFCD_STATES) & 0xf;
 		if (cs->debug & L1_DEB_ISAC)
-			debugl1(cs, "ph_state chg %d->%d", cs->ph_state,
+			debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcd.ph_state,
 				exval);
-		cs->ph_state = exval;
+		cs->dc.hfcd.ph_state = exval;
 		sched_event_D(cs, D_L1STATECHANGE);
 		val &= ~0x40;
 	}
@@ -984,7 +989,7 @@
 				del_timer(&cs->dbusytimer);
 			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
 				sched_event_D(cs, D_CLEARBUSY);
-			if (cs->tx_skb)
+			if (cs->tx_skb) {
 				if (cs->tx_skb->len) {
 					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
 						hfc_fill_dfifo(cs);
@@ -994,10 +999,11 @@
 					}
 					goto afterXPR;
 				} else {
-					dev_kfree_skb(cs->tx_skb);
+					idev_kfree_skb(cs->tx_skb, FREE_WRITE);
 					cs->tx_cnt = 0;
 					cs->tx_skb = NULL;
 				}
+			}
 			if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
 				cs->tx_cnt = 0;
 				if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
@@ -1166,8 +1172,8 @@
 #endif
 }
 
-unsigned int __init 
-*init_send_hfcd(int cnt)
+__initfunc(unsigned int
+*init_send_hfcd(int cnt))
 {
 	int i, *send;
 
@@ -1181,8 +1187,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.13/linux/drivers/isdn/hisax/hfc_2bs0.c linux/drivers/isdn/hisax/hfc_2bs0.c
--- v2.3.13/linux/drivers/isdn/hisax/hfc_2bs0.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/isdn/hisax/hfc_2bs0.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: hfc_2bs0.c,v 1.8 1998/11/15 23:54:43 keil Exp $
+/* $Id: hfc_2bs0.c,v 1.9 1999/07/01 08:11:36 keil Exp $
 
  *  specific routines for CCD's HFC 2BS0
  *
@@ -6,6 +6,9 @@
  *
  *
  * $Log: hfc_2bs0.c,v $
+ * Revision 1.9  1999/07/01 08:11:36  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 1.8  1998/11/15 23:54:43  keil
  * changes from 2.0
  *
@@ -219,6 +222,7 @@
 	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);
@@ -229,7 +233,7 @@
 		if (idx != count - 3) {
 			debugl1(cs, "RFIFO BUSY error");
 			printk(KERN_WARNING "HFC FIFO channel %d BUSY Error\n", bcs->channel);
-			dev_kfree_skb(skb);
+			idev_kfree_skb(skb, FREE_READ);
 			WaitNoBusy(cs);
 			stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC |
 					       HFC_CHANNEL(bcs->channel));
@@ -247,7 +251,7 @@
 				bcs->channel, chksum, stat);
 		if (stat) {
 			debugl1(cs, "FIFO CRC error");
-			dev_kfree_skb(skb);
+			idev_kfree_skb(skb, FREE_READ);
 			skb = NULL;
 		}
 		WaitNoBusy(cs);
@@ -321,7 +325,7 @@
 		bcs->tx_cnt -= count;
 		if (PACKET_NOACK == bcs->tx_skb->pkt_type)
 			count = -1;
-		dev_kfree_skb(bcs->tx_skb);
+		idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
 		bcs->tx_skb = NULL;
 		WaitForBusy(cs);
 		WaitNoBusy(cs);
@@ -519,7 +523,7 @@
 		discard_queue(&bcs->rqueue);
 		discard_queue(&bcs->squeue);
 		if (bcs->tx_skb) {
-			dev_kfree_skb(bcs->tx_skb);
+			idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
 			bcs->tx_skb = NULL;
 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 		}
@@ -555,8 +559,8 @@
 	return (0);
 }
 
-void __init 
-init_send(struct BCState *bcs)
+__initfunc(void
+init_send(struct BCState *bcs))
 {
 	int i;
 
@@ -569,8 +573,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.13/linux/drivers/isdn/hisax/hfc_pci.c linux/drivers/isdn/hisax/hfc_pci.c
--- v2.3.13/linux/drivers/isdn/hisax/hfc_pci.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/hisax/hfc_pci.c	Sun Aug 15 11:49:08 1999
@@ -0,0 +1,1585 @@
+/* $Id: hfc_pci.c,v 1.13 1999/08/11 21:01:28 keil Exp $
+
+ * hfc_pci.c     low level driver for CCDŽs hfc-pci based cards
+ *
+ * Author     Werner Cornelius (werner@isdn4linux.de)
+ *            based on existing driver for CCD hfc ISA cards
+ *
+ * Copyright 1999  by Werner Cornelius (werner@isdn4linux.de)
+ * Copyright 1999  by Karsten Keil (keil@isdn4linux.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Log: hfc_pci.c,v $
+ * Revision 1.13  1999/08/11 21:01:28  keil
+ * new PCI codefix
+ *
+ * Revision 1.12  1999/08/10 16:01:58  calle
+ * struct pci_dev changed in 2.3.13. Made the necessary changes.
+ *
+ * Revision 1.11  1999/08/09 19:13:32  werner
+ * moved constant pci ids to pci id table
+ *
+ * Revision 1.10  1999/08/08 10:17:34  werner
+ * added new PCI vendor and card ids for Manufacturer 0x1043
+ *
+ * Revision 1.9  1999/08/07 21:09:10  werner
+ * Fixed another memcpy problem in fifo handling.
+ * Thanks for debugging aid by Olaf Kordwittenborg.
+ *
+ * Revision 1.8  1999/07/23 14:25:15  werner
+ * Some smaller bug fixes and prepared support for GCI/IOM bus
+ *
+ * Revision 1.7  1999/07/14 21:24:20  werner
+ * fixed memcpy problem when using E-channel feature
+ *
+ * Revision 1.6  1999/07/13 21:08:08  werner
+ * added echo channel logging feature.
+ *
+ * Revision 1.5  1999/07/12 21:05:10  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 1.4  1999/07/04 21:51:39  werner
+ * Changes to solve problems with irq sharing and smp machines
+ * Thanks to Karsten Keil and Alex Holden for giving aid with
+ * testing and debugging
+ *
+ * Revision 1.3  1999/07/01 09:43:19  keil
+ * removed additional schedules in timeouts
+ *
+ * Revision 1.2  1999/07/01 08:07:51  keil
+ * Initial version
+ *
+ *
+ *
+ */
+
+#include <linux/config.h>
+#define __NO_VERSION__
+#include "hisax.h"
+#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.13 $";
+
+static const int CCD_VENDOR_IDS[] = { 
+	0x1043,   /* Asuscom  */
+	0x1051,   /* Motorola MC145575 */
+        0x1397,   /* CCD and Billion */
+	0,
+};
+
+static const int CCD_DEVICE_IDS[] = { 
+	0x675,    /* Asuscom  */
+	0x100,    /* Motorola MC145575 */
+        0x2BD0,   /* CCD and Billion */
+	0,
+};
+
+
+#if CONFIG_PCI
+/*****************************/
+/* release D- and B-channels */
+/*****************************/
+void
+releasehfcpci(struct IsdnCardState *cs)
+{
+	if (cs->bcs[0].hw.hfc.send) {
+		kfree(cs->bcs[0].hw.hfc.send);
+		cs->bcs[0].hw.hfc.send = NULL;
+	}
+	if (cs->bcs[1].hw.hfc.send) {
+		kfree(cs->bcs[1].hw.hfc.send);
+		cs->bcs[1].hw.hfc.send = NULL;
+	}
+}
+
+/******************************************/
+/* free hardware resources used by driver */
+/******************************************/
+void
+release_io_hfcpci(struct IsdnCardState *cs)
+{
+#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 */
+	releasehfcpci(cs);
+	del_timer(&cs->hw.hfcpci.timer);
+	kfree(cs->hw.hfcpci.share_start);
+	cs->hw.hfcpci.share_start = NULL;
+	vfree(cs->hw.hfcpci.pci_io);
+}
+
+/********************************************************************************/
+/* function called to reset the HFC PCI chip. A complete software reset of chip */
+/* and fifos is done.                                                           */
+/********************************************************************************/
+static void
+reset_hfcpci(struct IsdnCardState *cs)
+{
+	long flags;
+
+	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 */
+	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;
+	schedule_timeout((30 * HZ) / 1000);	/* Timeout 30ms */
+	Write_hfc(cs, HFCPCI_CIRM, 0);	/* Reset Off */
+	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");
+
+	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; /* no echo connect */
+	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.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;
+	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);
+	Write_hfc(cs, HFCPCI_STATES, 2);	/* HFC ST 2 */
+	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 = 0;
+	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 */
+	/* Slots 0 and 1 are set for B-chan 1 and 2 */
+	/* D- and monitor/CI channel are not enabled */
+	/* STIO1 is used as output for data, B1+B2 from ST->IOM+HFC */
+	/* STIO2 is used as data input, B1+B2 from IOM->ST */ 
+	/* ST B-channel send disabled -> continous 1s */
+	/* The IOM slots are always enabled */
+	cs->hw.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 */
+	restore_flags(flags);
+}
+
+/***************************************************/
+/* Timer function called when kernel timer expires */
+/***************************************************/
+static void
+hfcpci_Timer(struct IsdnCardState *cs)
+{
+	cs->hw.hfcpci.timer.expires = jiffies + 75;
+	/* WD RESET */
+/*      WriteReg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcpci.ctmt | 0x80);
+   add_timer(&cs->hw.hfcpci.timer);
+ */
+}
+
+
+/*********************************/
+/* schedule a new D-channel task */
+/*********************************/
+static void
+sched_event_D_pci(struct IsdnCardState *cs, int event)
+{
+	test_and_set_bit(event, &cs->event);
+	queue_task(&cs->tqueue, &tq_immediate);
+	mark_bh(IMMEDIATE_BH);
+}
+
+/*********************************/
+/* schedule a new b_channel task */
+/*********************************/
+static void
+hfcpci_sched_event(struct BCState *bcs, int event)
+{
+	bcs->event |= 1 << event;
+	queue_task(&bcs->tqueue, &tq_immediate);
+	mark_bh(IMMEDIATE_BH);
+}
+
+/************************************************/
+/* select a b-channel entry matching and active */
+/************************************************/
+static
+struct BCState *
+Sel_BCS(struct IsdnCardState *cs, int channel)
+{
+	if (cs->bcs[0].mode && (cs->bcs[0].channel == channel))
+		return (&cs->bcs[0]);
+	else if (cs->bcs[1].mode && (cs->bcs[1].channel == channel))
+		return (&cs->bcs[1]);
+	else
+		return (NULL);
+}
+
+/*********************************************/
+/* read a complete B-frame out of the buffer */
+/*********************************************/
+static struct sk_buff
+*
+hfcpci_empty_fifo(struct BCState *bcs, bzfifo_type * bz, u_char * bdata, int count)
+{
+	u_char *ptr, *ptr1, new_f2;
+	struct sk_buff *skb;
+	struct IsdnCardState *cs = bcs->cs;
+	int flags, total, maxlen, new_z2;
+	z_type *zp;
+
+	save_flags(flags);
+	sti();
+	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+		debugl1(cs, "hfcpci_empty_fifo");
+	zp = &bz->za[bz->f2];	/* point to Z-Regs */
+	new_z2 = zp->z2 + count;	/* new position in fifo */
+	if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
+		new_z2 -= B_FIFO_SIZE;	/* buffer wrap */
+	new_f2 = (bz->f2 + 1) & MAX_B_FRAMES;
+	if ((count > HSCX_BUFMAX + 3) || (count < 4) ||
+	    (*(bdata + (zp->z1 - B_SUB_VAL)))) {
+		if (cs->debug & L1_DEB_WARN)
+			debugl1(cs, "hfcpci_empty_fifo: incoming packet invalid length %d or crc", count);
+		bz->za[new_f2].z2 = new_z2;
+		bz->f2 = new_f2;	/* next buffer */
+		skb = NULL;
+	} 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)
+			maxlen = count;		/* complete transfer */
+		else
+			maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2;	/* maximum */
+
+		ptr1 = bdata + (zp->z2 - B_SUB_VAL);	/* start of data */
+		memcpy(ptr, ptr1, maxlen);	/* copy data */
+		count -= maxlen;
+
+		if (count) {	/* rest remaining */
+			ptr += maxlen;
+			ptr1 = bdata;	/* start of buffer */
+			memcpy(ptr, ptr1, count);	/* rest */
+		}
+		bz->za[new_f2].z2 = new_z2;
+		bz->f2 = new_f2;	/* next buffer */
+
+	}
+	restore_flags(flags);
+	return (skb);
+}
+
+/*******************************/
+/* D-channel receive procedure */
+/*******************************/
+static
+int
+receive_dmsg(struct IsdnCardState *cs)
+{
+	struct sk_buff *skb;
+	int maxlen;
+	int rcnt, total;
+	int count = 5;
+	u_char *ptr, *ptr1;
+	dfifo_type *df;
+	z_type *zp;
+
+	df = &((fifo_area *) (cs->hw.hfcpci.fifos))->d_chan.d_rx;
+	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+		debugl1(cs, "rec_dmsg blocked");
+		return (1);
+	}
+	while (((df->f1 & D_FREG_MASK) != (df->f2 & D_FREG_MASK)) && count--) {
+		zp = &df->za[df->f2 & D_FREG_MASK];
+		rcnt = zp->z1 - zp->z2;
+		if (rcnt < 0)
+			rcnt += D_FIFO_SIZE;
+		rcnt++;
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "hfcpci recd f1(%d) f2(%d) z1(%x) z2(%x) cnt(%d)",
+				df->f1, df->f2, zp->z1, zp->z2, rcnt);
+
+		if ((rcnt > MAX_DFRAME_LEN + 3) || (rcnt < 4) ||
+		    (df->data[zp->z1])) {
+			if (cs->debug & L1_DEB_WARN)
+				debugl1(cs, "empty_fifo hfcpci paket inv. len %d or crc %d", rcnt, df->data[zp->z1]);
+			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);
+
+			if (zp->z2 + rcnt <= D_FIFO_SIZE)
+				maxlen = rcnt;	/* complete transfer */
+			else
+				maxlen = D_FIFO_SIZE - zp->z2;	/* maximum */
+
+			ptr1 = df->data + zp->z2;	/* start of data */
+			memcpy(ptr, ptr1, maxlen);	/* copy data */
+			rcnt -= maxlen;
+
+			if (rcnt) {	/* rest remaining */
+				ptr += maxlen;
+				ptr1 = df->data;	/* start of buffer */
+				memcpy(ptr, ptr1, rcnt);	/* rest */
+			}
+			df->f2 = ((df->f2 + 1) & MAX_D_FRAMES) | (MAX_D_FRAMES + 1);	/* next buffer */
+			df->za[df->f2 & D_FREG_MASK].z2 = (zp->z2 + total) & (D_FIFO_SIZE - 1);
+
+			skb_queue_tail(&cs->rq, skb);
+			sched_event_D_pci(cs, D_RCVBUFREADY);
+		} else
+			printk(KERN_WARNING "HFC-PCI: D receive out of memory\n");
+	}
+	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+	return (1);
+}
+
+/**********************************/
+/* B-channel main receive routine */
+/**********************************/
+void
+main_rec_hfcpci(struct BCState *bcs)
+{
+	long flags;
+	struct IsdnCardState *cs = bcs->cs;
+	int rcnt;
+	int receive, count = 5;
+	struct sk_buff *skb;
+	bzfifo_type *bz;
+	u_char *bdata;
+	z_type *zp;
+
+
+	save_flags(flags);
+	if ((bcs->channel) && (!cs->hw.hfcpci.bswapped)) {
+		bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2;
+		bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxdat_b2;
+	} else {
+		bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b1;
+		bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxdat_b1;
+	}
+      Begin:
+	count--;
+	cli();
+	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+		debugl1(cs, "rec_data %d blocked", bcs->channel);
+		restore_flags(flags);
+		return;
+	}
+	sti();
+	if (bz->f1 != bz->f2) {
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "hfcpci rec %d f1(%d) f2(%d)",
+				bcs->channel, bz->f1, bz->f2);
+		zp = &bz->za[bz->f2];
+
+		rcnt = zp->z1 - zp->z2;
+		if (rcnt < 0)
+			rcnt += B_FIFO_SIZE;
+		rcnt++;
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "hfcpci rec %d z1(%x) z2(%x) cnt(%d)",
+				bcs->channel, zp->z1, zp->z2, rcnt);
+		if ((skb = hfcpci_empty_fifo(bcs, bz, bdata, rcnt))) {
+			cli();
+			skb_queue_tail(&bcs->rqueue, skb);
+			sti();
+			hfcpci_sched_event(bcs, B_RCVBUFREADY);
+		}
+		rcnt = bz->f1 - bz->f2;
+		if (rcnt < 0)
+			rcnt += MAX_B_FRAMES + 1;
+		if (rcnt > 1)
+			receive = 1;
+		else
+			receive = 0;
+	} else
+		receive = 0;
+	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+	if (count && receive)
+		goto Begin;
+	restore_flags(flags);
+	return;
+}
+
+/**************************/
+/* D-channel send routine */
+/**************************/
+static void
+hfcpci_fill_dfifo(struct IsdnCardState *cs)
+{
+	long flags;
+	int fcnt;
+	int count, new_z1, maxlen;
+	dfifo_type *df;
+	u_char *src, *dst, new_f1;
+
+	if (!cs->tx_skb)
+		return;
+	if (cs->tx_skb->len <= 0)
+		return;
+
+	df = &((fifo_area *) (cs->hw.hfcpci.fifos))->d_chan.d_tx;
+
+	if (cs->debug & L1_DEB_ISAC)
+		debugl1(cs, "hfcpci_fill_Dfifo f1(%d) f2(%d) z1(f1)(%x)",
+			df->f1, df->f2,
+			df->za[df->f1 & D_FREG_MASK].z1);
+	fcnt = df->f1 - df->f2;	/* frame count actually buffered */
+	if (fcnt < 0)
+		fcnt += (MAX_D_FRAMES + 1);	/* if wrap around */
+	if (fcnt > (MAX_D_FRAMES - 1)) {
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "hfcpci_fill_Dfifo more as 14 frames");
+		return;
+	}
+	/* now determine free bytes in FIFO buffer */
+	count = df->za[df->f1 & D_FREG_MASK].z2 - df->za[df->f1 & D_FREG_MASK].z1;
+	if (count <= 0)
+		count += D_FIFO_SIZE;	/* count now contains available bytes */
+
+	if (cs->debug & L1_DEB_ISAC)
+		debugl1(cs, "hfcpci_fill_Dfifo count(%ld/%d)",
+			cs->tx_skb->len, count);
+	if (count < cs->tx_skb->len) {
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "hfcpci_fill_Dfifo no fifo mem");
+		return;
+	}
+	count = cs->tx_skb->len;	/* get frame len */
+	new_z1 = (df->za[df->f1 & D_FREG_MASK].z1 + count) & (D_FIFO_SIZE - 1);
+	new_f1 = ((df->f1 + 1) & D_FREG_MASK) | (D_FREG_MASK + 1);
+	src = cs->tx_skb->data;	/* source pointer */
+	dst = df->data + df->za[df->f1 & D_FREG_MASK].z1;
+	maxlen = D_FIFO_SIZE - df->za[df->f1 & D_FREG_MASK].z1;		/* end fifo */
+	if (maxlen > count)
+		maxlen = count;	/* limit size */
+	memcpy(dst, src, maxlen);	/* first copy */
+
+	count -= maxlen;	/* remaining bytes */
+	if (count) {
+		dst = df->data;	/* start of buffer */
+		src += maxlen;	/* new position */
+		memcpy(dst, src, count);
+	}
+	save_flags(flags);
+	cli();
+	df->za[new_f1 & D_FREG_MASK].z1 = new_z1;	/* for next buffer */
+	df->za[df->f1 & D_FREG_MASK].z1 = new_z1;	/* new pos actual buffer */
+	df->f1 = new_f1;	/* next frame */
+	restore_flags(flags);
+
+	idev_kfree_skb(cs->tx_skb, FREE_WRITE);
+	cs->tx_skb = NULL;
+	return;
+}
+
+/**************************/
+/* B-channel send routine */
+/**************************/
+static void
+hfcpci_fill_fifo(struct BCState *bcs)
+{
+	struct IsdnCardState *cs = bcs->cs;
+	int flags, maxlen, fcnt;
+	int count, new_z1;
+	bzfifo_type *bz;
+	u_char *bdata;
+	u_char new_f1, *src, *dst;
+
+	if (!bcs->tx_skb)
+		return;
+	if (bcs->tx_skb->len <= 0)
+		return;
+
+	save_flags(flags);
+	sti();
+
+	if ((bcs->channel) && (!cs->hw.hfcpci.bswapped)) {
+		bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b2;
+		bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txdat_b2;
+	} else {
+		bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b1;
+		bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txdat_b1;
+	}
+
+	if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "hfcpci_fill_fifo %d f1(%d) f2(%d) z1(f1)(%x)",
+			bcs->channel, bz->f1, bz->f2,
+			bz->za[bz->f1].z1);
+
+	fcnt = bz->f1 - bz->f2;	/* frame count actually buffered */
+	if (fcnt < 0)
+		fcnt += (MAX_B_FRAMES + 1);	/* if wrap around */
+	if (fcnt > (MAX_B_FRAMES - 1)) {
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "hfcpci_fill_Bfifo more as 14 frames");
+		restore_flags(flags);
+		return;
+	}
+	/* now determine free bytes in FIFO buffer */
+	count = bz->za[bz->f1].z2 - bz->za[bz->f1].z1;
+	if (count <= 0)
+		count += B_FIFO_SIZE;	/* count now contains available bytes */
+
+	if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "hfcpci_fill_fifo %d count(%ld/%d),%lx",
+			bcs->channel, bcs->tx_skb->len,
+			count, current->state);
+
+	if (count < bcs->tx_skb->len) {
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "hfcpci_fill_fifo no fifo mem");
+		restore_flags(flags);
+		return;
+	}
+	count = bcs->tx_skb->len;	/* get frame len */
+	new_z1 = bz->za[bz->f1].z1 + count;	/* new buffer Position */
+	if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL))
+		new_z1 -= B_FIFO_SIZE;	/* buffer wrap */
+
+	new_f1 = ((bz->f1 + 1) & MAX_B_FRAMES);
+	src = bcs->tx_skb->data;	/* source pointer */
+	dst = bdata + (bz->za[bz->f1].z1 - B_SUB_VAL);
+	maxlen = (B_FIFO_SIZE + B_SUB_VAL) - bz->za[bz->f1].z1;		/* end 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;
+	if (bcs->st->lli.l1writewakeup &&
+	    (PACKET_NOACK != bcs->tx_skb->pkt_type))
+		bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len);
+
+	cli();
+	bz->za[new_f1].z1 = new_z1;	/* for next buffer */
+	bz->f1 = new_f1;	/* next frame */
+	restore_flags(flags);
+
+	idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+	bcs->tx_skb = NULL;
+	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+	return;
+}
+
+/***********************/
+/* set/reset echo mode */
+/***********************/ 
+int hfcpci_set_echo(struct IsdnCardState *cs, int i)
+{ int flags;
+
+  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_set_echo */ 
+
+/*****************************/
+/* E-channel receive routine */
+/*****************************/
+static void receive_emsg(struct IsdnCardState *cs)
+{
+	long flags;
+	int rcnt;
+	int receive, count = 5;
+	bzfifo_type *bz;
+	u_char *bdata;
+	z_type *zp;
+	u_char *ptr, *ptr1, new_f2;
+	int total, maxlen, new_z2;
+	u_char e_buffer[256];
+
+	save_flags(flags);
+	bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2;
+	bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxdat_b2;
+      Begin:
+	count--;
+	cli();
+	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+		debugl1(cs, "echo_rec_data blocked");
+		restore_flags(flags);
+		return;
+	}
+	sti();
+	if (bz->f1 != bz->f2) {
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "hfcpci e_rec f1(%d) f2(%d)",
+				bz->f1, bz->f2);
+		zp = &bz->za[bz->f2];
+
+		rcnt = zp->z1 - zp->z2;
+		if (rcnt < 0)
+			rcnt += B_FIFO_SIZE;
+		rcnt++;
+		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 */
+		if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
+		  new_z2 -= B_FIFO_SIZE; /* buffer wrap */
+		new_f2 = (bz->f2 + 1) & MAX_B_FRAMES;
+	        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 */
+		} 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 */
+
+		    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)
+			rcnt += MAX_B_FRAMES + 1;
+		if (rcnt > 1)
+			receive = 1;
+		else
+			receive = 0;
+	} else
+		receive = 0;
+	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+	if (count && receive)
+		goto Begin;
+	restore_flags(flags);
+	return;
+} /* receive_emsg */
+
+/*********************/
+/* Interrupt handler */
+/*********************/
+static void
+hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char exval;
+	struct BCState *bcs;
+	int count = 15;
+	long flags;
+	u_char val, stat;
+
+	if (!cs) {
+		printk(KERN_WARNING "HFC-PCI: Spurious interrupt!\n");
+		return;
+	}
+	if (HFCPCI_ANYINT & (stat = Read_hfc(cs, HFCPCI_STATUS))) {
+		val = Read_hfc(cs, HFCPCI_INT_S1);
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "HFC-PCI: stat(%02x) s1(%02x)", stat, val);
+	} else
+		return;
+
+	if (cs->debug & L1_DEB_ISAC)
+		debugl1(cs, "HFC-PCI irq %x %s", val,
+			test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ?
+			"locked" : "unlocked");
+	val &= cs->hw.hfcpci.int_m1;
+	if (val & 0x40) {	/* TE 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,
+				exval);
+		cs->dc.hfcpci.ph_state = exval;
+		sched_event_D_pci(cs, D_L1STATECHANGE);
+		val &= ~0x40;
+	}
+	while (val) {
+		save_flags(flags);
+		cli();
+		if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+			cs->hw.hfcpci.int_s1 |= val;
+			restore_flags(flags);
+			return;
+		}
+		if (cs->hw.hfcpci.int_s1 & 0x18) {
+			exval = val;
+			val = cs->hw.hfcpci.int_s1;
+			cs->hw.hfcpci.int_s1 = exval;
+		}
+		if (val & 0x08) {
+			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 (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 (cs->debug)
+					debugl1(cs, "hfcpci spurious 0x01 IRQ");
+			} else {
+				if (bcs->tx_skb) {
+					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+						hfcpci_fill_fifo(bcs);
+						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+					} else
+						debugl1(cs, "fill_data %d blocked", bcs->channel);
+				} else {
+					if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+						if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+							hfcpci_fill_fifo(bcs);
+							test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+						} else
+							debugl1(cs, "fill_data %d blocked", bcs->channel);
+					} else {
+						hfcpci_sched_event(bcs, B_XMTBUFREADY);
+					}
+				}
+			}
+		}
+		if (val & 0x02) {
+			if (!(bcs = Sel_BCS(cs, 1))) {
+				if (cs->debug)
+					debugl1(cs, "hfcpci spurious 0x02 IRQ");
+			} else {
+				if (bcs->tx_skb) {
+					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+						hfcpci_fill_fifo(bcs);
+						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+					} else
+						debugl1(cs, "fill_data %d blocked", bcs->channel);
+				} else {
+					if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+						if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+							hfcpci_fill_fifo(bcs);
+							test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+						} else
+							debugl1(cs, "fill_data %d blocked", bcs->channel);
+					} else {
+						hfcpci_sched_event(bcs, B_XMTBUFREADY);
+					}
+				}
+			}
+		}
+		if (val & 0x20) {	/* receive dframe */
+			receive_dmsg(cs);
+		}
+		if (val & 0x04) {	/* dframe transmitted */
+			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
+				del_timer(&cs->dbusytimer);
+			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
+				sched_event_D_pci(cs, D_CLEARBUSY);
+			if (cs->tx_skb) {
+				if (cs->tx_skb->len) {
+					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+						hfcpci_fill_dfifo(cs);
+						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+					} else {
+						debugl1(cs, "hfcpci_fill_dfifo irq blocked");
+					}
+					goto afterXPR;
+				} else {
+					idev_kfree_skb(cs->tx_skb, FREE_WRITE);
+					cs->tx_cnt = 0;
+					cs->tx_skb = NULL;
+				}
+			}
+			if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
+				cs->tx_cnt = 0;
+				if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+					hfcpci_fill_dfifo(cs);
+					test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+				} else {
+					debugl1(cs, "hfcpci_fill_dfifo irq blocked");
+				}
+			} else
+				sched_event_D_pci(cs, D_XMTBUFREADY);
+		}
+	      afterXPR:
+		if (cs->hw.hfcpci.int_s1 && count--) {
+			val = cs->hw.hfcpci.int_s1;
+			cs->hw.hfcpci.int_s1 = 0;
+			if (cs->debug & L1_DEB_ISAC)
+				debugl1(cs, "HFC-PCI irq %x loop %d", val, 15 - count);
+		} else
+			val = 0;
+		restore_flags(flags);
+	}
+}
+
+/********************************************************************/
+/* timer callback for D-chan busy resolution. Currently no function */
+/********************************************************************/
+static void
+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
+}
+
+/*************************************/
+/* Layer 1 D-channel hardware access */
+/*************************************/
+static void
+HFCPCI_l1hw(struct PStack *st, int pr, void *arg)
+{
+	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
+	struct sk_buff *skb = arg;
+
+	switch (pr) {
+		case (PH_DATA | REQUEST):
+			if (cs->debug & DEB_DLOG_HEX)
+				LogFrame(cs, skb->data, skb->len);
+			if (cs->debug & DEB_DLOG_VERBOSE)
+				dlogframe(cs, skb, 0);
+			if (cs->tx_skb) {
+				skb_queue_tail(&cs->sq, skb);
+#ifdef L2FRAME_DEBUG		/* psa */
+				if (cs->debug & L1_DEB_LAPD)
+					Logl2Frame(cs, skb, "PH_DATA Queued", 0);
+#endif
+			} else {
+				cs->tx_skb = skb;
+				cs->tx_cnt = 0;
+#ifdef L2FRAME_DEBUG		/* psa */
+				if (cs->debug & L1_DEB_LAPD)
+					Logl2Frame(cs, skb, "PH_DATA", 0);
+#endif
+				if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+					hfcpci_fill_dfifo(cs);
+					test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+				} else
+					debugl1(cs, "hfcpci_fill_dfifo blocked");
+
+			}
+			break;
+		case (PH_PULL | INDICATION):
+			if (cs->tx_skb) {
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
+				skb_queue_tail(&cs->sq, skb);
+				break;
+			}
+			if (cs->debug & DEB_DLOG_HEX)
+				LogFrame(cs, skb->data, skb->len);
+			if (cs->debug & DEB_DLOG_VERBOSE)
+				dlogframe(cs, skb, 0);
+			cs->tx_skb = skb;
+			cs->tx_cnt = 0;
+#ifdef L2FRAME_DEBUG		/* psa */
+			if (cs->debug & L1_DEB_LAPD)
+				Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
+#endif
+			if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+				hfcpci_fill_dfifo(cs);
+				test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+			} else
+				debugl1(cs, "hfcpci_fill_dfifo blocked");
+			break;
+		case (PH_PULL | REQUEST):
+#ifdef L2FRAME_DEBUG		/* psa */
+			if (cs->debug & L1_DEB_LAPD)
+				debugl1(cs, "-> PH_REQUEST_PULL");
+#endif
+			if (!cs->tx_skb) {
+				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+			} else
+				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+			break;
+		case (HW_RESET | REQUEST):
+			Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 3);	/* HFC ST 3 */
+			udelay(6);
+			Write_hfc(cs, HFCPCI_STATES, 3);	/* HFC ST 2 */
+			cs->hw.hfcpci.mst_m |= HFCPCI_MASTER;
+			Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
+			Write_hfc(cs, HFCPCI_STATES, HFCPCI_ACTIVATE | HFCPCI_DO_ACTION);
+			l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
+			break;
+		case (HW_ENABLE | REQUEST):
+			Write_hfc(cs, HFCPCI_STATES, HFCPCI_ACTIVATE | HFCPCI_DO_ACTION);
+			break;
+		case (HW_DEACTIVATE | REQUEST):
+      			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);
+			}
+			break;
+#endif
+		default:
+			if (cs->debug & L1_DEB_WARN)
+				debugl1(cs, "hfcpci_l1hw unknown pr %4x", pr);
+			break;
+	}
+}
+
+/***********************************************/
+/* called during init setting l1 stack pointer */
+/***********************************************/
+void
+setstack_hfcpci(struct PStack *st, struct IsdnCardState *cs)
+{
+	st->l1.l1hw = HFCPCI_l1hw;
+}
+
+/**************************************/
+/* send B-channel data if not blocked */
+/**************************************/
+static void
+hfcpci_send_data(struct BCState *bcs)
+{
+	struct IsdnCardState *cs = bcs->cs;
+
+	if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+		hfcpci_fill_fifo(bcs);
+		test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+	} else
+		debugl1(cs, "send_data %d blocked", bcs->channel);
+}
+
+/***************************************************************/
+/* activate/deactivate hardware for selected channels and mode */
+/***************************************************************/
+void
+mode_hfcpci(struct BCState *bcs, int mode, int bc)
+{
+	struct IsdnCardState *cs = bcs->cs;
+	int flags;
+
+	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; 
+	  }  
+	}  
+	save_flags(flags);
+	cli();
+	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;
+				cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B1;
+				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);
+			} 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;
+				cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B1;
+				cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B1TRANS+HFCPCI_INTS_B1REC);
+			}
+			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;
+				cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B1;
+				cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B1TRANS+HFCPCI_INTS_B1REC);
+			}
+			break;
+		case (L1_MODE_EXTRN):
+			if (bc) {
+			        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);
+			} else {
+			        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);
+			}
+			break;
+	}
+	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);
+}
+
+/******************************/
+/* Layer2 -> Layer 1 Transfer */
+/******************************/
+static void
+hfcpci_l2l1(struct PStack *st, int pr, void *arg)
+{
+	struct sk_buff *skb = arg;
+	long flags;
+
+	switch (pr) {
+		case (PH_DATA | REQUEST):
+			save_flags(flags);
+			cli();
+			if (st->l1.bcs->tx_skb) {
+				skb_queue_tail(&st->l1.bcs->squeue, skb);
+				restore_flags(flags);
+			} else {
+				st->l1.bcs->tx_skb = skb;
+/*                              test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+ */ st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
+				restore_flags(flags);
+			}
+			break;
+		case (PH_PULL | INDICATION):
+			if (st->l1.bcs->tx_skb) {
+				printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n");
+				break;
+			}
+			save_flags(flags);
+			cli();
+/*                      test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+ */ st->l1.bcs->tx_skb = skb;
+			st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
+			restore_flags(flags);
+			break;
+		case (PH_PULL | REQUEST):
+			if (!st->l1.bcs->tx_skb) {
+				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+			} else
+				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+			break;
+		case (PH_ACTIVATE | REQUEST):
+			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+			mode_hfcpci(st->l1.bcs, st->l1.mode, st->l1.bc);
+			l1_msg_b(st, pr, arg);
+			break;
+		case (PH_DEACTIVATE | REQUEST):
+			l1_msg_b(st, pr, arg);
+			break;
+		case (PH_DEACTIVATE | CONFIRM):
+			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+			test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+			mode_hfcpci(st->l1.bcs, 0, st->l1.bc);
+			st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
+			break;
+	}
+}
+
+/******************************************/
+/* deactivate B-channel access and queues */
+/******************************************/
+static void
+close_hfcpci(struct BCState *bcs)
+{
+	mode_hfcpci(bcs, 0, bcs->channel);
+	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
+		discard_queue(&bcs->rqueue);
+		discard_queue(&bcs->squeue);
+		if (bcs->tx_skb) {
+			idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+			bcs->tx_skb = NULL;
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+		}
+	}
+}
+
+/*************************************/
+/* init B-channel queues and control */
+/*************************************/
+static int
+open_hfcpcistate(struct IsdnCardState *cs, struct BCState *bcs)
+{
+	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
+		skb_queue_head_init(&bcs->rqueue);
+		skb_queue_head_init(&bcs->squeue);
+	}
+	bcs->tx_skb = NULL;
+	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+	bcs->event = 0;
+	bcs->tx_cnt = 0;
+	return (0);
+}
+
+/*********************************/
+/* inits the stack for B-channel */
+/*********************************/
+static int
+setstack_2b(struct PStack *st, struct BCState *bcs)
+{
+	bcs->channel = st->l1.bc;
+	if (open_hfcpcistate(st->l1.hardware, bcs))
+		return (-1);
+	st->l1.bcs = bcs;
+	st->l2.l2l1 = hfcpci_l2l1;
+	setstack_manager(st);
+	bcs->st = st;
+	setstack_l1_B(st);
+	return (0);
+}
+
+/***************************/
+/* handle L1 state changes */
+/***************************/
+static void
+hfcpci_bh(struct IsdnCardState *cs)
+{
+/*      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 (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);
+}
+
+
+/*************************************/
+/* Alloc memory send data for queues */
+/*************************************/
+__initfunc(unsigned int
+	   *init_send_hfcpci(int cnt))
+{
+	int i, *send;
+
+	if (!(send = kmalloc(cnt * sizeof(unsigned int), GFP_ATOMIC))) {
+		printk(KERN_WARNING
+		       "HiSax: No memory for hfcpci.send\n");
+		return (NULL);
+	}
+	for (i = 0; i < cnt; i++)
+		send[i] = 0x1fff;
+	return (send);
+}
+
+/********************************/
+/* called for card init message */
+/********************************/
+__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)
+		cs->bcs[1].hw.hfc.send = init_send_hfcpci(32);
+	cs->BC_Send_Data = &hfcpci_send_data;
+	cs->bcs[0].BC_SetStack = setstack_2b;
+	cs->bcs[1].BC_SetStack = setstack_2b;
+	cs->bcs[0].BC_Close = close_hfcpci;
+	cs->bcs[1].BC_Close = close_hfcpci;
+	mode_hfcpci(cs->bcs, 0, 0);
+	mode_hfcpci(cs->bcs + 1, 0, 1);
+}
+
+
+
+/*******************************************/
+/* handle card messages from control layer */
+/*******************************************/
+static int
+hfcpci_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+	long flags;
+
+	if (cs->debug & L1_DEB_ISAC)
+		debugl1(cs, "HFCPCI: card_msg %x", mt);
+	switch (mt) {
+		case CARD_RESET:
+			reset_hfcpci(cs);
+			return (0);
+		case CARD_RELEASE:
+			release_io_hfcpci(cs);
+			return (0);
+		case CARD_INIT:
+			inithfcpci(cs);
+			save_flags(flags);
+			sti();
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout((80 * HZ) / 1000);	/* Timeout 80ms */
+			/* now switch timer interrupt off */
+			cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER;
+			Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
+			/* reinit mode reg */
+			Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
+			restore_flags(flags);
+			return (0);
+		case CARD_TEST:
+			return (0);
+	}
+	return (0);
+}
+
+
+/* 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 */
+
+__initfunc(int
+	   setup_hfcpci(struct IsdnCard *card))
+{
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+	int i;
+#ifdef COMPAT_HAS_NEW_PCI
+        struct pci_dev *tmp_hfcpci = NULL;
+#endif
+
+	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 (CCD_VENDOR_IDS[i]) {
+		  tmp_hfcpci = pci_find_device(CCD_VENDOR_IDS[i],
+					       CCD_DEVICE_IDS[i],
+					       dev_hfcpci);
+		  if (tmp_hfcpci) break;
+		  i++;
+		}  
+					      
+		if (tmp_hfcpci) {
+		        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;
+			if (!cs->irq) {
+				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);
+		} 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 (CCD_VENDOR_IDS[i]) {
+			  if (pcibios_find_device(CCD_VENDOR_IDS[i],
+						  CCD_DEVICE_IDS[i], pci_index,
+						  &cs->hw.hfcpci.pci_bus, &cs->hw.hfcpci.pci_device_fn) == 0) 
+			    break;
+			  i++;
+			}
+			if (!CCD_VENDOR_IDS[i]) 
+			  continue;
+
+			pcibios_read_config_byte(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn,
+					       PCI_INTERRUPT_LINE, &irq);
+			cs->irq = irq;
+
+			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);
+			break;
+		}
+		if (pci_index == 255) {
+			printk(KERN_WARNING "HFC-PCI: No card found\n");
+			return (0);
+		}
+		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);
+		}
+		/* Allocate memory for FIFOS */
+		/* Because the HFC-PCI needs a 32K physical alignment, we */
+		/* need to allocate the double mem and align the address */
+		if (!((void *) cs->hw.hfcpci.share_start = kmalloc(65536, GFP_KERNEL))) {
+			printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n");
+			return 0;
+		}
+		(ulong) cs->hw.hfcpci.fifos =
+		    (((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));
+		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",
+		       (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_m1 = 0;
+		Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
+		Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
+		/* At this point the needed PCI config is done */
+		/* fifos are still not enabled */
+	} else
+		return (0);	/* no valid card type */
+
+
+	cs->readisac = NULL;
+	cs->writeisac = NULL;
+	cs->readisacfifo = NULL;
+	cs->writeisacfifo = NULL;
+	cs->BC_Read_Reg = NULL;
+	cs->BC_Write_Reg = NULL;
+	cs->irq_func = &hfcpci_interrupt;
+	cs->irq_flags |= SA_SHIRQ;
+
+	cs->hw.hfcpci.timer.function = (void *) hfcpci_Timer;
+	cs->hw.hfcpci.timer.data = (long) cs;
+	init_timer(&cs->hw.hfcpci.timer);
+
+	reset_hfcpci(cs);
+	cs->cardmsg = &hfcpci_card_msg;
+	return (1);
+#else
+	printk(KERN_WARNING "HFC-PCI: NO_PCI_BIOS\n");
+	return (0);
+#endif				/* CONFIG_PCI */
+}
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/hfc_pci.h linux/drivers/isdn/hisax/hfc_pci.h
--- v2.3.13/linux/drivers/isdn/hisax/hfc_pci.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/hisax/hfc_pci.h	Thu Aug 12 09:42:33 1999
@@ -0,0 +1,252 @@
+/* $Id: hfc_pci.h,v 1.5 1999/08/09 19:13:34 werner Exp $
+
+ *  specific defines for CCD's HFC 2BDS0 PCI chips
+ *
+ * Author     Werner Cornelius (werner@isdn4linux.de)      
+ *
+ * Copyright 1999  by Werner Cornelius (werner@isdn4linux.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Log: hfc_pci.h,v $
+ * Revision 1.5  1999/08/09 19:13:34  werner
+ * moved constant pci ids to pci id table
+ *
+ * Revision 1.4  1999/08/08 10:17:33  werner
+ * added new PCI vendor and card ids for Manufacturer 0x1043
+ *
+ * Revision 1.3  1999/07/14 12:39:34  werner
+ * Added changes for echo handling.
+ *
+ * Revision 1.2  1999/07/01 08:07:52  keil
+ * Initial version
+ *
+ *
+ *
+ */
+
+
+/* defines for PCI config */
+
+#define PCI_ENA_MEMIO    0x02
+#define PCI_ENA_MASTER   0x04
+
+
+/* GCI/IOM bus monitor registers */
+
+#define HCFPCI_C_I       0x08
+#define HFCPCI_TRxR      0x0C
+#define HFCPCI_MON1_D    0x28
+#define HFCPCI_MON2_D    0x2C
+
+
+/* GCI/IOM bus timeslot registers */
+
+#define HFCPCI_B1_SSL    0x80
+#define HFCPCI_B2_SSL    0x84
+#define HFCPCI_AUX1_SSL  0x88
+#define HFCPCI_AUX2_SSL  0x8C
+#define HFCPCI_B1_RSL    0x90
+#define HFCPCI_B2_RSL    0x94
+#define HFCPCI_AUX1_RSL  0x98
+#define HFCPCI_AUX2_RSL  0x9C
+
+/* GCI/IOM bus data registers */
+
+#define HFCPCI_B1_D      0xA0
+#define HFCPCI_B2_D      0xA4
+#define HFCPCI_AUX1_D    0xA8
+#define HFCPCI_AUX2_D    0xAC
+
+/* GCI/IOM bus configuration registers */
+
+#define HFCPCI_MST_EMOD  0xB4
+#define HFCPCI_MST_MODE	 0xB8
+#define HFCPCI_CONNECT 	 0xBC
+
+
+/* Interrupt and status registers */
+
+#define HFCPCI_FIFO_EN   0x44
+#define HFCPCI_TRM       0x48
+#define HFCPCI_B_MODE    0x4C
+#define HFCPCI_CHIP_ID   0x58
+#define HFCPCI_CIRM  	 0x60
+#define HFCPCI_CTMT	 0x64
+#define HFCPCI_INT_M1  	 0x68
+#define HFCPCI_INT_M2  	 0x6C
+#define HFCPCI_INT_S1  	 0x78
+#define HFCPCI_INT_S2  	 0x7C
+#define HFCPCI_STATUS  	 0x70
+
+/* S/T section registers */
+
+#define HFCPCI_STATES  	 0xC0
+#define HFCPCI_SCTRL  	 0xC4
+#define HFCPCI_SCTRL_E   0xC8
+#define HFCPCI_SCTRL_R   0xCC
+#define HFCPCI_SQ  	 0xD0
+#define HFCPCI_CLKDEL  	 0xDC
+#define HFCPCI_B1_REC    0xF0
+#define HFCPCI_B1_SEND   0xF0
+#define HFCPCI_B2_REC    0xF4
+#define HFCPCI_B2_SEND   0xF4
+#define HFCPCI_D_REC     0xF8
+#define HFCPCI_D_SEND    0xF8
+#define HFCPCI_E_REC     0xFC
+
+
+/* bits in status register (READ) */
+#define HFCPCI_PCI_PROC   0x02
+#define HFCPCI_NBUSY	  0x04 
+#define HFCPCI_TIMER_ELAP 0x10
+#define HFCPCI_STATINT	  0x20
+#define HFCPCI_FRAMEINT	  0x40
+#define HFCPCI_ANYINT	  0x80
+
+/* bits in CTMT (Write) */
+#define HFCPCI_CLTIMER    0x80
+#define HFCPCI_TIM3_125   0x00
+#define HFCPCI_TIM25      0x10
+#define HFCPCI_TIM50      0x14
+#define HFCPCI_TIM400     0x18
+#define HFCPCI_TIM800     0x1C
+#define HFCPCI_AUTO_TIMER 0x20
+#define HFCPCI_TRANSB2    0x02
+#define HFCPCI_TRANSB1    0x01
+
+/* bits in CIRM (Write) */
+#define HFCPCI_AUX_MSK    0x07
+#define HFCPCI_RESET  	  0x08
+#define HFCPCI_B1_REV     0x40
+#define HFCPCI_B2_REV     0x80
+
+/* bits in INT_M1 and INT_S1 */
+#define HFCPCI_INTS_B1TRANS  0x01
+#define HFCPCI_INTS_B2TRANS  0x02
+#define HFCPCI_INTS_DTRANS   0x04
+#define HFCPCI_INTS_B1REC    0x08
+#define HFCPCI_INTS_B2REC    0x10
+#define HFCPCI_INTS_DREC     0x20
+#define HFCPCI_INTS_L1STATE  0x40
+#define HFCPCI_INTS_TIMER    0x80
+
+/* bits in INT_M2 */
+#define HFCPCI_PROC_TRANS    0x01
+#define HFCPCI_GCI_I_CHG     0x02
+#define HFCPCI_GCI_MON_REC   0x04
+#define HFCPCI_IRQ_ENABLE    0x08
+#define HFCPCI_PMESEL        0x80
+
+/* bits in STATES */
+#define HFCPCI_STATE_MSK     0x0F
+#define HFCPCI_LOAD_STATE    0x10
+#define HFCPCI_ACTIVATE	     0x20
+#define HFCPCI_DO_ACTION     0x40
+#define HFCPCI_NT_G2_G3      0x80
+
+/* bits in HFCD_MST_MODE */
+#define HFCPCI_MASTER	     0x01
+#define HFCPCI_SLAVE         0x00
+/* remaining bits are for codecs control */
+
+/* bits in HFCD_SCTRL */
+#define SCTRL_B1_ENA	     0x01
+#define SCTRL_B2_ENA	     0x02
+#define SCTRL_MODE_TE        0x00
+#define SCTRL_MODE_NT        0x04
+#define SCTRL_LOW_PRIO	     0x08
+#define SCTRL_SQ_ENA	     0x10
+#define SCTRL_TEST	     0x20
+#define SCTRL_NONE_CAP	     0x40
+#define SCTRL_PWR_DOWN	     0x80
+
+/* bits in SCTRL_E  */
+#define HFCPCI_AUTO_AWAKE    0x01
+#define HFCPCI_DBIT_1        0x04
+#define HFCPCI_IGNORE_COL    0x08
+#define HFCPCI_CHG_B1_B2     0x80
+
+/****************************/
+/* bits in FIFO_EN register */
+/****************************/
+#define HFCPCI_FIFOEN_B1     0x03
+#define HFCPCI_FIFOEN_B2     0x0C
+#define HFCPCI_FIFOEN_DTX    0x10
+#define HFCPCI_FIFOEN_B2RX   0x08
+
+
+/***********************************/
+/* definitions of fifo memory area */
+/***********************************/
+#define MAX_D_FRAMES 15
+#define MAX_B_FRAMES 31
+#define B_SUB_VAL    0x200
+#define B_FIFO_SIZE  (0x2000 - B_SUB_VAL)
+#define D_FIFO_SIZE  512
+#define D_FREG_MASK  0xF
+
+typedef struct {
+    unsigned short z1;  /* Z1 pointer 16 Bit */
+    unsigned short z2;  /* Z2 pointer 16 Bit */
+  } z_type;
+
+typedef struct {
+    u_char data[D_FIFO_SIZE]; /* FIFO data space */
+    u_char fill1[0x20A0-D_FIFO_SIZE]; /* reserved, do not use */
+    u_char f1,f2; /* f pointers */
+    u_char fill2[0x20C0-0x20A2]; /* reserved, do not use */
+    z_type za[MAX_D_FRAMES+1]; /* mask index with D_FREG_MASK for access */
+    u_char fill3[0x4000-0x2100]; /* align 16K */  
+  } dfifo_type;
+
+typedef struct {
+    z_type za[MAX_B_FRAMES+1]; /* only range 0x0..0x1F allowed */ 
+    u_char f1,f2; /* f pointers */
+    u_char fill[0x2100-0x2082]; /* alignment */
+  } bzfifo_type;
+
+
+typedef union {
+    struct { 
+      dfifo_type d_tx; /* D-send channel */
+      dfifo_type d_rx; /* D-receive channel */
+    } d_chan; 
+    struct {
+      u_char fill1[0x200];
+      u_char txdat_b1[B_FIFO_SIZE];
+      bzfifo_type txbz_b1;
+
+      bzfifo_type txbz_b2;
+      u_char txdat_b2[B_FIFO_SIZE];
+
+      u_char fill2[D_FIFO_SIZE];
+
+      u_char rxdat_b1[B_FIFO_SIZE];
+      bzfifo_type rxbz_b1;
+
+      bzfifo_type rxbz_b2;
+      u_char rxdat_b2[B_FIFO_SIZE];
+    } b_chans;  
+    u_char fill[32768]; 
+  } fifo_area;
+
+
+#define Write_hfc(a,b,c) (*(((u_char *)a->hw.hfcpci.pci_io)+b) = c) 
+#define Read_hfc(a,b) (*(((u_char *)a->hw.hfcpci.pci_io)+b))
+
+extern void main_irq_hcpci(struct BCState *bcs);
+extern void inithfcpci(struct IsdnCardState *cs);
+extern void releasehfcpci(struct IsdnCardState *cs);
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/hfcscard.c linux/drivers/isdn/hisax/hfcscard.c
--- v2.3.13/linux/drivers/isdn/hisax/hfcscard.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/hisax/hfcscard.c	Thu Aug 12 09:42:33 1999
@@ -0,0 +1,206 @@
+/* $Id: hfcscard.c,v 1.4 1999/08/09 18:59:59 keil Exp $
+
+ * hfcscard.c     low level stuff for hfcs based cards (Teles3c, ACER P10)
+ *
+ * Author     Karsten Keil (keil@isdn4linux.de)
+ *
+ *
+ * $Log: hfcscard.c,v $
+ * Revision 1.4  1999/08/09 18:59:59  keil
+ * Fix S0 init - Thanks to Stefan Gybas
+ *
+ * Revision 1.3  1999/07/12 21:05:12  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 1.2  1999/07/01 08:16:03  keil
+ * teles3c ---> hfcscard
+ *
+ *
+ *
+ */
+
+#define __NO_VERSION__
+#include "hisax.h"
+#include "hfc_2bds0.h"
+#include "isdnl1.h"
+
+extern const char *CardType[];
+
+static const char *hfcs_revision = "$Revision: 1.4 $";
+
+static void
+hfcs_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char val, stat;
+
+	if (!cs) {
+		printk(KERN_WARNING "HFCS: Spurious interrupt!\n");
+		return;
+	}
+	if ((HFCD_ANYINT | HFCD_BUSY_NBUSY) & 
+		(stat = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_STAT))) {
+		val = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_INT_S1);
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "HFCS: stat(%02x) s1(%02x)", stat, val);
+		hfc2bds0_interrupt(cs, val);
+	} else {
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "HFCS: irq_no_irq stat(%02x)", stat);
+	}
+}
+
+static void
+hfcs_Timer(struct IsdnCardState *cs)
+{
+	cs->hw.hfcD.timer.expires = jiffies + 75;
+	/* WD RESET */
+/*	WriteReg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt | 0x80);
+	add_timer(&cs->hw.hfcD.timer);
+*/
+}
+
+void
+release_io_hfcs(struct IsdnCardState *cs)
+{
+	release2bds0(cs);
+	del_timer(&cs->hw.hfcD.timer);
+	if (cs->hw.hfcD.addr)
+		release_region(cs->hw.hfcD.addr, 2);
+}
+
+static void
+reset_hfcs(struct IsdnCardState *cs)
+{
+	long flags;
+
+	printk(KERN_INFO "HFCS: resetting card\n");
+	cs->hw.hfcD.cirm = HFCD_RESET;
+	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 On */
+	save_flags(flags);
+	sti();
+	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;
+	schedule_timeout((10*HZ)/1000);
+	if (cs->typ == ISDN_CTYPE_TELES3C)
+		cs->hw.hfcD.cirm |= HFCD_INTB;
+	else if (cs->typ == ISDN_CTYPE_ACERP10)
+		cs->hw.hfcD.cirm |= HFCD_INTA;
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm);
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CLKDEL, 0x0e);
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_TEST, HFCD_AUTO_AWAKE); /* S/T Auto awake */
+	cs->hw.hfcD.ctmt = HFCD_TIM25 | HFCD_AUTO_TIMER;
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt);
+	cs->hw.hfcD.int_m2 = HFCD_IRQ_ENABLE;
+	cs->hw.hfcD.int_m1 = HFCD_INTS_B1TRANS | HFCD_INTS_B2TRANS |
+		HFCD_INTS_DTRANS | HFCD_INTS_B1REC | HFCD_INTS_B2REC |
+		HFCD_INTS_DREC | HFCD_INTS_L1STATE;
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_INT_M1, cs->hw.hfcD.int_m1);
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_INT_M2, cs->hw.hfcD.int_m2);
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_STATES, HFCD_LOAD_STATE | 2); /* HFC ST 2 */
+	udelay(10);
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_STATES, 2); /* HFC ST 2 */
+	cs->hw.hfcD.mst_m = HFCD_MASTER;
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m); /* HFC Master */
+	cs->hw.hfcD.sctrl = 0;
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_SCTRL, cs->hw.hfcD.sctrl);
+	restore_flags(flags);
+}
+
+static int
+hfcs_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+	long flags;
+
+	if (cs->debug & L1_DEB_ISAC)
+		debugl1(cs, "HFCS: card_msg %x", mt);
+	switch (mt) {
+		case CARD_RESET:
+			reset_hfcs(cs);
+			return(0);
+		case CARD_RELEASE:
+			release_io_hfcs(cs);
+			return(0);
+		case CARD_INIT:
+			cs->hw.hfcD.timer.expires = jiffies + 75;
+			add_timer(&cs->hw.hfcD.timer);
+			init2bds0(cs);
+			save_flags(flags);
+			sti();
+			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); 
+			cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
+			restore_flags(flags);
+			return(0);
+		case CARD_TEST:
+			return(0);
+	}
+	return(0);
+}
+
+__initfunc(int
+setup_hfcs(struct IsdnCard *card))
+{
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+
+	strcpy(tmp, hfcs_revision);
+	printk(KERN_INFO "HiSax: HFC-S driver Rev. %s\n", HiSax_getrev(tmp));
+	cs->hw.hfcD.addr = card->para[1] & 0xfffe;
+	cs->irq = card->para[0];
+	cs->hw.hfcD.cip = 0;
+	cs->hw.hfcD.int_s1 = 0;
+	cs->hw.hfcD.send = NULL;
+	cs->bcs[0].hw.hfc.send = NULL;
+	cs->bcs[1].hw.hfc.send = NULL;
+	cs->hw.hfcD.dfifosize = 512;
+	cs->dc.hfcd.ph_state = 0;
+	cs->hw.hfcD.fifo = 255;
+	if (cs->typ == ISDN_CTYPE_TELES3C) {
+		cs->hw.hfcD.bfifosize = 1024 + 512;
+	} else if (cs->typ == ISDN_CTYPE_ACERP10) {
+		cs->hw.hfcD.bfifosize = 7*1024 + 512;
+	} else
+		return (0);
+	if (check_region((cs->hw.hfcD.addr), 2)) {
+		printk(KERN_WARNING
+		       "HiSax: %s config port %x-%x already in use\n",
+		       CardType[card->typ],
+		       cs->hw.hfcD.addr,
+		       cs->hw.hfcD.addr + 2);
+		return (0);
+	} else {
+		request_region(cs->hw.hfcD.addr, 2, "HFCS isdn");
+	}
+	printk(KERN_INFO
+	       "HFCS: defined at 0x%x IRQ %d HZ %d\n",
+	       cs->hw.hfcD.addr,
+	       cs->irq, HZ);
+	if (cs->typ == ISDN_CTYPE_TELES3C) {
+		/* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */
+		outb(0x00, cs->hw.hfcD.addr);
+		outb(0x56, cs->hw.hfcD.addr | 1);
+	} else if (cs->typ == ISDN_CTYPE_ACERP10) {
+		/* Acer P10 IO ADR is 0x300 */
+		outb(0x00, cs->hw.hfcD.addr);
+		outb(0x57, cs->hw.hfcD.addr | 1);
+	}
+	set_cs_func(cs);
+	cs->hw.hfcD.timer.function = (void *) hfcs_Timer;
+	cs->hw.hfcD.timer.data = (long) cs;
+	init_timer(&cs->hw.hfcD.timer);
+	reset_hfcs(cs);
+	cs->cardmsg = &hfcs_card_msg;
+	cs->irq_func = &hfcs_interrupt;
+	return (1);
+}
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/hisax.h linux/drivers/isdn/hisax/hisax.h
--- v2.3.13/linux/drivers/isdn/hisax/hisax.h	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/hisax/hisax.h	Thu Aug 12 09:42:33 1999
@@ -1,8 +1,28 @@
-/* $Id: hisax.h,v 2.26 1998/11/15 23:54:45 keil Exp $
+/* $Id: hisax.h,v 2.33 1999/08/05 20:43:16 keil Exp $
 
  *   Basic declarations, defines and prototypes
  *
  * $Log: hisax.h,v $
+ * Revision 2.33  1999/08/05 20:43:16  keil
+ * ISAR analog modem support
+ *
+ * Revision 2.31  1999/07/21 14:46:11  keil
+ * changes from EICON certification
+ *
+ * Revision 2.30  1999/07/14 12:38:38  werner
+ * Added changes for echo channel handling
+ *
+ * Revision 2.29  1999/07/12 21:05:14  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 2.28  1999/07/05 23:51:46  werner
+ * Allow limiting of available HiSax B-chans per card. Controlled by hisaxctrl
+ * hisaxctrl id 10 <nr. of chans 0-2>
+ *
+ * Revision 2.27  1999/07/01 08:11:38  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 2.26  1998/11/15 23:54:45  keil
  * changes from 2.0
  *
@@ -111,8 +131,7 @@
 #include <linux/wait.h>
 #include <linux/isdnif.h>
 #include <linux/tty.h>
-#include <linux/init.h>
-#include <linux/serialP.h>
+#include <linux/serial_reg.h>
 
 #define REQUEST		0
 #define CONFIRM		1
@@ -131,7 +150,6 @@
 #define HW_RSYNC	0x0060
 #define HW_TESTLOOP	0x0070
 #define CARD_RESET	0x00F0
-#define CARD_SETIRQ	0x00F1
 #define CARD_INIT	0x00F2
 #define CARD_RELEASE	0x00F3
 #define CARD_TEST	0x00F4
@@ -168,16 +186,21 @@
 #define CC_SETUP_COMPL	0x0330
 #define CC_PROCEEDING	0x0340
 #define CC_ALERTING	0x0344
+#define CC_PROGRESS	0x0348
 #define CC_CONNECT	0x0350
 #define CC_CHARGE	0x0354
+#define CC_NOTIFY	0x0358
 #define CC_DISCONNECT	0x0360
 #define CC_RELEASE	0x0368
 #define CC_SUSPEND	0x0370
+#define CC_PROCEED_SEND 0x0374
+#define CC_REDIR        0x0378
 #define CC_T303		0x0383
 #define CC_T304		0x0384
 #define CC_T305		0x0385
 #define CC_T308_1	0x0388
-#define CC_T308_2	0x0389
+#define CC_T308_2	0x038A
+#define CC_T309         0x0309
 #define CC_T310		0x0390
 #define CC_T313		0x0393
 #define CC_T318		0x0398
@@ -188,12 +211,22 @@
 #define CC_RESUME_ERR	0x03E3
 #define CC_CONNECT_ERR	0x03E4
 #define CC_RELEASE_ERR	0x03E5
-#define CC_DLRL		0x03F0
 #define CC_RESTART	0x03F4
+#define CC_TDSS1_IO     0x13F4    /* DSS1 IO user timer */
+
+/* define maximum number of possible waiting incoming calls */
+#define MAX_WAITING_CALLS 2
 
 
 #ifdef __KERNEL__
 
+/* include only l3dss1 specific process structures, but no other defines */
+#ifdef CONFIG_HISAX_EURO
+  #define l3dss1_process
+  #include "l3dss1.h" 
+  #undef  l3dss1_process
+#endif CONFIG_HISAX_EURO
+
 #define MAX_DFRAME_LEN	260
 #define MAX_DFRAME_LEN_L1	300
 #define HSCX_BUFMAX	4096
@@ -294,16 +327,17 @@
 #define FLG_ESTAB_PEND	13
 #define FLG_PTP		14
 #define FLG_FIXED_TEI	15
+#define FLG_L2BLOCK	16
 
 struct Layer2 {
 	int tei;
 	int sap;
 	int maxlen;
 	unsigned int flag;
-	int vs, va, vr;
+	unsigned int vs, va, vr;
 	int rc;
-	int window;
-	int sow;
+	unsigned int window;
+	unsigned int sow;
 	struct sk_buff *windowar[MAX_WINDOW];
 	struct sk_buff_head i_queue;
 	struct sk_buff_head ui_queue;
@@ -319,8 +353,10 @@
 
 struct Layer3 {
 	void (*l3l4) (struct PStack *, int, void *);
+        void (*l3ml3) (struct PStack *, int, void *);
 	void (*l3l2) (struct PStack *, int, void *);
 	struct FsmInst l3m;
+        struct FsmTimer l3m_timer;
 	struct sk_buff_head squeue;
 	struct l3_process *proc;
 	struct l3_process *global;
@@ -331,6 +367,7 @@
 
 struct LLInterface {
 	void (*l4l3) (struct PStack *, int, void *);
+        int  (*l4l3_proto) (struct PStack *, isdn_ctrl *);
 	void *userdata;
 	void (*l1writewakeup) (struct PStack *, int);
 	void (*l2writewakeup) (struct PStack *, int);
@@ -345,16 +382,17 @@
 	void (*layer) (struct PStack *, int, void *);
 };
 
+#define NO_CAUSE 254
 
 struct Param {
-	int cause;
-	int loc;
+	u_char cause;
+	u_char loc;
+	u_char diag[6];
 	int bchannel;
-	setup_parm setup;	/* from isdnif.h numbers and Serviceindicator */
-	int chargeinfo;		/* Charge Info - only for 1tr6 in
-				 * the moment
-				 */
+	int chargeinfo;
 	int spv;		/* SPV Flag */
+	setup_parm setup;	/* from isdnif.h numbers and Serviceindicator */
+	u_char moderate;	/* transfer mode and rate (bearer octet 4) */
 };
 
 
@@ -366,6 +404,14 @@
 	struct LLInterface lli;
 	struct Management ma;
 	int protocol;		/* EDSS1 or 1TR6 */
+
+        /* protocol specific data fields */
+        union
+	 { u_char uuuu; /* only as dummy */
+#ifdef CONFIG_HISAX_EURO
+           dss1_stk_priv dss1; /* private dss1 data */
+#endif CONFIG_HISAX_EURO              
+	 } prot;
 };
 
 struct l3_process {
@@ -378,6 +424,15 @@
 	struct Channel *chan;
 	struct PStack *st;
 	struct l3_process *next;
+        ulong redir_result;
+
+        /* protocol specific data fields */
+        union 
+	 { u_char uuuu; /* only when euro not defined, avoiding empty union */
+#ifdef CONFIG_HISAX_EURO 
+           dss1_proc_priv dss1; /* private dss1 data */
+#endif CONFIG_HISAX_EURO            
+	 } prot;
 };
 
 struct hscx_hw {
@@ -385,6 +440,8 @@
 	int rcvidx;
 	int count;              /* Current skb sent count */
 	u_char *rcvbuf;         /* B-Channel receive Buffer */
+	u_char tsaxr0;
+	u_char tsaxr1;
 };
 
 struct isar_reg {
@@ -402,6 +459,7 @@
 	int txcnt;
 	int mml;
 	u_char *rcvbuf;         /* B-Channel receive Buffer */
+	u_char conmsg[16];
 	struct isar_reg *reg;
 };
 
@@ -469,11 +527,15 @@
 #define BC_FLG_NOFRAME	4
 #define BC_FLG_HALF	5
 #define BC_FLG_EMPTY	6
+#define BC_FLG_ORIG	7
 
 #define L1_MODE_NULL	0
 #define L1_MODE_TRANS	1
 #define L1_MODE_HDLC	2
+#define L1_MODE_EXTRN	3
 #define L1_MODE_MODEM	7
+#define L1_MODE_V32	8
+#define L1_MODE_FAX	9
 
 struct BCState {
 	int channel;
@@ -486,6 +548,7 @@
 	struct sk_buff_head squeue;	/* B-Channel send Queue */
 	struct PStack *st;
 	u_char *blog;
+	u_char *conmsg;
 	struct timer_list transbusy;
 	struct tq_struct tqueue;
 	int event;
@@ -578,7 +641,8 @@
 };
 
 struct diva_hw {
-	unsigned int cfg_reg;
+	unsigned long cfg_reg;
+	unsigned long pci_cfg;
 	unsigned int ctrl;
 	unsigned int isac_adr;
 	unsigned int isac;
@@ -647,6 +711,31 @@
 	unsigned char last_is0;
 };
 
+struct hfcPCI_hw {
+	unsigned char cirm;
+	unsigned char ctmt;
+	unsigned char conn;
+	unsigned char mst_m;
+	unsigned char int_m1;
+	unsigned char int_m2;
+	unsigned char int_s1;
+	unsigned char sctrl;
+        unsigned char sctrl_r;
+        unsigned char sctrl_e;
+        unsigned char trm;
+	unsigned char stat;
+	unsigned char fifo;
+        unsigned char fifo_en;
+        unsigned char bswapped;
+  /*	unsigned int *send; */
+	unsigned char pci_bus;
+        unsigned char pci_device_fn;
+        unsigned char *pci_io; /* start of PCI IO memory */
+        void *share_start; /* shared memory for Fifos start */
+        void *fifos; /* FIFO memory */ 
+	struct timer_list timer;
+};
+
 struct hfcD_hw {
 	unsigned int addr;
 	unsigned int bfifosize;
@@ -668,25 +757,118 @@
 	struct timer_list timer;
 };
 
-#define HW_IOM1		0
-#define HW_IPAC		1
-#define HW_ISAR		2
-#define FLG_TWO_DCHAN	4
-#define FLG_L1_DBUSY	5
-#define FLG_DBUSY_TIMER 6
-#define FLG_LOCK_ATOMIC 7
-#define HW_MON0_RX_END	8
-#define HW_MON1_RX_END	9
-#define HW_MON0_TX_END	10
-#define HW_MON1_TX_END	11
+struct isurf_hw {
+	unsigned int reset;
+	unsigned int isac;
+	unsigned int isar;
+	struct isar_reg isar_r;
+};
+
+struct saphir_hw {
+	unsigned int cfg_reg;
+	unsigned int ale;
+	unsigned int isac;
+	unsigned int hscx;
+	struct timer_list timer;
+};
+
+struct bkm_hw {
+	unsigned int base;
+	/* A4T stuff */
+	unsigned int isac_adr;
+	unsigned int isac_ale;
+	unsigned int jade_adr;
+	unsigned int jade_ale;
+	/* Scitel Quadro stuff */
+	unsigned int plx_adr;
+	unsigned int data_adr;
+};	
+
+struct gazel_hw {
+	unsigned int cfg_reg;
+	unsigned int pciaddr[2];
+        signed   int ipac;
+	signed   int isac;
+	signed   int hscx[2];
+	signed   int isacfifo;
+	signed   int hscxfifo[2];
+	unsigned char timeslot;
+	unsigned char iom2;
+};
+
+#ifdef  CONFIG_HISAX_TESTEMU
+struct te_hw {
+	unsigned char *sfifo;
+	unsigned char *sfifo_w;
+	unsigned char *sfifo_r;
+	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
+
+struct arcofi_msg {
+	struct arcofi_msg *next;
+	u_char receive;
+	u_char len;
+	u_char msg[10];
+};
+
+struct isac_chip {
+	int ph_state;
+	u_char *mon_tx;
+	u_char *mon_rx;
+	int mon_txp;
+	int mon_txc;
+	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;
+	u_char adf2;
+};
+
+struct hfcd_chip {
+	int ph_state;
+};
+
+struct hfcpci_chip {
+	int ph_state;
+};
+
+#define HW_IOM1			0
+#define HW_IPAC			1
+#define HW_ISAR			2
+#define FLG_TWO_DCHAN		4
+#define FLG_L1_DBUSY		5
+#define FLG_DBUSY_TIMER 	6
+#define FLG_LOCK_ATOMIC 	7
+#define FLG_ARCOFI_TIMER	8
+#define FLG_ARCOFI_ERROR	9
 
 struct IsdnCardState {
 	unsigned char typ;
 	unsigned char subtyp;
 	int protocol;
 	unsigned int irq;
+	unsigned long irq_flags;
 	int HW_Flags;
 	int *busy_flag;
+        int chanlimit; /* limited number of B-chans to use */
+        int logecho; /* log echo if supported by card */
 	union {
 		struct elsa_hw elsa;
 		struct teles0_hw teles0;
@@ -701,7 +883,15 @@
 		struct mic_hw mic;
 		struct njet_hw njet;
 		struct hfcD_hw hfcD;
+		struct hfcPCI_hw hfcpci;
 		struct ix1_hw niccy;
+		struct isurf_hw isurf;
+		struct saphir_hw saphir;
+#ifdef CONFIG_HISAX_TESTEMU
+		struct te_hw te;
+#endif
+		struct bkm_hw ax;
+		struct gazel_hw gazel;
 	} hw;
 	int myid;
 	isdn_if iif;
@@ -717,9 +907,21 @@
 	void   (*BC_Write_Reg) (struct IsdnCardState *, int, u_char, u_char);
 	void   (*BC_Send_Data) (struct BCState *);
 	int    (*cardmsg) (struct IsdnCardState *, int, void *);
-	struct Channel channel[2];
-	struct BCState bcs[2];
+	void   (*setstack_d) (struct PStack *, struct IsdnCardState *);
+	void   (*DC_Close) (struct IsdnCardState *);
+	void   (*irq_func) (int, void *, struct pt_regs *);
+	struct Channel channel[2+MAX_WAITING_CALLS];
+	struct BCState bcs[2+MAX_WAITING_CALLS];
 	struct PStack *stlist;
+	struct sk_buff_head rq, sq; /* D-channel queues */
+	int cardnr;
+	char *dlog;
+	int debug;
+	union {
+		struct isac_chip isac;
+		struct hfcd_chip hfcd;
+		struct hfcpci_chip hfcpci;
+	} dc;
 	u_char *rcvbuf;
 	int rcvidx;
 	struct sk_buff *tx_skb;
@@ -727,18 +929,6 @@
 	int event;
 	struct tq_struct tqueue;
 	struct timer_list dbusytimer;
-	struct sk_buff_head rq, sq; /* D-channel queues */
-	int ph_state;
-	int cardnr;
-	char *dlog;
-	int debug;
-	u_char *mon_tx;
-	u_char *mon_rx;
-	int mon_txp;
-	int mon_txc;
-	int mon_rxp;
-	u_char mocr;
-	void   (*setstack_d) (struct PStack *, struct IsdnCardState *);
 };
 
 #define  MON0_RX	1
@@ -776,18 +966,33 @@
 #define  ISDN_CTYPE_A1_PCMCIA	26
 #define  ISDN_CTYPE_FRITZPCI	27
 #define  ISDN_CTYPE_SEDLBAUER_FAX     28
+#define  ISDN_CTYPE_ISURF	29
+#define  ISDN_CTYPE_ACERP10	30
+#define  ISDN_CTYPE_HSTSAPHIR	31
+#define	 ISDN_CTYPE_BKM_A4T	32
+#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_COUNT	28
 
 #ifdef ISDN_CHIP_ISAC
 #undef ISDN_CHIP_ISAC
 #endif
 
+#ifndef __initfunc
+#define __initfunc(__arginit) __arginit
+#endif
+
+#ifndef __initdata
+#define __initdata
+#endif
+
 #define HISAX_INITFUNC(__arginit) __initfunc(__arginit)
 #define HISAX_INITDATA __initdata
 
 #ifdef	CONFIG_HISAX_16_0
-#define  CARD_TELES0 (1<< ISDN_CTYPE_16_0) | (1<< ISDN_CTYPE_8_0)
+#define  CARD_TELES0 1
 #ifndef ISDN_CHIP_ISAC
 #define ISDN_CHIP_ISAC 1
 #endif
@@ -796,8 +1001,7 @@
 #endif
 
 #ifdef	CONFIG_HISAX_16_3
-#define  CARD_TELES3 (1<< ISDN_CTYPE_16_3) | (1<< ISDN_CTYPE_PNP) | \
-		     (1<< ISDN_CTYPE_TELESPCMCIA) | (1<< ISDN_CTYPE_COMPAQ_ISA)
+#define  CARD_TELES3 1
 #ifndef ISDN_CHIP_ISAC
 #define ISDN_CHIP_ISAC 1
 #endif
@@ -806,7 +1010,7 @@
 #endif
 
 #ifdef	CONFIG_HISAX_TELESPCI
-#define  CARD_TELESPCI (1<< ISDN_CTYPE_TELESPCI)
+#define  CARD_TELESPCI 1
 #ifndef ISDN_CHIP_ISAC
 #define ISDN_CHIP_ISAC 1
 #endif
@@ -815,7 +1019,7 @@
 #endif
 
 #ifdef	CONFIG_HISAX_AVM_A1
-#define  CARD_AVM_A1 (1<< ISDN_CTYPE_A1)
+#define  CARD_AVM_A1 1
 #ifndef ISDN_CHIP_ISAC
 #define ISDN_CHIP_ISAC 1
 #endif
@@ -824,7 +1028,7 @@
 #endif
 
 #ifdef	CONFIG_HISAX_AVM_A1_PCMCIA
-#define  CARD_AVM_A1_PCMCIA (1<< ISDN_CTYPE_A1_PCMCIA)
+#define  CARD_AVM_A1_PCMCIA 1
 #ifndef ISDN_CHIP_ISAC
 #define ISDN_CHIP_ISAC 1
 #endif
@@ -833,7 +1037,7 @@
 #endif
 
 #ifdef	CONFIG_HISAX_FRITZPCI
-#define  CARD_FRITZPCI (1<< ISDN_CTYPE_FRITZPCI)
+#define  CARD_FRITZPCI 1
 #ifndef ISDN_CHIP_ISAC
 #define ISDN_CHIP_ISAC 1
 #endif
@@ -842,8 +1046,7 @@
 #endif
 
 #ifdef	CONFIG_HISAX_ELSA
-#define  CARD_ELSA (1<< ISDN_CTYPE_ELSA) | (1<< ISDN_CTYPE_ELSA_PNP) | \
-		   (1<< ISDN_CTYPE_ELSA_PCMCIA) | (1<< ISDN_CTYPE_ELSA_PCI)
+#define  CARD_ELSA 1
 #ifndef ISDN_CHIP_ISAC
 #define ISDN_CHIP_ISAC 1
 #endif
@@ -855,9 +1058,8 @@
 #define  CARD_ELSA  0
 #endif
 
-
 #ifdef	CONFIG_HISAX_IX1MICROR2
-#define	CARD_IX1MICROR2 (1 << ISDN_CTYPE_IX1MICROR2)
+#define	CARD_IX1MICROR2 1
 #ifndef ISDN_CHIP_ISAC
 #define ISDN_CHIP_ISAC 1
 #endif
@@ -866,7 +1068,7 @@
 #endif
 
 #ifdef  CONFIG_HISAX_DIEHLDIVA
-#define CARD_DIEHLDIVA (1 << ISDN_CTYPE_DIEHLDIVA)
+#define CARD_DIEHLDIVA 1
 #ifndef ISDN_CHIP_ISAC
 #define ISDN_CHIP_ISAC 1
 #endif
@@ -875,7 +1077,7 @@
 #endif
 
 #ifdef  CONFIG_HISAX_ASUSCOM
-#define CARD_ASUSCOM (1 << ISDN_CTYPE_ASUSCOM)
+#define CARD_ASUSCOM 1
 #ifndef ISDN_CHIP_ISAC
 #define ISDN_CHIP_ISAC 1
 #endif
@@ -884,7 +1086,7 @@
 #endif
 
 #ifdef  CONFIG_HISAX_TELEINT
-#define CARD_TELEINT (1 << ISDN_CTYPE_TELEINT)
+#define CARD_TELEINT 1
 #ifndef ISDN_CHIP_ISAC
 #define ISDN_CHIP_ISAC 1
 #endif
@@ -893,7 +1095,7 @@
 #endif
 
 #ifdef  CONFIG_HISAX_SEDLBAUER
-#define CARD_SEDLBAUER (1 << ISDN_CTYPE_SEDLBAUER) | (1 << ISDN_CTYPE_SEDLBAUER_PCMCIA) | ( 1 << ISDN_CTYPE_SEDLBAUER_FAX)
+#define CARD_SEDLBAUER 1
 #ifndef ISDN_CHIP_ISAC
 #define ISDN_CHIP_ISAC 1
 #endif
@@ -902,7 +1104,7 @@
 #endif
 
 #ifdef  CONFIG_HISAX_SPORTSTER
-#define CARD_SPORTSTER (1 << ISDN_CTYPE_SPORTSTER)
+#define CARD_SPORTSTER 1
 #ifndef ISDN_CHIP_ISAC
 #define ISDN_CHIP_ISAC 1
 #endif
@@ -911,7 +1113,7 @@
 #endif
 
 #ifdef  CONFIG_HISAX_MIC
-#define CARD_MIC (1 << ISDN_CTYPE_MIC)
+#define CARD_MIC 1
 #ifndef ISDN_CHIP_ISAC
 #define ISDN_CHIP_ISAC 1
 #endif
@@ -920,7 +1122,7 @@
 #endif
 
 #ifdef  CONFIG_HISAX_NETJET
-#define CARD_NETJET (1 << ISDN_CTYPE_NETJET)
+#define CARD_NETJET 1
 #ifndef ISDN_CHIP_ISAC
 #define ISDN_CHIP_ISAC 1
 #endif
@@ -928,20 +1130,27 @@
 #define CARD_NETJET 0
 #endif
 
-#ifdef	CONFIG_HISAX_TELES3C
-#define  CARD_TELES3C (1<< ISDN_CTYPE_TELES3C)
+#ifdef	CONFIG_HISAX_HFCS
+#define  CARD_HFCS 1
+#else
+#define  CARD_HFCS 0
+#endif
+
+#ifdef	CONFIG_HISAX_HFC_PCI
+#define  CARD_HFC_PCI 1
+extern int hfcpci_set_echo(struct IsdnCardState *, int);
 #else
-#define  CARD_TELES3C  0
+#define  CARD_HFC_PCI 0
 #endif
 
 #ifdef  CONFIG_HISAX_AMD7930
-#define CARD_AMD7930 (1 << ISDN_CTYPE_AMD7930)
+#define CARD_AMD7930 1
 #else
 #define CARD_AMD7930 0
 #endif
 
 #ifdef	CONFIG_HISAX_NICCY
-#define	CARD_NICCY (1 << ISDN_CTYPE_NICCY)
+#define	CARD_NICCY 1
 #ifndef ISDN_CHIP_ISAC
 #define ISDN_CHIP_ISAC 1
 #endif
@@ -949,8 +1158,17 @@
 #define CARD_NICCY 0
 #endif
 
+#ifdef	CONFIG_HISAX_ISURF
+#define	CARD_ISURF 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define CARD_ISURF 0
+#endif
+
 #ifdef	CONFIG_HISAX_S0BOX
-#define	CARD_S0BOX (1 << ISDN_CTYPE_S0BOX)
+#define	CARD_S0BOX 1
 #ifndef ISDN_CHIP_ISAC
 #define ISDN_CHIP_ISAC 1
 #endif
@@ -958,12 +1176,50 @@
 #define CARD_S0BOX 0
 #endif
 
-#define  SUPORTED_CARDS  (CARD_TELES0 | CARD_TELES3 | CARD_AVM_A1 | CARD_ELSA \
-			 | CARD_IX1MICROR2 | CARD_DIEHLDIVA | CARD_ASUSCOM \
-			 | CARD_TELEINT | CARD_SEDLBAUER | CARD_SPORTSTER \
-			 | CARD_MIC | CARD_NETJET | CARD_TELES3C | CARD_AMD7930 \
-			 | CARD_AVM_A1_PCMCIA | CARD_FRITZPCI\
-			 | CARD_NICCY | CARD_S0BOX | CARD_TELESPCI)
+#ifdef	CONFIG_HISAX_HSTSAPHIR
+#define	CARD_HSTSAPHIR 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define CARD_HSTSAPHIR 0
+#endif
+
+#ifdef	CONFIG_HISAX_TESTEMU
+#define	CARD_TESTEMU 1
+#define ISDN_CTYPE_TESTEMU 99
+#undef ISDN_CTYPE_COUNT
+#define  ISDN_CTYPE_COUNT ISDN_CTYPE_TESTEMU
+#else
+#define CARD_TESTEMU 0
+#endif
+
+#ifdef	CONFIG_HISAX_BKM_A4T
+#define	CARD_BKM_A4T 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define CARD_BKM_A4T 0
+#endif
+
+#ifdef	CONFIG_HISAX_SCT_QUADRO
+#define	CARD_SCT_QUADRO 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define CARD_SCT_QUADRO 0
+#endif
+
+#ifdef	CONFIG_HISAX_GAZEL
+#define  CARD_GAZEL 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define  CARD_GAZEL  0
+#endif
 
 #define TEI_PER_CARD 0
 
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/hscx.c linux/drivers/isdn/hisax/hscx.c
--- v2.3.13/linux/drivers/isdn/hisax/hscx.c	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/hisax/hscx.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: hscx.c,v 1.16 1998/11/15 23:54:48 keil Exp $
+/* $Id: hscx.c,v 1.17 1999/07/01 08:11:41 keil Exp $
 
  * hscx.c   HSCX specific routines
  *
@@ -6,6 +6,9 @@
  *
  *
  * $Log: hscx.c,v $
+ * Revision 1.17  1999/07/01 08:11:41  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 1.16  1998/11/15 23:54:48  keil
  * changes from 2.0
  *
@@ -110,12 +113,12 @@
 
 	if (bc == 0) {
 		cs->BC_Write_Reg(cs, hscx, HSCX_TSAX,
-			      test_bit(HW_IOM1, &cs->HW_Flags) ? 0x7 : 0x2f);
+			      test_bit(HW_IOM1, &cs->HW_Flags) ? 0x7 : bcs->hw.hscx.tsaxr0);
 		cs->BC_Write_Reg(cs, hscx, HSCX_TSAR,
-			      test_bit(HW_IOM1, &cs->HW_Flags) ? 0x7 : 0x2f);
+			      test_bit(HW_IOM1, &cs->HW_Flags) ? 0x7 : bcs->hw.hscx.tsaxr0);
 	} else {
-		cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, 0x3);
-		cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, 0x3);
+		cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, bcs->hw.hscx.tsaxr1);
+		cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, bcs->hw.hscx.tsaxr1);
 	}
 	switch (mode) {
 		case (L1_MODE_NULL):
@@ -216,7 +219,7 @@
 		discard_queue(&bcs->rqueue);
 		discard_queue(&bcs->squeue);
 		if (bcs->tx_skb) {
-			dev_kfree_skb(bcs->tx_skb);
+			idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
 			bcs->tx_skb = NULL;
 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 		}
@@ -301,6 +304,10 @@
 	cs->bcs[1].BC_Close = close_hscxstate;
 	cs->bcs[0].hw.hscx.hscx = 0;
 	cs->bcs[1].hw.hscx.hscx = 1;
+	cs->bcs[0].hw.hscx.tsaxr0 = 0x2f;
+	cs->bcs[0].hw.hscx.tsaxr1 = 3;
+	cs->bcs[1].hw.hscx.tsaxr0 = 0x2f;
+	cs->bcs[1].hw.hscx.tsaxr1 = 3;
 	modehscx(cs->bcs, 0, 0);
 	modehscx(cs->bcs + 1, 0, 0);
 }
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/hscx_irq.c linux/drivers/isdn/hisax/hscx_irq.c
--- v2.3.13/linux/drivers/isdn/hisax/hscx_irq.c	Tue Jun  1 23:25:48 1999
+++ linux/drivers/isdn/hisax/hscx_irq.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: hscx_irq.c,v 1.11 1998/11/15 23:54:49 keil Exp $
+/* $Id: hscx_irq.c,v 1.12 1999/07/01 08:11:42 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.12  1999/07/01 08:11:42  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 1.11  1998/11/15 23:54:49  keil
  * changes from 2.0
  *
@@ -42,8 +45,6 @@
  *
  */
 
-#include <linux/string.h>
-
 
 static inline void
 waitforCEC(struct IsdnCardState *cs, int hscx)
@@ -203,6 +204,7 @@
 				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);
 				}
@@ -218,6 +220,7 @@
 			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);
 			}
@@ -234,7 +237,7 @@
 				if (bcs->st->lli.l1writewakeup &&
 					(PACKET_NOACK != bcs->tx_skb->pkt_type))
 					bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count);
-				dev_kfree_skb(bcs->tx_skb);
+				idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
 				bcs->hw.hscx.count = 0; 
 				bcs->tx_skb = NULL;
 			}
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/isac.c linux/drivers/isdn/hisax/isac.c
--- v2.3.13/linux/drivers/isdn/hisax/isac.c	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/hisax/isac.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: isac.c,v 1.18 1998/11/15 23:54:51 keil Exp $
+/* $Id: isac.c,v 1.22 1999/08/09 19:04:40 keil Exp $
 
  * isac.c   ISAC specific routines
  *
@@ -9,6 +9,19 @@
  *		../../../Documentation/isdn/HiSax.cert
  *
  * $Log: isac.c,v $
+ * Revision 1.22  1999/08/09 19:04:40  keil
+ * Fix race condition - Thanks to Christer Weinigel
+ *
+ * Revision 1.21  1999/07/12 21:05:17  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 1.20  1999/07/09 08:23:06  keil
+ * Fix ISAC lost TX IRQ handling
+ *
+ * Revision 1.19  1999/07/01 08:11:43  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 1.18  1998/11/15 23:54:51  keil
  * changes from 2.0
  *
@@ -69,6 +82,7 @@
 #define __NO_VERSION__
 #include "hisax.h"
 #include "isac.h"
+#include "arcofi.h"
 #include "isdnl1.h"
 #include <linux/interrupt.h>
 
@@ -100,7 +114,7 @@
 static void
 isac_new_ph(struct IsdnCardState *cs)
 {
-	switch (cs->ph_state) {
+	switch (cs->dc.isac.ph_state) {
 		case (ISAC_IND_RS):
 		case (ISAC_IND_EI):
 			ph_command(cs, ISAC_CMD_DUI);
@@ -154,14 +168,10 @@
 		DChannel_proc_rcv(cs);
 	if (test_and_clear_bit(D_XMTBUFREADY, &cs->event))
 		DChannel_proc_xmt(cs);
-	if (test_and_clear_bit(D_RX_MON0, &cs->event))
-		test_and_set_bit(HW_MON0_RX_END, &cs->HW_Flags);
 	if (test_and_clear_bit(D_RX_MON1, &cs->event))
-		test_and_set_bit(HW_MON1_RX_END, &cs->HW_Flags);
-	if (test_and_clear_bit(D_TX_MON0, &cs->event))
-		test_and_set_bit(HW_MON0_TX_END, &cs->HW_Flags);
+		arcofi_fsm(cs, ARCOFI_RX_END, NULL);
 	if (test_and_clear_bit(D_TX_MON1, &cs->event))
-		test_and_set_bit(HW_MON1_TX_END, &cs->HW_Flags);
+		arcofi_fsm(cs, ARCOFI_TX_END, NULL);
 }
 
 void
@@ -226,7 +236,6 @@
 	cs->tx_cnt += count;
 	cs->writeisacfifo(cs, ptr, count);
 	cs->writeisac(cs, ISAC_CMDR, more ? 0x8 : 0xa);
-	restore_flags(flags);
 	if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
 		debugl1(cs, "isac_fill_fifo dbusytimer running");
 		del_timer(&cs->dbusytimer);
@@ -234,6 +243,7 @@
 	init_timer(&cs->dbusytimer);
 	cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
 	add_timer(&cs->dbusytimer);
+	restore_flags(flags);
 	if (cs->debug & L1_DEB_ISAC_FIFO) {
 		char *t = cs->dlog;
 
@@ -283,6 +293,7 @@
 				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);
 				}
@@ -310,7 +321,7 @@
 				isac_fill_fifo(cs);
 				goto afterXPR;
 			} else {
-				dev_kfree_skb(cs->tx_skb);
+				idev_kfree_skb(cs->tx_skb, FREE_WRITE);
 				cs->tx_cnt = 0;
 				cs->tx_skb = NULL;
 			}
@@ -327,9 +338,9 @@
 		if (cs->debug & L1_DEB_ISAC)
 			debugl1(cs, "ISAC CIR0 %02X", exval );
 		if (exval & 2) {
-			cs->ph_state = (exval >> 2) & 0xf;
+			cs->dc.isac.ph_state = (exval >> 2) & 0xf;
 			if (cs->debug & L1_DEB_ISAC)
-				debugl1(cs, "ph_state change %x", cs->ph_state);
+				debugl1(cs, "ph_state change %x", cs->dc.isac.ph_state);
 			isac_sched_event(cs, D_L1STATECHANGE);
 		}
 		if (exval & 1) {
@@ -347,127 +358,147 @@
 		exval = cs->readisac(cs, ISAC_EXIR);
 		if (cs->debug & L1_DEB_WARN)
 			debugl1(cs, "ISAC EXIR %02x", exval);
-		if (exval & 0x04) {
+		if (exval & 0x80) {  /* XMR */
+			debugl1(cs, "ISAC XMR");
+			printk(KERN_WARNING "HiSax: ISAC XMR\n");
+		}
+		if (exval & 0x40) {  /* XDU */
+			debugl1(cs, "ISAC XDU");
+			printk(KERN_WARNING "HiSax: ISAC XDU\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))
+				isac_sched_event(cs, D_CLEARBUSY);
+			if (cs->tx_skb) { /* Restart frame */
+				skb_push(cs->tx_skb, cs->tx_cnt);
+				cs->tx_cnt = 0;
+				isac_fill_fifo(cs);
+			} else {
+				printk(KERN_WARNING "HiSax: ISAC XDU no skb\n");
+				debugl1(cs, "ISAC XDU no skb");
+			}
+		}
+		if (exval & 0x04) {  /* MOS */
 			v1 = cs->readisac(cs, ISAC_MOSR);
 			if (cs->debug & L1_DEB_MONITOR)
 				debugl1(cs, "ISAC MOSR %02x", v1);
 #if ARCOFI_USE
 			if (v1 & 0x08) {
-				if (!cs->mon_rx) {
-					if (!(cs->mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) {
+				if (!cs->dc.isac.mon_rx) {
+					if (!(cs->dc.isac.mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) {
 						if (cs->debug & L1_DEB_WARN)
 							debugl1(cs, "ISAC MON RX out of memory!");
-						cs->mocr &= 0xf0;
-						cs->mocr |= 0x0a;
-						cs->writeisac(cs, ISAC_MOCR, cs->mocr);
+						cs->dc.isac.mocr &= 0xf0;
+						cs->dc.isac.mocr |= 0x0a;
+						cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
 						goto afterMONR0;
 					} else
-						cs->mon_rxp = 0;
+						cs->dc.isac.mon_rxp = 0;
 				}
-				if (cs->mon_rxp >= MAX_MON_FRAME) {
-					cs->mocr &= 0xf0;
-					cs->mocr |= 0x0a;
-					cs->writeisac(cs, ISAC_MOCR, cs->mocr);
-					cs->mon_rxp = 0;
+				if (cs->dc.isac.mon_rxp >= MAX_MON_FRAME) {
+					cs->dc.isac.mocr &= 0xf0;
+					cs->dc.isac.mocr |= 0x0a;
+					cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
+					cs->dc.isac.mon_rxp = 0;
 					if (cs->debug & L1_DEB_WARN)
 						debugl1(cs, "ISAC MON RX overflow!");
 					goto afterMONR0;
 				}
-				cs->mon_rx[cs->mon_rxp++] = cs->readisac(cs, ISAC_MOR0);
+				cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp++] = cs->readisac(cs, ISAC_MOR0);
 				if (cs->debug & L1_DEB_MONITOR)
-					debugl1(cs, "ISAC MOR0 %02x", cs->mon_rx[cs->mon_rxp -1]);
-				if (cs->mon_rxp == 1) {
-					cs->mocr |= 0x04;
-					cs->writeisac(cs, ISAC_MOCR, cs->mocr);
+					debugl1(cs, "ISAC MOR0 %02x", cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp -1]);
+				if (cs->dc.isac.mon_rxp == 1) {
+					cs->dc.isac.mocr |= 0x04;
+					cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
 				}
 			}
 		      afterMONR0:
 			if (v1 & 0x80) {
-				if (!cs->mon_rx) {
-					if (!(cs->mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) {
+				if (!cs->dc.isac.mon_rx) {
+					if (!(cs->dc.isac.mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) {
 						if (cs->debug & L1_DEB_WARN)
 							debugl1(cs, "ISAC MON RX out of memory!");
-						cs->mocr &= 0x0f;
-						cs->mocr |= 0xa0;
-						cs->writeisac(cs, ISAC_MOCR, cs->mocr);
+						cs->dc.isac.mocr &= 0x0f;
+						cs->dc.isac.mocr |= 0xa0;
+						cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
 						goto afterMONR1;
 					} else
-						cs->mon_rxp = 0;
+						cs->dc.isac.mon_rxp = 0;
 				}
-				if (cs->mon_rxp >= MAX_MON_FRAME) {
-					cs->mocr &= 0x0f;
-					cs->mocr |= 0xa0;
-					cs->writeisac(cs, ISAC_MOCR, cs->mocr);
-					cs->mon_rxp = 0;
+				if (cs->dc.isac.mon_rxp >= MAX_MON_FRAME) {
+					cs->dc.isac.mocr &= 0x0f;
+					cs->dc.isac.mocr |= 0xa0;
+					cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
+					cs->dc.isac.mon_rxp = 0;
 					if (cs->debug & L1_DEB_WARN)
 						debugl1(cs, "ISAC MON RX overflow!");
 					goto afterMONR1;
 				}
-				cs->mon_rx[cs->mon_rxp++] = cs->readisac(cs, ISAC_MOR1);
+				cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp++] = cs->readisac(cs, ISAC_MOR1);
 				if (cs->debug & L1_DEB_MONITOR)
-					debugl1(cs, "ISAC MOR1 %02x", cs->mon_rx[cs->mon_rxp -1]);
-				cs->mocr |= 0x40;
-				cs->writeisac(cs, ISAC_MOCR, cs->mocr);
+					debugl1(cs, "ISAC MOR1 %02x", cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp -1]);
+				cs->dc.isac.mocr |= 0x40;
+				cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
 			}
 		      afterMONR1:
 			if (v1 & 0x04) {
-				cs->mocr &= 0xf0;
-				cs->writeisac(cs, ISAC_MOCR, cs->mocr);
-				cs->mocr |= 0x0a;
-				cs->writeisac(cs, ISAC_MOCR, cs->mocr);
-				test_and_set_bit(HW_MON0_RX_END, &cs->HW_Flags);
+				cs->dc.isac.mocr &= 0xf0;
+				cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
+				cs->dc.isac.mocr |= 0x0a;
+				cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
+				isac_sched_event(cs, D_RX_MON0);
 			}
 			if (v1 & 0x40) {
-				cs->mocr &= 0x0f;
-				cs->writeisac(cs, ISAC_MOCR, cs->mocr);
-				cs->mocr |= 0xa0;
-				cs->writeisac(cs, ISAC_MOCR, cs->mocr);
-				test_and_set_bit(HW_MON1_RX_END, &cs->HW_Flags);
+				cs->dc.isac.mocr &= 0x0f;
+				cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
+				cs->dc.isac.mocr |= 0xa0;
+				cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
+				isac_sched_event(cs, D_RX_MON1);
 			}
 			if (v1 & 0x02) {
-				if ((!cs->mon_tx) || (cs->mon_txc && 
-					(cs->mon_txp >= cs->mon_txc) && 
+				if ((!cs->dc.isac.mon_tx) || (cs->dc.isac.mon_txc && 
+					(cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc) && 
 					!(v1 & 0x08))) {
-					cs->mocr &= 0xf0;
-					cs->writeisac(cs, ISAC_MOCR, cs->mocr);
-					cs->mocr |= 0x0a;
-					cs->writeisac(cs, ISAC_MOCR, cs->mocr);
-					if (cs->mon_txc &&
-						(cs->mon_txp >= cs->mon_txc))
-						test_and_set_bit(HW_MON0_TX_END, &cs->HW_Flags);
+					cs->dc.isac.mocr &= 0xf0;
+					cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
+					cs->dc.isac.mocr |= 0x0a;
+					cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
+					if (cs->dc.isac.mon_txc &&
+						(cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc))
+						isac_sched_event(cs, D_TX_MON0);
 					goto AfterMOX0;
 				}
-				if (cs->mon_txc && (cs->mon_txp >= cs->mon_txc)) {
-					test_and_set_bit(HW_MON0_TX_END, &cs->HW_Flags);
+				if (cs->dc.isac.mon_txc && (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc)) {
+					isac_sched_event(cs, D_TX_MON0);
 					goto AfterMOX0;
 				}
 				cs->writeisac(cs, ISAC_MOX0,
-					cs->mon_tx[cs->mon_txp++]);
+					cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]);
 				if (cs->debug & L1_DEB_MONITOR)
-					debugl1(cs, "ISAC %02x -> MOX0", cs->mon_tx[cs->mon_txp -1]);
+					debugl1(cs, "ISAC %02x -> MOX0", cs->dc.isac.mon_tx[cs->dc.isac.mon_txp -1]);
 			}
 		      AfterMOX0:
 			if (v1 & 0x20) {
-				if ((!cs->mon_tx) || (cs->mon_txc && 
-					(cs->mon_txp >= cs->mon_txc) && 
+				if ((!cs->dc.isac.mon_tx) || (cs->dc.isac.mon_txc && 
+					(cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc) && 
 					!(v1 & 0x80))) {
-					cs->mocr &= 0x0f;
-					cs->writeisac(cs, ISAC_MOCR, cs->mocr);
-					cs->mocr |= 0xa0;
-					cs->writeisac(cs, ISAC_MOCR, cs->mocr);
-					if (cs->mon_txc &&
-						(cs->mon_txp >= cs->mon_txc))
-						test_and_set_bit(HW_MON1_TX_END, &cs->HW_Flags);
+					cs->dc.isac.mocr &= 0x0f;
+					cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
+					cs->dc.isac.mocr |= 0xa0;
+					cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
+					if (cs->dc.isac.mon_txc &&
+						(cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc))
+						isac_sched_event(cs, D_TX_MON1);
 					goto AfterMOX1;
 				}
-				if (cs->mon_txc && (cs->mon_txp >= cs->mon_txc)) {
-					test_and_set_bit(HW_MON1_TX_END, &cs->HW_Flags);
+				if (cs->dc.isac.mon_txc && (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc)) {
+					isac_sched_event(cs, D_TX_MON1);
 					goto AfterMOX1;
 				}
 				cs->writeisac(cs, ISAC_MOX1,
-					cs->mon_tx[cs->mon_txp++]);
+					cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]);
 				if (cs->debug & L1_DEB_MONITOR)
-					debugl1(cs, "ISAC %02x -> MOX1", cs->mon_tx[cs->mon_txp -1]);
+					debugl1(cs, "ISAC %02x -> MOX1", cs->dc.isac.mon_tx[cs->dc.isac.mon_txp -1]);
 			}
 		      AfterMOX1:
 #endif
@@ -535,9 +566,9 @@
 				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 			break;
 		case (HW_RESET | REQUEST):
-			if ((cs->ph_state == ISAC_IND_EI) ||
-				(cs->ph_state == ISAC_IND_DR) ||
-				(cs->ph_state == ISAC_IND_RS))
+			if ((cs->dc.isac.ph_state == ISAC_IND_EI) ||
+				(cs->dc.isac.ph_state == ISAC_IND_DR) ||
+				(cs->dc.isac.ph_state == ISAC_IND_RS))
 			        ph_command(cs, ISAC_CMD_TIM);
 			else
 				ph_command(cs, ISAC_CMD_RS);
@@ -576,7 +607,7 @@
 			discard_queue(&cs->rq);
 			discard_queue(&cs->sq);
 			if (cs->tx_skb) {
-				dev_kfree_skb(cs->tx_skb);
+				idev_kfree_skb(cs->tx_skb, FREE_WRITE);
 				cs->tx_skb = NULL;
 			}
 			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
@@ -597,27 +628,50 @@
 	st->l1.l1hw = ISAC_l1hw;
 }
 
+void 
+DC_Close_isac(struct IsdnCardState *cs) {
+	if (cs->dc.isac.mon_rx) {
+		kfree(cs->dc.isac.mon_rx);
+		cs->dc.isac.mon_rx = NULL;
+	}
+	if (cs->dc.isac.mon_tx) {
+		kfree(cs->dc.isac.mon_tx);
+		cs->dc.isac.mon_tx = NULL;
+	}
+}
+
 static void
 dbusy_timer_handler(struct IsdnCardState *cs)
 {
 	struct PStack *stptr;
-	int	val;
+	int	rbch, star;
 
 	if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
-		if (cs->debug) {
-			debugl1(cs, "D-Channel Busy");
-			val = cs->readisac(cs, ISAC_RBCH);
-			if (val & ISAC_RBCH_XAC)
-				debugl1(cs, "ISAC XAC");
-			else
-				debugl1(cs, "ISAC No XAC");
-		}
-		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;
+		rbch = cs->readisac(cs, ISAC_RBCH);
+		star = cs->readisac(cs, ISAC_STAR);
+		if (cs->debug) 
+			debugl1(cs, "D-Channel Busy RBCH %02x STAR %02x",
+				rbch, star);
+		if (rbch & ISAC_RBCH_XAC) { /* 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) {
+				idev_kfree_skb(cs->tx_skb, FREE_WRITE);
+				cs->tx_cnt = 0;
+				cs->tx_skb = NULL;
+			} else {
+				printk(KERN_WARNING "HiSax: ISAC D-Channel Busy no skb\n");
+				debugl1(cs, "D-Channel Busy no skb");
+			}
+			cs->writeisac(cs, ISAC_CMDR, 0x01); /* Transmitter reset */
+			cs->irq_func(cs->irq, cs, NULL);
 		}
 	}
 }
@@ -627,11 +681,14 @@
 {
 	cs->tqueue.routine = (void *) (void *) isac_bh;
 	cs->setstack_d = setstack_isac;
+	cs->DC_Close = DC_Close_isac;
+	cs->dc.isac.mon_tx = NULL;
+	cs->dc.isac.mon_rx = NULL;
 	cs->dbusytimer.function = (void *) dbusy_timer_handler;
 	cs->dbusytimer.data = (long) cs;
 	init_timer(&cs->dbusytimer);
   	cs->writeisac(cs, ISAC_MASK, 0xff);
-  	cs->mocr = 0xaa;
+  	cs->dc.isac.mocr = 0xaa;
 	if (test_bit(HW_IOM1, &cs->HW_Flags)) {
 		/* IOM 1 Mode */
 		cs->writeisac(cs, ISAC_ADF2, 0x0);
@@ -641,7 +698,9 @@
 		cs->writeisac(cs, ISAC_MODE, 0xc9);
 	} else {
 		/* IOM 2 Mode */
-		cs->writeisac(cs, ISAC_ADF2, 0x80);
+		if (!cs->dc.isac.adf2)
+			cs->dc.isac.adf2 = 0x80;
+		cs->writeisac(cs, ISAC_ADF2, cs->dc.isac.adf2);
 		cs->writeisac(cs, ISAC_SQXR, 0x2f);
 		cs->writeisac(cs, ISAC_SPCR, 0x00);
 		cs->writeisac(cs, ISAC_STCR, 0x70);
@@ -672,7 +731,7 @@
 	}
 	val = cs->readisac(cs, ISAC_CIR0);
 	debugl1(cs, "ISAC CIR0 %x", val);
-	cs->ph_state = (val >> 2) & 0xf;
+	cs->dc.isac.ph_state = (val >> 2) & 0xf;
 	isac_sched_event(cs, D_L1STATECHANGE);
 	/* Disable all IRQ */
 	cs->writeisac(cs, ISAC_MASK, 0xFF);
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/isar.c linux/drivers/isdn/hisax/isar.c
--- v2.3.13/linux/drivers/isdn/hisax/isar.c	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/hisax/isar.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: isar.c,v 1.2 1998/11/15 23:54:53 keil Exp $
+/* $Id: isar.c,v 1.4 1999/08/05 20:43:18 keil Exp $
 
  * isar.c   ISAR (Siemens PSB 7110) specific routines
  *
@@ -6,6 +6,12 @@
  *
  *
  * $Log: isar.c,v $
+ * Revision 1.4  1999/08/05 20:43:18  keil
+ * ISAR analog modem support
+ *
+ * Revision 1.3  1999/07/01 08:11:45  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 1.2  1998/11/15 23:54:53  keil
  * changes from 2.0
  *
@@ -425,7 +431,9 @@
 		cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
 		break;
 	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);
@@ -459,6 +467,7 @@
 				} 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);
@@ -512,6 +521,7 @@
 		printk(KERN_ERR"isar_fill_fifo wrong mode 0\n");
 		break;
 	case L1_MODE_TRANS:
+	case L1_MODE_V32:
 		if (!sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA,
 			0, count, ptr)) {
 			if (cs->debug)
@@ -557,7 +567,7 @@
 			if (bcs->st->lli.l1writewakeup &&
 				(PACKET_NOACK != bcs->tx_skb->pkt_type))
 					bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.isar.txcnt);
-			dev_kfree_skb(bcs->tx_skb);
+			idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
 			bcs->hw.isar.txcnt = 0; 
 			bcs->tx_skb = NULL;
 		}
@@ -593,6 +603,136 @@
 	}
 	
 }
+const char *dmril[] = {"NO SPEED", "1200/75", "NODEF2", "75/1200", "NODEF4",
+			"300", "600", "1200", "2400", "4800", "7200",
+			"9600nt", "9600t", "12000", "14400", "WRONG"};
+const char *dmrim[] = {"NO MOD", "NO DEF", "V32/V32b", "V22", "V21",
+			"Bell103", "V23", "Bell202", "V17", "V29", "V27ter"};
+
+static void
+isar_pump_status_rsp(struct BCState *bcs, struct isar_reg *ireg) {
+	struct IsdnCardState *cs = bcs->cs;
+	u_char ril = ireg->par[0];
+	u_char rim;
+
+	if (!test_and_clear_bit(ISAR_RATE_REQ, &bcs->hw.isar.reg->Flags))
+		return; 
+	if (ril > 14) {
+		if (cs->debug & L1_DEB_WARN)
+			debugl1(cs, "wrong pstrsp ril=%d",ril);
+		ril = 15;
+	}
+	switch(ireg->par[1]) {
+		case 0:
+			rim = 0;
+			break;
+		case 0x20:
+			rim = 2;
+			break;
+		case 0x40:
+			rim = 3;
+			break;
+		case 0x41:
+			rim = 4;
+			break;
+		case 0x51:
+			rim = 5;
+			break;
+		case 0x61:
+			rim = 6;
+			break;
+		case 0x71:
+			rim = 7;
+			break;
+		case 0x82:
+			rim = 8;
+			break;
+		case 0x92:
+			rim = 9;
+			break;
+		case 0xa2:
+			rim = 10;
+			break;
+		default:
+			rim = 1;
+			break;
+	}
+	sprintf(bcs->hw.isar.conmsg,"%s %s", dmril[ril], dmrim[rim]);
+	bcs->conmsg = bcs->hw.isar.conmsg;
+	if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "pump strsp %s", bcs->conmsg);
+}
+
+static void
+isar_pump_status_ev(struct BCState *bcs, u_char devt) {
+	struct IsdnCardState *cs = bcs->cs;
+	u_char dps = SET_DPS(bcs->hw.isar.dpath);
+
+	switch(devt) {
+		case PSEV_10MS_TIMER:
+			if (cs->debug & L1_DEB_HSCX)
+				debugl1(cs, "pump stev TIMER");
+			break;
+		case PSEV_CON_ON:
+			if (cs->debug & L1_DEB_HSCX)
+				debugl1(cs, "pump stev CONNECT");
+			l1_msg_b(bcs->st, PH_ACTIVATE | REQUEST, NULL);
+			break;
+		case PSEV_CON_OFF:
+			if (cs->debug & L1_DEB_HSCX)
+				debugl1(cs, "pump stev NO CONNECT");
+			sendmsg(cs, dps | ISAR_HIS_PSTREQ, 0, 0, NULL);
+			l1_msg_b(bcs->st, PH_DEACTIVATE | REQUEST, NULL);
+			break;
+		case PSEV_V24_OFF:
+			if (cs->debug & L1_DEB_HSCX)
+				debugl1(cs, "pump stev V24 OFF");
+			break;
+		case PSEV_CTS_ON:
+			if (cs->debug & L1_DEB_HSCX)
+				debugl1(cs, "pump stev CTS ON");
+			break;
+		case PSEV_CTS_OFF:
+			if (cs->debug & L1_DEB_HSCX)
+				debugl1(cs, "pump stev CTS OFF");
+			break;
+		case PSEV_DCD_ON:
+			if (cs->debug & L1_DEB_HSCX)
+				debugl1(cs, "pump stev CARRIER ON");
+			test_and_set_bit(ISAR_RATE_REQ, &bcs->hw.isar.reg->Flags); 
+			sendmsg(cs, dps | ISAR_HIS_PSTREQ, 0, 0, NULL);
+			break;
+		case PSEV_DCD_OFF:
+			if (cs->debug & L1_DEB_HSCX)
+				debugl1(cs, "pump stev CARRIER OFF");
+			break;
+		case PSEV_DSR_ON:
+			if (cs->debug & L1_DEB_HSCX)
+				debugl1(cs, "pump stev DSR ON");
+//			sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, 0xCF, 0, NULL);
+			break;
+		case PSEV_DSR_OFF:
+			if (cs->debug & L1_DEB_HSCX)
+				debugl1(cs, "pump stev DSR_OFF");
+			break;
+		case PSEV_REM_RET:
+			if (cs->debug & L1_DEB_HSCX)
+				debugl1(cs, "pump stev REMOTE RETRAIN");
+			break;
+		case PSEV_REM_REN:
+			if (cs->debug & L1_DEB_HSCX)
+				debugl1(cs, "pump stev REMOTE RENEGOTIATE");
+			break;
+		case PSEV_GSTN_CLR:
+			if (cs->debug & L1_DEB_HSCX)
+				debugl1(cs, "pump stev GSTN CLEAR", devt);
+			break;
+		default:
+			if (cs->debug & L1_DEB_HSCX)
+				debugl1(cs, "unknown pump stev %x", devt);
+			break;
+	}
+}
 
 static char debbuf[64];
 
@@ -628,10 +768,31 @@
 			if (cs->debug & L1_DEB_WARN)
 				debugl1(cs, "Buffer STEV dpath%d msb(%x)",
 					ireg->iis>>6, ireg->cmsb);
+		case ISAR_IIS_PSTEV:
+			if ((bcs = sel_bcs_isar(cs, ireg->iis >> 6))) {
+				rcv_mbox(cs, ireg, (u_char *)ireg->par);
+				isar_pump_status_ev(bcs, ireg->cmsb);
+			} else {
+				debugl1(cs, "isar spurious IIS_PSTEV %x/%x/%x",
+					ireg->iis, ireg->cmsb, ireg->clsb);
+				printk(KERN_WARNING"isar spurious IIS_PSTEV %x/%x/%x\n",
+					ireg->iis, ireg->cmsb, ireg->clsb);
+				cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+			}
 			break;
-		case ISAR_IIS_DIAG:
 		case ISAR_IIS_PSTRSP:
-		case ISAR_IIS_PSTEV:
+			if ((bcs = sel_bcs_isar(cs, ireg->iis >> 6))) {
+				rcv_mbox(cs, ireg, (u_char *)ireg->par);
+				isar_pump_status_rsp(bcs, ireg);
+			} else {
+				debugl1(cs, "isar spurious IIS_PSTRSP %x/%x/%x",
+					ireg->iis, ireg->cmsb, ireg->clsb);
+				printk(KERN_WARNING"isar spurious IIS_PSTRSP %x/%x/%x\n",
+					ireg->iis, ireg->cmsb, ireg->clsb);
+				cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+			}
+			break;
+		case ISAR_IIS_DIAG:
 		case ISAR_IIS_BSTRSP:
 		case ISAR_IIS_IOM2RSP:
 			rcv_mbox(cs, ireg, (u_char *)ireg->par);
@@ -659,7 +820,8 @@
 setup_pump(struct BCState *bcs) {
 	struct IsdnCardState *cs = bcs->cs;
 	u_char dps = SET_DPS(bcs->hw.isar.dpath);
-	
+	u_char ctrl, param[6];
+
 	switch (bcs->mode) {
 		case L1_MODE_NULL:
 		case L1_MODE_TRANS:
@@ -670,6 +832,44 @@
 						bcs->hw.isar.dpath);
 			}
 			break;
+		case L1_MODE_V32:
+			ctrl = PMOD_DATAMODEM;
+			if (test_bit(BC_FLG_ORIG, &bcs->Flag)) {
+				ctrl |= PCTRL_ORIG;
+				param[5] = PV32P6_CTN;
+			} else {
+				param[5] = PV32P6_ATN;
+			}
+			param[0] = 11; /* 11 db */
+//			param[1] = PV32P2_V22A | PV32P2_V22B | PV32P2_V21; 
+			param[1] = PV32P2_V22A; 
+//			param[2] = PV32P3_AMOD | PV32P3_V32B;
+			param[2] = PV32P3_AMOD;
+			param[3] = PV32P4_48;
+			param[4] = PV32P5_48;
+//			param[3] = PV32P4_UT144;
+//			param[4] = PV32P5_UT144;
+			if (!sendmsg(cs, dps | ISAR_HIS_PUMPCFG, ctrl, 6, param)) {
+				if (cs->debug)
+					debugl1(cs, "isar pump datamodem cfg dp%d failed",
+						bcs->hw.isar.dpath);
+			}
+			break;
+		case L1_MODE_FAX:
+			ctrl = PMOD_FAX;
+			if (test_bit(BC_FLG_ORIG, &bcs->Flag)) {
+				ctrl |= PCTRL_ORIG;
+				param[1] = PFAXP2_CTN;
+			} else {
+				param[1] = PFAXP2_ATN;
+			}
+			param[0] = 8; /* 8 db */
+			if (!sendmsg(cs, dps | ISAR_HIS_PUMPCFG, ctrl, 2, param)) {
+				if (cs->debug)
+					debugl1(cs, "isar pump faxmodem cfg dp%d failed",
+						bcs->hw.isar.dpath);
+			}
+			break;
 	}
 	if (!sendmsg(cs, dps | ISAR_HIS_PSTREQ, 0, 0, NULL)) {
 		if (cs->debug)
@@ -682,6 +882,7 @@
 setup_sart(struct BCState *bcs) {
 	struct IsdnCardState *cs = bcs->cs;
 	u_char dps = SET_DPS(bcs->hw.isar.dpath);
+	u_char ctrl, param[2];
 	
 	switch (bcs->mode) {
 		case L1_MODE_NULL:
@@ -701,7 +902,17 @@
 		case L1_MODE_HDLC:
 			if (!sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_HDLC, 1, "\0")) {
 				if (cs->debug)
-					debugl1(cs, "isar sart binary dp%d failed",
+					debugl1(cs, "isar sart hdlc dp%d failed",
+						bcs->hw.isar.dpath);
+			}
+			break;
+		case L1_MODE_V32:
+			ctrl = SMODE_V14 | SCTRL_HDMC_BOTH;
+			param[0] = S_P1_CHS_8;
+			param[1] = S_P2_BFT_DEF;
+			if (!sendmsg(cs, dps | ISAR_HIS_SARTCFG, ctrl, 2, param)) {
+				if (cs->debug)
+					debugl1(cs, "isar sart v14 dp%d failed",
 						bcs->hw.isar.dpath);
 			}
 			break;
@@ -717,18 +928,22 @@
 setup_iom2(struct BCState *bcs) {
 	struct IsdnCardState *cs = bcs->cs;
 	u_char dps = SET_DPS(bcs->hw.isar.dpath);
-	u_char cmsb = 0, msg[5] = {0x10,0,0,0,0};
+	u_char cmsb = IOM_CTRL_ENA, msg[5] = {IOM_P1_TXD,0,0,0,0};
 	
+	if (bcs->channel)
+		msg[1] = msg[3] = 1;
 	switch (bcs->mode) {
 		case L1_MODE_NULL:
+			cmsb = 0;
 			/* dummy slot */
 			msg[1] = msg[3] = bcs->hw.isar.dpath + 2;
 			break;
 		case L1_MODE_TRANS:
 		case L1_MODE_HDLC:
-			cmsb = 0x80;
-			if (bcs->channel)
-				msg[1] = msg[3] = 1;
+			break;
+		case L1_MODE_V32:
+		case L1_MODE_FAX:
+			cmsb |= IOM_CTRL_ALAW | IOM_CTRL_RCV;
 			break;
 	}
 	if (!sendmsg(cs, dps | ISAR_HIS_IOM2CFG, cmsb, 5, msg)) {
@@ -763,7 +978,18 @@
 					&bcs->hw.isar.reg->Flags))
 					bcs->hw.isar.dpath = 1;
 				else {
-					printk(KERN_ERR"isar modeisar both pathes in use\n");
+					printk(KERN_WARNING"isar modeisar both pathes in use\n");
+					return(1);
+				}
+				break;
+			case L1_MODE_V32:
+				/* only datapath 1 */
+				if (!test_and_set_bit(ISAR_DP1_USE, 
+					&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");
 					return(1);
 				}
 				break;
@@ -774,8 +1000,8 @@
 			bcs->hw.isar.dpath, bcs->mode, mode, bc);
 	bcs->mode = mode;
 	setup_pump(bcs);
-	setup_sart(bcs);
 	setup_iom2(bcs);
+	setup_sart(bcs);
 	if (bcs->mode == L1_MODE_NULL) {
 		/* Clear resources */
 		if (bcs->hw.isar.dpath == 1)
@@ -853,8 +1079,24 @@
 			break;
 		case (PH_ACTIVATE | REQUEST):
 			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			modeisar(st->l1.bcs, st->l1.mode, st->l1.bc);
-			l1_msg_b(st, pr, arg);
+			st->l1.bcs->hw.isar.conmsg[0] = 0;
+			if (test_bit(FLG_ORIG, &st->l2.flag))
+				test_and_set_bit(BC_FLG_ORIG, &st->l1.bcs->Flag);
+			else
+				test_and_clear_bit(BC_FLG_ORIG, &st->l1.bcs->Flag);
+			switch(st->l1.mode) {
+				case L1_MODE_TRANS:
+				case L1_MODE_HDLC:
+					if (modeisar(st->l1.bcs, st->l1.mode, st->l1.bc))
+						l1_msg_b(st, PH_DEACTIVATE | REQUEST, arg);
+					else
+						l1_msg_b(st, PH_ACTIVATE | REQUEST, arg);
+					break;
+				case L1_MODE_V32:
+					if (modeisar(st->l1.bcs, st->l1.mode, st->l1.bc))
+						l1_msg_b(st, PH_DEACTIVATE | REQUEST, arg);
+					break;
+			}
 			break;
 		case (PH_DEACTIVATE | REQUEST):
 			l1_msg_b(st, pr, arg);
@@ -882,7 +1124,7 @@
 		discard_queue(&bcs->rqueue);
 		discard_queue(&bcs->squeue);
 		if (bcs->tx_skb) {
-			dev_kfree_skb(bcs->tx_skb);
+			idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
 			bcs->tx_skb = NULL;
 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 			if (bcs->cs->debug & L1_DEB_HSCX)
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/isar.h linux/drivers/isdn/hisax/isar.h
--- v2.3.13/linux/drivers/isdn/hisax/isar.h	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/hisax/isar.h	Thu Aug 12 09:42:33 1999
@@ -1,10 +1,16 @@
-/* $Id: isar.h,v 1.2 1998/11/15 23:54:54 keil Exp $
+/* $Id: isar.h,v 1.4 1999/08/05 20:43:20 keil Exp $
  * isar.h   ISAR (Siemens PSB 7110) specific defines
  *
  * Author Karsten Keil (keil@isdn4linux.de)
  *
  *
  * $Log: isar.h,v $
+ * Revision 1.4  1999/08/05 20:43:20  keil
+ * ISAR analog modem support
+ *
+ * Revision 1.3  1999/07/01 08:11:46  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 1.2  1998/11/15 23:54:54  keil
  * changes from 2.0
  *
@@ -36,8 +42,10 @@
 #define ISAR_HIS_P12CFG	0x24
 #define ISAR_HIS_SARTCFG	0x25	
 #define ISAR_HIS_PUMPCFG	0x26	
+#define ISAR_HIS_PUMPCTRL	0x2a	
 #define ISAR_HIS_IOM2CFG	0x27
 #define ISAR_HIS_IOM2REQ	0x07
+#define ISAR_HIS_IOM2CTRL	0x2b
 #define ISAR_HIS_BSTREQ	0x0c
 #define ISAR_HIS_PSTREQ	0x0e
 #define ISAR_HIS_SDATA	0x20
@@ -66,12 +74,97 @@
 
 #define ISAR_DP1_USE	1
 #define ISAR_DP2_USE	2
+#define ISAR_RATE_REQ	3
 
+#define PMOD_DISABLE	0
+#define PMOD_FAX	1
+#define PMOD_DATAMODEM	2
+#define PMOD_HALFDUPLEX	3
+#define PMOD_V110	4
+#define PMOD_DTMF	5
+#define PMOD_DTMF_TRANS	6
 #define PMOD_BYPASS	7
 
+#define PCTRL_ORIG	0x80
+#define PV32P2_V23R	0x40
+#define PV32P2_V22A	0x20
+#define PV32P2_V22B	0x10
+#define PV32P2_V22C	0x08
+#define PV32P2_V21	0x02
+#define PV32P2_BEL	0x01
+
+#define PV32P3_AMOD	0x80
+#define PV32P3_V32B	0x02
+#define PV32P4_48	0x05
+#define PV32P5_48	0x11
+#define PV32P4_UT48	0x0d
+#define PV32P5_UT48	0x11
+#define PV32P4_96	0x03
+#define PV32P5_96	0x11
+#define PV32P4_UT96	0x0f
+#define PV32P5_UT96	0x11
+#define PV32P4_B96	0x0b
+#define PV32P5_B96	0x91
+#define PV32P4_UTB96	0x0f
+#define PV32P5_UTB96	0xd1
+#define PV32P4_120	0x09
+#define PV32P5_120	0xb1
+#define PV32P4_UT120	0x0f
+#define PV32P5_UT120	0xf1
+#define PV32P4_144	0x09
+#define PV32P5_144	0x99
+#define PV32P4_UT144	0x0f
+#define PV32P5_UT144	0xf9
+#define PV32P6_CTN	0x01
+#define PV32P6_ATN	0x02
+#define PFAXP2_CTN	0x01
+#define PFAXP2_ATN	0x04
+
+#define PSEV_10MS_TIMER	0x02
+#define PSEV_CON_ON	0x18
+#define PSEV_CON_OFF	0x19
+#define PSEV_V24_OFF	0x20
+#define PSEV_CTS_ON	0x21
+#define PSEV_CTS_OFF	0x22
+#define PSEV_DCD_ON	0x23
+#define PSEV_DCD_OFF	0x24
+#define PSEV_DSR_ON	0x25
+#define PSEV_DSR_OFF	0x26
+#define PSEV_REM_RET	0xcc
+#define PSEV_REM_REN	0xcd
+#define PSEV_GSTN_CLR	0xd4
+
+#define PCTRL_LOC_RET	0xcf
+#define PCTRL_LOC_REN	0xce
+
 #define SMODE_DISABLE	0
+#define SMODE_V14	2
 #define SMODE_HDLC	3
 #define SMODE_BINARY	4
+#define SMODE_FSK_V14	5
+
+#define SCTRL_HDMC_BOTH	0x00
+#define SCTRL_HDMC_DTX	0x80
+#define SCTRL_HDMC_DRX	0x40
+#define S_P1_OVSP	0x40
+#define S_P1_SNP	0x20
+#define S_P1_EOP	0x10
+#define S_P1_EDP	0x08
+#define S_P1_NSB	0x04
+#define S_P1_CHS_8	0x03
+#define S_P1_CHS_7	0x02
+#define S_P1_CHS_6	0x01
+#define S_P1_CHS_5	0x00
+
+#define S_P2_BFT_DEF	30
+
+#define IOM_CTRL_ENA	0x80
+#define IOM_CTRL_NOPCM	0x00
+#define IOM_CTRL_ALAW	0x02
+#define IOM_CTRL_ULAW	0x04
+#define IOM_CTRL_RCV	0x01
+
+#define IOM_P1_TXD	0x10
 
 #define HDLC_FED	0x40
 #define HDLC_FSD	0x20
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/isdnl1.c linux/drivers/isdn/hisax/isdnl1.c
--- v2.3.13/linux/drivers/isdn/hisax/isdnl1.c	Wed May 26 16:55:40 1999
+++ linux/drivers/isdn/hisax/isdnl1.c	Sun Aug 15 11:49:08 1999
@@ -1,4 +1,4 @@
-/* $Id: isdnl1.c,v 2.31 1998/11/15 23:54:56 keil Exp $
+/* $Id: isdnl1.c,v 2.34 1999/07/09 13:50:15 keil Exp $
 
  * isdnl1.c     common low level stuff for Siemens Chipsetbased isdn cards
  *              based on the teles driver from Jan den Ouden
@@ -15,6 +15,15 @@
  *
  *
  * $Log: isdnl1.c,v $
+ * Revision 2.34  1999/07/09 13:50:15  keil
+ * remove unused variable
+ *
+ * Revision 2.33  1999/07/09 13:34:33  keil
+ * remove debug code
+ *
+ * Revision 2.32  1999/07/01 08:11:47  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 2.31  1998/11/15 23:54:56  keil
  * changes from 2.0
  *
@@ -120,7 +129,7 @@
  *
  */
 
-const char *l1_revision = "$Revision: 2.31 $";
+const char *l1_revision = "$Revision: 2.34 $";
 
 #define __NO_VERSION__
 #include "hisax.h"
@@ -298,9 +307,18 @@
 			Logl2Frame(cs, skb, "PH_DATA", 1);
 #endif
 		stptr = cs->stlist;
+		if (skb->len<3) {
+			debugl1(cs, "D-channel frame too short(%d)",skb->len);
+			idev_kfree_skb(skb, FREE_READ);
+			return;
+		}
+		if ((skb->data[0] & 1) || !(skb->data[1] &1)) {
+			debugl1(cs, "D-channel frame wrong EA0/EA1");
+			idev_kfree_skb(skb, FREE_READ);
+			return;
+		}
 		sapi = skb->data[0] >> 2;
 		tei = skb->data[1] >> 1;
-
 		if (cs->debug & DEB_DLOG_HEX)
 			LogFrame(cs, skb->data, skb->len);
 		if (cs->debug & DEB_DLOG_VERBOSE)
@@ -323,7 +341,7 @@
 					stptr = stptr->next;
 				}
 			}
-			dev_kfree_skb(skb);
+			idev_kfree_skb(skb, FREE_READ);
 		} else if (sapi == CTRL_SAPI) { /* sapi 0 */
 			found = 0;
 			while (stptr != NULL)
@@ -334,7 +352,7 @@
 				} else
 					stptr = stptr->next;
 			if (!found)
-				dev_kfree_skb(skb);
+				idev_kfree_skb(skb, FREE_READ);
 		}
 	}
 }
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/isdnl2.c linux/drivers/isdn/hisax/isdnl2.c
--- v2.3.13/linux/drivers/isdn/hisax/isdnl2.c	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/hisax/isdnl2.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: isdnl2.c,v 2.16 1998/11/15 23:55:01 keil Exp $
+/* $Id: isdnl2.c,v 2.19 1999/08/05 20:40:26 keil Exp $
 
  * Author       Karsten Keil (keil@isdn4linux.de)
  *              based on the teles driver from Jan den Ouden
@@ -11,6 +11,15 @@
  *              Fritz Elfert
  *
  * $Log: isdnl2.c,v $
+ * Revision 2.19  1999/08/05 20:40:26  keil
+ * Fix interlayer communication
+ *
+ * Revision 2.18  1999/07/21 14:46:16  keil
+ * changes from EICON certification
+ *
+ * Revision 2.17  1999/07/01 08:11:50  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 2.16  1998/11/15 23:55:01  keil
  * changes from 2.0
  *
@@ -71,7 +80,7 @@
 #include "hisax.h"
 #include "isdnl2.h"
 
-const char *l2_revision = "$Revision: 2.16 $";
+const char *l2_revision = "$Revision: 2.19 $";
 
 static void l2m_debug(struct FsmInst *fi, char *fmt, ...);
 
@@ -106,7 +115,7 @@
 
 enum {
 	EV_L2_UI,
-	EV_L2_SABMX,
+	EV_L2_SABME,
 	EV_L2_DISC,
 	EV_L2_DM,
 	EV_L2_UA,
@@ -116,22 +125,25 @@
 	EV_L2_DL_DATA,
 	EV_L2_ACK_PULL,
 	EV_L2_DL_UNIT_DATA,
-	EV_L2_DL_ESTABLISH,
-	EV_L2_DL_RELEASE,
+	EV_L2_DL_ESTABLISH_REQ,
+	EV_L2_DL_RELEASE_REQ,
 	EV_L2_MDL_ASSIGN,
 	EV_L2_MDL_REMOVE,
 	EV_L2_MDL_ERROR,
 	EV_L1_DEACTIVATE,
 	EV_L2_T200,
 	EV_L2_T203,
+	EV_L2_SET_OWN_BUSY,
+	EV_L2_CLEAR_OWN_BUSY,
+	EV_L2_FRAME_ERROR,
 };
 
-#define L2_EVENT_COUNT (EV_L2_T203+1)
+#define L2_EVENT_COUNT (EV_L2_FRAME_ERROR+1)
 
 static char *strL2Event[] =
 {
 	"EV_L2_UI",
-	"EV_L2_SABMX",
+	"EV_L2_SABME",
 	"EV_L2_DISC",
 	"EV_L2_DM",
 	"EV_L2_UA",
@@ -141,19 +153,35 @@
 	"EV_L2_DL_DATA",
 	"EV_L2_ACK_PULL",
 	"EV_L2_DL_UNIT_DATA",
-	"EV_L2_DL_ESTABLISH",
-	"EV_L2_DL_RELEASE",
+	"EV_L2_DL_ESTABLISH_REQ",
+	"EV_L2_DL_RELEASE_REQ",
 	"EV_L2_MDL_ASSIGN",
 	"EV_L2_MDL_REMOVE",
 	"EV_L2_MDL_ERROR",
 	"EV_L1_DEACTIVATE",
 	"EV_L2_T200",
 	"EV_L2_T203",
+	"EV_L2_SET_OWN_BUSY",
+	"EV_L2_CLEAR_OWN_BUSY",
+	"EV_L2_FRAME_ERROR",
 };
 
 static int l2addrsize(struct Layer2 *l2);
 
 static void
+set_peer_busy(struct Layer2 *l2) {
+	test_and_set_bit(FLG_PEER_BUSY, &l2->flag);
+	if (skb_queue_len(&l2->i_queue) || skb_queue_len(&l2->ui_queue))
+		test_and_set_bit(FLG_L2BLOCK, &l2->flag);
+}
+
+static void
+clear_peer_busy(struct Layer2 *l2) {
+	if (test_and_clear_bit(FLG_PEER_BUSY, &l2->flag))
+		test_and_clear_bit(FLG_L2BLOCK, &l2->flag);
+}
+
+static void
 InitWin(struct Layer2 *l2)
 {
 	int i;
@@ -162,30 +190,45 @@
 		l2->windowar[i] = NULL;
 }
 
-static void
-ReleaseWin(struct Layer2 *l2)
+static int
+freewin1(struct Layer2 *l2)
 {
 	int i, cnt = 0;
 
 	for (i = 0; i < MAX_WINDOW; i++) {
 		if (l2->windowar[i]) {
 			cnt++;
-			dev_kfree_skb(l2->windowar[i]);
+			idev_kfree_skb(l2->windowar[i], FREE_WRITE);
 			l2->windowar[i] = NULL;
 		}
 	}
-	if (cnt)
+	return cnt;
+}
+
+inline void
+freewin(struct PStack *st)
+{
+	freewin1(&st->l2);
+}
+
+static void
+ReleaseWin(struct Layer2 *l2)
+{
+	int cnt;
+
+	if((cnt = freewin1(l2)))
 		printk(KERN_WARNING "isdl2 freed %d skbuffs in release\n", cnt);
 }
 
-inline int
+inline unsigned int
 cansend(struct PStack *st)
 {
-	int p1;
+	unsigned int p1;
 
-	p1 = st->l2.vs - st->l2.va;
-	if (p1 < 0)
-		p1 += (test_bit(FLG_MOD128, &st->l2.flag) ? 128 : 8);
+	if(test_bit(FLG_MOD128, &st->l2.flag))
+		p1 = (st->l2.vs - st->l2.va) % 128;
+	else
+		p1 = (st->l2.vs - st->l2.va) % 8;
 	return ((p1 < st->l2.window) && !test_bit(FLG_PEER_BUSY, &st->l2.flag));
 }
 
@@ -195,7 +238,7 @@
 	test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
 	test_and_clear_bit(FLG_REJEXC, &l2->flag);
 	test_and_clear_bit(FLG_OWN_BUSY, &l2->flag);
-	test_and_clear_bit(FLG_PEER_BUSY, &l2->flag);
+	clear_peer_busy(l2);
 }
 
 inline int
@@ -244,98 +287,197 @@
 #define enqueue_ui(a, b) enqueue_super(a, b)
 
 inline int
-IsUI(u_char * data, int ext)
+IsUI(u_char * data)
 {
 	return ((data[0] & 0xef) == UI);
 }
 
 inline int
-IsUA(u_char * data, int ext)
+IsUA(u_char * data)
 {
 	return ((data[0] & 0xef) == UA);
 }
 
 inline int
-IsDM(u_char * data, int ext)
+IsDM(u_char * data)
 {
 	return ((data[0] & 0xef) == DM);
 }
 
 inline int
-IsDISC(u_char * data, int ext)
+IsDISC(u_char * data)
 {
 	return ((data[0] & 0xef) == DISC);
 }
 
 inline int
-IsRR(u_char * data, int ext)
+IsRR(u_char * data, struct PStack *st)
 {
-	if (ext)
+	if (test_bit(FLG_MOD128, &st->l2.flag))
 		return (data[0] == RR);
 	else
 		return ((data[0] & 0xf) == 1);
 }
 
 inline int
-IsSFrame(u_char * data, int ext)
+IsSFrame(u_char * data, struct PStack *st)
 {
 	register u_char d = *data;
 	
-	if (!ext)
+	if (!test_bit(FLG_MOD128, &st->l2.flag))
 		d &= 0xf;
 	return(((d & 0xf3) == 1) && ((d & 0x0c) != 0x0c));
 }
 
 inline int
-IsSABMX(u_char * data, int ext)
+IsSABME(u_char * data, struct PStack *st)
 {
 	u_char d = data[0] & ~0x10;
 
-	return (ext ? d == SABME : d == SABM);
+	return (test_bit(FLG_MOD128, &st->l2.flag) ? d == SABME : d == SABM);
 }
 
 inline int
-IsREJ(u_char * data, int ext)
+IsREJ(u_char * data, struct PStack *st)
 {
-	return (ext ? data[0] == REJ : (data[0] & 0xf) == REJ);
+	return (test_bit(FLG_MOD128, &st->l2.flag) ? data[0] == REJ : (data[0] & 0xf) == REJ);
 }
 
 inline int
-IsFRMR(u_char * data, int ext)
+IsFRMR(u_char * data)
 {
 	return ((data[0] & 0xef) == FRMR);
 }
 
 inline int
-IsRNR(u_char * data, int ext)
+IsRNR(u_char * data, struct PStack *st)
 {
-	return (ext ? data[0] == RNR : (data[0] & 0xf) == RNR);
+	return (test_bit(FLG_MOD128, &st->l2.flag) ? data[0] == RNR : (data[0] & 0xf) == RNR);
 }
 
-static int
-legalnr(struct PStack *st, int nr)
+int
+iframe_error(struct PStack *st, struct sk_buff *skb)
 {
-	struct Layer2 *l2 = &st->l2;
-	int lnr, lvs;
+	int i = l2addrsize(&st->l2) + (test_bit(FLG_MOD128, &st->l2.flag) ? 1 : 0);
+	int rsp = *skb->data & 0x2;
+
+	if (test_bit(FLG_ORIG, &st->l2.flag))
+		rsp = !rsp;
+
+	if (rsp)
+		return 'L';
+
+
+	if (skb->len <= i)
+		return 'N';
+
+	if ((skb->len - i) > st->l2.maxlen)
+		return 'O';
 
-	lvs = (l2->vs >= l2->va) ? l2->vs :
-	    (l2->vs + (test_bit(FLG_MOD128, &l2->flag) ? 128 : 8));
-	lnr = (nr >= l2->va) ? nr : (test_bit(FLG_MOD128, &l2->flag) ? 128 : 8);
-	return (lnr <= lvs);
+
+	return 0;
+}
+
+int
+super_error(struct PStack *st, struct sk_buff *skb)
+{
+	if (skb->len != l2addrsize(&st->l2) +
+	    (test_bit(FLG_MOD128, &st->l2.flag) ? 2 : 1))
+		return 'N';
+
+	return 0;
+}
+
+int
+unnum_error(struct PStack *st, struct sk_buff *skb, int wantrsp)
+{
+	int rsp = (*skb->data & 0x2) >> 1;
+	if (test_bit(FLG_ORIG, &st->l2.flag))
+		rsp = !rsp;
+
+	if (rsp != wantrsp)
+		return 'L';
+
+	if (skb->len != l2addrsize(&st->l2) + 1)
+		return 'N';
+
+	return 0;
+}
+
+int
+UI_error(struct PStack *st, struct sk_buff *skb)
+{
+	int rsp = *skb->data & 0x2;
+	if (test_bit(FLG_ORIG, &st->l2.flag))
+		rsp = !rsp;
+
+	if (rsp)
+		return 'L';
+
+	if (skb->len > st->l2.maxlen + l2addrsize(&st->l2) + 1)
+		return 'O';
+
+	return 0;
+}
+
+int
+FRMR_error(struct PStack *st, struct sk_buff *skb)
+{
+	int headers = l2addrsize(&st->l2) + 1;
+	u_char *datap = skb->data + headers;
+	int rsp = *skb->data & 0x2;
+
+	if (test_bit(FLG_ORIG, &st->l2.flag))
+		rsp = !rsp;
+
+	if (!rsp)
+		return 'L';
+
+	if (test_bit(FLG_MOD128, &st->l2.flag)) {
+		if (skb->len < headers + 5)
+			return 'N';
+		else
+			l2m_debug(&st->l2.l2m, "FRMR information %2x %2x %2x %2x %2x",
+				datap[0], datap[1], datap[2],
+				datap[3], datap[4]);
+	} else {
+		if (skb->len < headers + 3)
+			return 'N';
+		else
+			l2m_debug(&st->l2.l2m, "FRMR information %2x %2x %2x",
+				datap[0], datap[1], datap[2]);
+	}
+
+	return 0;
+}
+
+static unsigned int
+legalnr(struct PStack *st, unsigned int nr)
+{
+        struct Layer2 *l2 = &st->l2;
+
+	if(test_bit(FLG_MOD128, &l2->flag))
+		return ((nr - l2->va) % 128) <= ((l2->vs - l2->va) % 128);
+	else
+		return ((nr - l2->va) % 8) <= ((l2->vs - l2->va) % 8);
 }
 
 static void
-setva(struct PStack *st, int nr)
+setva(struct PStack *st, unsigned int nr)
 {
 	struct Layer2 *l2 = &st->l2;
 	int len;
 
 	while (l2->va != nr) {
-		l2->va = (l2->va + 1) % (test_bit(FLG_MOD128, &l2->flag) ? 128 : 8);
+		(l2->va)++;
+		if(test_bit(FLG_MOD128, &l2->flag))
+			l2->va %= 128;
+		else
+			l2->va %= 8;
 		len = l2->windowar[l2->sow]->len;
 		if (PACKET_NOACK == l2->windowar[l2->sow]->pkt_type)
 			len = -1;
-		dev_kfree_skb(l2->windowar[l2->sow]);
+		idev_kfree_skb(l2->windowar[l2->sow], FREE_WRITE);
 		l2->windowar[l2->sow] = NULL;
 		l2->sow = (l2->sow + 1) % l2->window;
 		if (st->lli.l2writewakeup && (len >=0))
@@ -356,6 +498,7 @@
 		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);
 }
@@ -369,7 +512,7 @@
 inline void
 FreeSkb(struct sk_buff *skb)
 {
-	dev_kfree_skb(skb);
+	idev_kfree_skb(skb, FREE_READ);
 }
 
 
@@ -383,6 +526,48 @@
 	return (PF);
 }
 
+inline void
+start_t200(struct PStack *st, int i)
+{
+	FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, i);
+	test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
+}
+
+inline void
+restart_t200(struct PStack *st, int i)
+{
+	FsmRestartTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, i);
+	test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
+}
+
+inline void
+stop_t200(struct PStack *st, int i)
+{
+	if(test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
+		FsmDelTimer(&st->l2.t200, i);
+}
+
+inline void
+st5_dl_release_l2l3(struct PStack *st)
+{
+		int pr;
+
+		if(test_and_clear_bit(FLG_PEND_REL, &st->l2.flag))
+			pr = DL_RELEASE | CONFIRM;
+		else
+			pr = DL_RELEASE | INDICATION;
+
+		st->l2.l2l3(st, pr, NULL);
+}
+
+inline void
+lapb_dl_release_l2l3(struct PStack *st, int f)
+{
+		if (test_bit(FLG_LAPB, &st->l2.flag))
+			st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
+		st->l2.l2l3(st, DL_RELEASE | f, NULL);
+}
+
 static void
 establishlink(struct FsmInst *fi)
 {
@@ -394,56 +579,91 @@
 	cmd = (test_bit(FLG_MOD128, &st->l2.flag) ? SABME : SABM) | 0x10;
 	send_uframe(st, cmd, CMD);
 	FsmDelTimer(&st->l2.t203, 1);
-	FsmRestartTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 1);
-	test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
+	restart_t200(st, 1);
+	test_and_clear_bit(FLG_PEND_REL, &st->l2.flag);
+	freewin(st);
 	FsmChangeState(fi, ST_L2_5);
 }
 
 static void
-l2_mdl_error(struct FsmInst *fi, int event, void *arg)
+l2_mdl_error_ua(struct FsmInst *fi, int event, void *arg)
 {
 	struct sk_buff *skb = arg;
 	struct PStack *st = fi->userdata;
 
-	switch (event) {
-		case EV_L2_UA:
-			if (get_PollFlagFree(st, skb))
-				st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'C');
-			else
-				st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'D');
-			break;
-		case EV_L2_DM:
-			if (get_PollFlagFree(st, skb))
-				st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'B');
-			else {
-				st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'E');
-				establishlink(fi);
-				test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
-			}
-			break;
-	}
+	if (get_PollFlagFree(st, skb))
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'C');
+	else
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'D');
 }
 
 static void
-l2_dl_establish(struct FsmInst *fi, int event, void *arg)
+l2_mdl_error_dm(struct FsmInst *fi, int event, void *arg)
 {
+	struct sk_buff *skb = arg;
 	struct PStack *st = fi->userdata;
-	int state = fi->state;
 
-	
-	if (test_bit(FLG_FIXED_TEI, &st->l2.flag)) {
-		FsmChangeState(fi, ST_L2_4);
+	if (get_PollFlagFree(st, skb))
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'B');
+	else {
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'E');
 		establishlink(fi);
-		test_and_set_bit(FLG_L3_INIT, &st->l2.flag);
-	} else {
-		FsmChangeState(fi, ST_L2_3);
-		if (state == ST_L2_1)
-			st->l2.l2tei(st, MDL_ASSIGN | INDICATION, NULL);
+		test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
+	}
+}
+
+static void
+l2_st8_mdl_error_dm(struct FsmInst *fi, int event, void *arg)
+{
+	struct sk_buff *skb = arg;
+	struct PStack *st = fi->userdata;
+
+	if (get_PollFlagFree(st, skb))
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'B');
+	else {
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'E');
 	}
+	establishlink(fi);
+	test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
+}
+
+static void
+l2_go_st3(struct FsmInst *fi, int event, void *arg)
+{
+	FsmChangeState(fi, ST_L2_3); 
+}
+
+static void
+l2_mdl_assign(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	FsmChangeState(fi, ST_L2_3); 
+	st->l2.l2tei(st, MDL_ASSIGN | INDICATION, NULL);
+}
+
+static void
+l2_queue_ui_assign(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+	struct sk_buff *skb = arg;
+
+	skb_queue_tail(&st->l2.ui_queue, skb);
+	FsmChangeState(fi, ST_L2_2);
+	st->l2.l2tei(st, MDL_ASSIGN | INDICATION, NULL);
+}
+
+static void
+l2_queue_ui(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+	struct sk_buff *skb = arg;
+
+	skb_queue_tail(&st->l2.ui_queue, skb);
 }
 
 static void
-l2_send_ui(struct PStack *st)
+tx_ui(struct PStack *st)
 {
 	struct sk_buff *skb;
 	u_char header[MAX_HEADER_LEN];
@@ -458,18 +678,13 @@
 }
 
 static void
-l2_put_ui(struct FsmInst *fi, int event, void *arg)
+l2_send_ui(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
 	struct sk_buff *skb = arg;
 
 	skb_queue_tail(&st->l2.ui_queue, skb);
-	if (fi->state == ST_L2_1) {
-		FsmChangeState(fi, ST_L2_2);
-		st->l2.l2tei(st, MDL_ASSIGN | INDICATION, NULL);
-	}
-	if (fi->state > ST_L2_3)
-		l2_send_ui(st);
+	tx_ui(st);
 }
 
 static void
@@ -479,11 +694,12 @@
 	struct sk_buff *skb = arg;
 
 	skb_pull(skb, l2headersize(&st->l2, 1));
-	if (skb->len > st->l2.maxlen) { 
-		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'O');
-		FreeSkb(skb);
-	} else
-		st->l2.l2l3(st, DL_UNIT_DATA | INDICATION, skb);
+	st->l2.l2l3(st, DL_UNIT_DATA | INDICATION, skb);
+/*	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ *		in states 1-3 for broadcast
+ */
+
+
 }
 
 static void
@@ -491,277 +707,244 @@
 {
 	struct PStack *st = fi->userdata;
 
-	if (fi->state != ST_L2_4)
-		discard_queue(&st->l2.i_queue);
-	if (fi->state != ST_L2_5)
-		establishlink(fi);
+	establishlink(fi);
 	test_and_set_bit(FLG_L3_INIT, &st->l2.flag);
 }
 
 static void
-l2_dl_release(struct FsmInst *fi, int event, void *arg)
+l2_discard_i_setl3(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	discard_queue(&st->l2.i_queue);
+	test_and_set_bit(FLG_L3_INIT, &st->l2.flag);
+	test_and_clear_bit(FLG_PEND_REL, &st->l2.flag);
+}
+
+static void
+l2_l3_reestablish(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
 
-	if (fi->state == ST_L2_4) {
-		st->l2.l2l3(st, DL_RELEASE  | CONFIRM, NULL);
-		return;
-	} else if (fi->state == ST_L2_5) {
-		test_and_set_bit(FLG_PEND_REL, &st->l2.flag);
-		return;
-	}
 	discard_queue(&st->l2.i_queue);
+	establishlink(fi);
+	test_and_set_bit(FLG_L3_INIT, &st->l2.flag);
+}
+
+static void
+l2_release(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL);
+}
+
+static void
+l2_pend_rel(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	test_and_set_bit(FLG_PEND_REL, &st->l2.flag);
+}
+
+static void
+l2_disconnect(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	discard_queue(&st->l2.i_queue);
+	freewin(st);
 	FsmChangeState(fi, ST_L2_6);
 	st->l2.rc = 0;
 	send_uframe(st, DISC | 0x10, CMD);
 	FsmDelTimer(&st->l2.t203, 1);
-	FsmRestartTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 2);
-	test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
+	restart_t200(st, 2);
+}
+
+static void
+l2_start_multi(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+	struct sk_buff *skb = arg;
+
+	send_uframe(st, UA | get_PollFlagFree(st, skb), RSP);
+
+	clear_exception(&st->l2);
+	st->l2.vs = 0;
+	st->l2.va = 0;
+	st->l2.vr = 0;
+	st->l2.sow = 0;
+	FsmChangeState(fi, ST_L2_7);
+	FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 3);
+
+	st->l2.l2l3(st, DL_ESTABLISH | INDICATION, NULL);
 }
 
 static void
-l2_got_SABMX(struct FsmInst *fi, int event, void *arg)
+l2_send_UA(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
 	struct sk_buff *skb = arg;
-	int est = 1, state, rsp;
-	u_char PollFlag;
+
+	send_uframe(st, UA | get_PollFlagFree(st, skb), RSP);
+}
+
+static void
+l2_send_DM(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+	struct sk_buff *skb = arg;
+
+	send_uframe(st, DM | get_PollFlagFree(st, skb), RSP);
+}
+
+static void
+l2_restart_multi(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+	struct sk_buff *skb = arg;
+	int est = 0, state;
 
 	state = fi->state;
-	rsp = *skb->data & 0x2;
-	if (test_bit(FLG_ORIG, &st->l2.flag))
-		rsp = !rsp;
-	if (rsp) {
-		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'L');
-		FreeSkb(skb);
-		if ((state == ST_L2_7) || (state == ST_L2_8))
-			establishlink(fi);
-		return;
-	}	
-	if (skb->len != (l2addrsize(&st->l2) + 1)) {
-		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
-		FreeSkb(skb);
-		if ((state == ST_L2_7) || (state == ST_L2_8))
-			establishlink(fi);
-		return;
-	}
-	PollFlag = get_PollFlagFree(st, skb);
-	if (ST_L2_6 == state) {
-		send_uframe(st, DM | PollFlag, RSP);
-		return;
-	} else
-		send_uframe(st, UA | PollFlag, RSP);
-	if (ST_L2_5 == state)
-		return;
-	if (ST_L2_4 != state) {
-		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'F');
-		if (st->l2.vs != st->l2.va) {
-			discard_queue(&st->l2.i_queue);
-			est = 1;
-		} else
-			est = 0;
+
+	send_uframe(st, UA | get_PollFlagFree(st, skb), RSP);
+
+	st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'F');
+
+	if (st->l2.vs != st->l2.va) {
+		discard_queue(&st->l2.i_queue);
+		est = 1;
 	}
+
 	clear_exception(&st->l2);
 	st->l2.vs = 0;
 	st->l2.va = 0;
 	st->l2.vr = 0;
 	st->l2.sow = 0;
 	FsmChangeState(fi, ST_L2_7);
-	if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
-		FsmDelTimer(&st->l2.t200, 2);
+	stop_t200(st, 3);
 	FsmRestartTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 3);
 
 	if (est)
 		st->l2.l2l3(st, DL_ESTABLISH | INDICATION, NULL);
 
-	if (ST_L2_8 == state)
-		if (skb_queue_len(&st->l2.i_queue) && cansend(st))
-			st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
+	if ((ST_L2_7==state) || (ST_L2_8 == state))
+		if (skb_queue_len(&st->l2.i_queue) && cansend(st))
+			st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
+}
+
+static void
+l2_stop_multi(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+	struct sk_buff *skb = arg;
+
+	FsmChangeState(fi, ST_L2_4);
+	FsmDelTimer(&st->l2.t203, 3);
+	stop_t200(st, 4);
+
+	send_uframe(st, UA | get_PollFlagFree(st, skb), RSP);
+
+	discard_queue(&st->l2.i_queue);
+	freewin(st);
+	lapb_dl_release_l2l3(st, INDICATION);
+}
+
+static void
+l2_connected(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+	struct sk_buff *skb = arg;
+	int pr=-1;
+
+	if (!get_PollFlag(st, skb)) {
+		l2_mdl_error_ua(fi, event, arg);
+		return;
+	}
+	FreeSkb(skb);
+
+	if (test_and_clear_bit(FLG_PEND_REL, &st->l2.flag))
+		l2_disconnect(fi, event, arg);
+
+	if (test_and_clear_bit(FLG_L3_INIT, &st->l2.flag)) {
+		pr = DL_ESTABLISH | CONFIRM;
+	} else if (st->l2.vs != st->l2.va) {
+		discard_queue(&st->l2.i_queue);
+		pr = DL_ESTABLISH | INDICATION;
+	}
+
+	stop_t200(st, 5);
+
+	st->l2.vr = 0;
+	st->l2.vs = 0;
+	st->l2.va = 0;
+	st->l2.sow = 0;
+	FsmChangeState(fi, ST_L2_7);
+	FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 4);
+
+	if (pr != -1)
+		st->l2.l2l3(st, pr, NULL);
+
+	if (skb_queue_len(&st->l2.i_queue) && cansend(st))
+		st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
+}
+
+static void
+l2_released(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+	struct sk_buff *skb = arg;
+
+	if (!get_PollFlag(st, skb)) {
+		l2_mdl_error_ua(fi, event, arg);
+		return;
+	}
+	FreeSkb(skb);
+
+	stop_t200(st, 6);
+	lapb_dl_release_l2l3(st, CONFIRM);
+	FsmChangeState(fi, ST_L2_4);
 }
 
 static void
-l2_got_disconn(struct FsmInst *fi, int event, void *arg)
+l2_reestablish(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
 	struct sk_buff *skb = arg;
-	u_char PollFlag, cmd = UA;
-	int state, rel = 1, cst = 1, rsp;
-
-	state = fi->state;
-	rsp = *skb->data & 0x2;
-	if (test_bit(FLG_ORIG, &st->l2.flag))
-		rsp = !rsp;
 
-	if (rsp) {
-		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'L');
-		FreeSkb(skb);
-		if ((state == ST_L2_7) || (state == ST_L2_8))
-			establishlink(fi);
-		return;
-	}	
-	if (skb->len != (l2addrsize(&st->l2) + 1)) {
-		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
-		FreeSkb(skb);
-		if ((state == ST_L2_7) || (state == ST_L2_8))
-			establishlink(fi);
-		return;
-	}
-	PollFlag = get_PollFlagFree(st, skb);
-	if ((state == ST_L2_4) || (state == ST_L2_5)) {
-		rel = 0;
-		cst = 0;
-		cmd = DM;
-	} else if (state == ST_L2_6) {
-		rel = 0;
-		cst = 0;
-	}
-	if (cst) {
-		FsmChangeState(fi, ST_L2_4);
-		FsmDelTimer(&st->l2.t203, 3);
-		if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag)) 
-			FsmDelTimer(&st->l2.t200, 2);
-	}
-	send_uframe(st, cmd | PollFlag, RSP);
-	if (rel) {
-		if (test_bit(FLG_LAPB, &st->l2.flag))
-			st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
-		st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
+	if (!get_PollFlagFree(st, skb)) {
+		establishlink(fi);
+		test_and_set_bit(FLG_L3_INIT, &st->l2.flag);
 	}
 }
 
-
 static void
-l2_got_ua(struct FsmInst *fi, int event, void *arg)
+l2_st5_dm_release(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
 	struct sk_buff *skb = arg;
-	int pr=-1;
-	u_char PollFlag;
-	int state,rsp;
-
-	state = fi->state;
-	rsp = *skb->data & 0x2;
-	if (test_bit(FLG_ORIG, &st->l2.flag))
-		rsp = !rsp;
-
-	if (!rsp) {
-		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'L');
-		FreeSkb(skb);
-		if ((state == ST_L2_7) || (state == ST_L2_8))
-			establishlink(fi);
-		return;
-	}	
-	if (skb->len != (l2addrsize(&st->l2) + 1)) {
-		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
-		FreeSkb(skb);
-		if ((fi->state == ST_L2_7) || (fi->state == ST_L2_8))
-			establishlink(fi);
-		return;
-	}
-	PollFlag = get_PollFlag(st, skb);
-	if (!PollFlag) {
-		l2_mdl_error(fi, event, arg);
-		return;
-	}
-	FreeSkb(skb);
 
-	if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
-		FsmDelTimer(&st->l2.t200, 2);
-	if (fi->state == ST_L2_5) {
-		if (test_and_clear_bit(FLG_PEND_REL, &st->l2.flag)) {
+	if (get_PollFlagFree(st, skb)) {
+		stop_t200(st, 7);
+	 	if (!test_bit(FLG_L3_INIT, &st->l2.flag))
 			discard_queue(&st->l2.i_queue);
-			st->l2.rc = 0;
-			send_uframe(st, DISC | 0x10, CMD);
-			FsmChangeState(fi, ST_L2_6);
-			FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 4);
-			test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
-		} else {
-			if (test_and_clear_bit(FLG_L3_INIT, &st->l2.flag)) {
-				pr = DL_ESTABLISH | CONFIRM;
-			} else if (st->l2.vs != st->l2.va) {
-				discard_queue(&st->l2.i_queue);
-				pr = DL_ESTABLISH | INDICATION;
-			}
-			st->l2.vs = 0;
-			st->l2.va = 0;
-			st->l2.vr = 0;
-			st->l2.sow = 0;
-			FsmChangeState(fi, ST_L2_7);
-			if (pr > -1)
-				st->l2.l2l3(st, pr, NULL);
-		}
-	} else {		/* ST_L2_6 */
 		if (test_bit(FLG_LAPB, &st->l2.flag))
 			st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
-		st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL);
+		st5_dl_release_l2l3(st);
 		FsmChangeState(fi, ST_L2_4);
 	}
 }
 
 static void
-l2_got_dm(struct FsmInst *fi, int event, void *arg)
+l2_st6_dm_release(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
 	struct sk_buff *skb = arg;
-	u_char PollFlag;
-	int state,rsp;
-
-	state = fi->state;
-	rsp = *skb->data & 0x2;
-	if (test_bit(FLG_ORIG, &st->l2.flag))
-		rsp = !rsp;
 
-	if (!rsp) {
-		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'L');
-		FreeSkb(skb);
-		if ((state == ST_L2_7) || (state == ST_L2_8))
-			establishlink(fi);
-		return;
-	}	
-	if (skb->len != (l2addrsize(&st->l2) + 1)) {
-		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
-		FreeSkb(skb);
-		if ((fi->state == ST_L2_7) || (fi->state == ST_L2_8))
-			establishlink(fi);
-		return;
-	}
-	PollFlag = get_PollFlagFree(st, skb);
-	if (!PollFlag) {
-		if (fi->state == ST_L2_4) {
-			establishlink(fi);
-			test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
-			FsmChangeState(fi, ST_L2_5);
-		} else if ((fi->state == ST_L2_7) || (fi->state == ST_L2_8)) {
-			st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'E');
-			establishlink(fi);
-		}
-	} else {
-		switch (fi->state) {
-			case ST_L2_8:
-				 establishlink(fi);
-			case ST_L2_7:
-				st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'B');
-				break;
-			case ST_L2_4:
-				break;
-			case ST_L2_5:
-				if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
-					FsmDelTimer(&st->l2.t200, 2);
-				discard_queue(&st->l2.i_queue);
-				if (test_bit(FLG_LAPB, &st->l2.flag))
-					st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
-				st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
-				FsmChangeState(fi, ST_L2_4);
-				break;
-			case ST_L2_6:
-				if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
-					FsmDelTimer(&st->l2.t200, 2);
-				if (test_bit(FLG_LAPB, &st->l2.flag))
-					st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
-				st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL);
-				FsmChangeState(fi, ST_L2_4);
-				break;
-		}
+	if (get_PollFlagFree(st, skb)) {
+		stop_t200(st, 8);
+		lapb_dl_release_l2l3(st, CONFIRM);
+		FsmChangeState(fi, ST_L2_4);
 	}
 }
 
@@ -784,6 +967,7 @@
 		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);
 }
@@ -806,8 +990,7 @@
 	else
 		enquiry_cr(st, RR, CMD, 1);
 	test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
-	FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 12);
-	test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
+	start_t200(st, 9);
 }
 
 
@@ -818,42 +1001,42 @@
 
 	st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'J');
 	establishlink(fi);
+	test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
 }
 
 static void
-invoke_retransmission(struct PStack *st, int nr)
+invoke_retransmission(struct PStack *st, unsigned int nr)
 {
 	struct Layer2 *l2 = &st->l2;
-	int p1;
-	long flags;
+	unsigned int p1;
 
 	if (l2->vs != nr) {
-		save_flags(flags);
-		cli();
 		while (l2->vs != nr) {
-			l2->vs = l2->vs - 1;
-			if (l2->vs < 0)
-				l2->vs += (test_bit(FLG_MOD128, &l2->flag) ? 128 : 8);
-			p1 = l2->vs - l2->va;
-			if (p1 < 0)
-				p1 += (test_bit(FLG_MOD128, &l2->flag) ? 128 : 8);
+			(l2->vs)--;
+			if(test_bit(FLG_MOD128, &l2->flag)) {
+				l2->vs %= 128;
+				p1 = (l2->vs - l2->va) % 128;
+			} else {
+				l2->vs %= 8;
+				p1 = (l2->vs - l2->va) % 8;
+			}
 			p1 = (p1 + l2->sow) % l2->window;
 			if (test_bit(FLG_LAPB, &l2->flag))
 				st->l1.bcs->tx_cnt += l2->windowar[p1]->len + l2headersize(l2, 0);
 			skb_queue_head(&l2->i_queue, l2->windowar[p1]);
 			l2->windowar[p1] = NULL;
 		}
-		restore_flags(flags);
 		st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
 	}
 }
 
 static void
-l2_got_st7_super(struct FsmInst *fi, int event, void *arg)
+l2_st7_got_super(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
 	struct sk_buff *skb = arg;
-	int PollFlag, nr, rsp, typ = RR;
+	int PollFlag, rsp, typ = RR;
+	unsigned int nr;
 	struct Layer2 *l2 = &st->l2;
 
 	rsp = *skb->data & 0x2;
@@ -861,72 +1044,77 @@
 		rsp = !rsp;
 
 	skb_pull(skb, l2addrsize(l2));
-	if (IsRNR(skb->data, test_bit(FLG_MOD128, &l2->flag))) {
-		test_and_set_bit(FLG_PEER_BUSY, &l2->flag);
+	if (IsRNR(skb->data, st)) {
+		set_peer_busy(l2);
 		typ = RNR;
 	} else
-		test_and_clear_bit(FLG_PEER_BUSY, &l2->flag);
-	if (IsREJ(skb->data, test_bit(FLG_MOD128, &l2->flag)))
+		clear_peer_busy(l2);
+	if (IsREJ(skb->data, st))
 		typ = REJ;
+
 	if (test_bit(FLG_MOD128, &l2->flag)) {
-		if (skb->len == 2) {
-			PollFlag = (skb->data[1] & 0x1) == 0x1;
-			nr = skb->data[1] >> 1;
-		} else {
-			if (skb->len >2) {
-				st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
-				establishlink(fi);
-			}
-			FreeSkb(skb);
-			return;
-		}
+		PollFlag = (skb->data[1] & 0x1) == 0x1;
+		nr = skb->data[1] >> 1;
 	} else {
-		if (skb->len == 1) {
-			PollFlag = (skb->data[0] & 0x10);
-			nr = (skb->data[0] >> 5) & 0x7;
-		} else {
-			st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
-			FreeSkb(skb);
-			establishlink(fi);
-			return;
-		}
+		PollFlag = (skb->data[0] & 0x10);
+		nr = (skb->data[0] >> 5) & 0x7;
 	}
 	FreeSkb(skb);
 
-	if ((!rsp) && PollFlag)
-		enquiry_response(st);
-	if (rsp && PollFlag)
-		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'A');
+	if (PollFlag) {
+		if (rsp)
+			st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'A');
+		else
+			enquiry_response(st);
+	}
 	if (legalnr(st, nr)) {
 		if (typ == REJ) {
 			setva(st, nr);
 			invoke_retransmission(st, nr);
-			if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
-				FsmDelTimer(&st->l2.t200, 9);
+			stop_t200(st, 10);
 			if (FsmAddTimer(&st->l2.t203, st->l2.T203,
 					EV_L2_T203, NULL, 6))
 				l2m_debug(&st->l2.l2m, "Restart T203 ST7 REJ");
 		} else if ((nr == l2->vs) && (typ == RR)) {
 			setva(st, nr);
-			if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
-				FsmDelTimer(&st->l2.t200, 9);
+			stop_t200(st, 11);
 			FsmRestartTimer(&st->l2.t203, st->l2.T203,
 					EV_L2_T203, NULL, 7);
 		} else if ((l2->va != nr) || (typ == RNR)) {
 			setva(st, nr);
-			FsmDelTimer(&st->l2.t203, 9);
-			FsmRestartTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 6);
-			test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
+			if(typ != RR) FsmDelTimer(&st->l2.t203, 9);
+			restart_t200(st, 12);
 		}
 		if (skb_queue_len(&st->l2.i_queue) && (typ == RR))
 			st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
 	} else
 		nrerrorrecovery(fi);
+}
 
-	if ((fi->userint & LC_FLUSH_WAIT) && rsp && !(skb_queue_len(&st->l2.i_queue))) {
-		fi->userint &= ~LC_FLUSH_WAIT;
-		st->l2.l2l3(st, DL_FLUSH | INDICATION, NULL);
-	}
+static void
+l2_feed_i_if_reest(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+	struct sk_buff *skb = arg;
+
+	if (test_bit(FLG_LAPB, &st->l2.flag))
+		st->l1.bcs->tx_cnt += skb->len + l2headersize(&st->l2, 0);
+	if (!test_bit(FLG_L3_INIT, &st->l2.flag))
+		skb_queue_tail(&st->l2.i_queue, skb);
+	else
+		FreeSkb(skb);
+}
+
+static void
+l2_feed_i_pull(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+	struct sk_buff *skb = arg;
+
+	if (test_bit(FLG_LAPB, &st->l2.flag))
+		st->l1.bcs->tx_cnt += skb->len + l2headersize(&st->l2, 0);
+	skb_queue_tail(&st->l2.i_queue, skb);
+	st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
 }
 
 static void
@@ -937,10 +1125,7 @@
 
 	if (test_bit(FLG_LAPB, &st->l2.flag))
 		st->l1.bcs->tx_cnt += skb->len + l2headersize(&st->l2, 0);
-	if (!((fi->state == ST_L2_5) && test_bit(FLG_L3_INIT, &st->l2.flag)))
-		skb_queue_tail(&st->l2.i_queue, skb);
-	if (fi->state == ST_L2_7)
-		st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
+	skb_queue_tail(&st->l2.i_queue, skb);
 }
 
 static void
@@ -949,54 +1134,30 @@
 	struct PStack *st = fi->userdata;
 	struct sk_buff *skb = arg;
 	struct Layer2 *l2 = &(st->l2);
-	int PollFlag, ns, nr, i, rsp;
-
-	rsp = *skb->data & 0x2;
-	if (test_bit(FLG_ORIG, &l2->flag))
-		rsp = !rsp;
+	int PollFlag, ns, i;
+	unsigned int nr;
 
-	if (rsp) {
-		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'L');
-		FreeSkb(skb);
-		establishlink(fi);
-		return;
-	}	
 	i = l2addrsize(l2);
 	if (test_bit(FLG_MOD128, &l2->flag)) {
-		if (skb->len <= (i + 1)) {
-			FreeSkb(skb);
-			return;
-		} else if ((skb->len - i - 1) > l2->maxlen) { 
-			st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'O');
-			FreeSkb(skb);
-			establishlink(fi);
-			return;
-		}
 		PollFlag = ((skb->data[i + 1] & 0x1) == 0x1);
 		ns = skb->data[i] >> 1;
 		nr = (skb->data[i + 1] >> 1) & 0x7f;
 	} else {
-		if (skb->len <= i) {
-			st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
-			FreeSkb(skb);
-			establishlink(fi);
-			return;
-		} else if ((skb->len - i) > l2->maxlen) { 
-			st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'O');
-			FreeSkb(skb);
-			establishlink(fi);
-			return;
-		}
 		PollFlag = (skb->data[i] & 0x10);
 		ns = (skb->data[i] >> 1) & 0x7;
 		nr = (skb->data[i] >> 5) & 0x7;
 	}
 	if (test_bit(FLG_OWN_BUSY, &l2->flag)) {
 		FreeSkb(skb);
-		enquiry_response(st);
+		if(PollFlag) enquiry_response(st);
 	} else if (l2->vr == ns) {
-		l2->vr = (l2->vr + 1) % (test_bit(FLG_MOD128, &l2->flag) ? 128 : 8);
+		(l2->vr)++;
+		if(test_bit(FLG_MOD128, &l2->flag))
+			l2->vr %= 128;
+		else
+			l2->vr %= 8;
 		test_and_clear_bit(FLG_REJEXC, &l2->flag);
+
 		if (PollFlag)
 			enquiry_response(st);
 		else
@@ -1016,19 +1177,15 @@
 	}
 
 	if (legalnr(st, nr)) {
-		setva(st, nr);
 		if (!test_bit(FLG_PEER_BUSY, &st->l2.flag) && (fi->state == ST_L2_7)) {
 			if (nr == st->l2.vs) {
-				if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
-					FsmDelTimer(&st->l2.t200, 10);
+				stop_t200(st, 13);
 				FsmRestartTimer(&st->l2.t203, st->l2.T203,
 						EV_L2_T203, NULL, 7);
-			} else if (nr != st->l2.va) {
-				FsmRestartTimer(&st->l2.t200, st->l2.T200, EV_L2_T200,
-						NULL, 8);
-				test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
-			}
+			} else if (nr != st->l2.va)
+				restart_t200(st, 14);
 		}
+		setva(st, nr);
 	} else {
 		nrerrorrecovery(fi);
 		return;
@@ -1053,7 +1210,7 @@
 	} else
 		FsmChangeState(fi, ST_L2_4);
 	if (skb_queue_len(&st->l2.ui_queue))
-		l2_send_ui(st);
+		tx_ui(st);
 }
 
 static void
@@ -1071,7 +1228,7 @@
 		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'G');
 		if (test_bit(FLG_LAPB, &st->l2.flag))
 			st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
-		st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
+		st5_dl_release_l2l3(st);
 	} else {
 		st->l2.rc++;
 		FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9);
@@ -1090,10 +1247,9 @@
 		FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9);
 	} else if (st->l2.rc == st->l2.N200) {
 		FsmChangeState(fi, ST_L2_4);
+		test_and_clear_bit(FLG_T200_RUN, &st->l2.flag);
 		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'H');
-		if (test_bit(FLG_LAPB, &st->l2.flag))
-			st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
-		st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
+		lapb_dl_release_l2l3(st, CONFIRM);
 	} else {
 		st->l2.rc++;
 		FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200,
@@ -1103,7 +1259,7 @@
 }
 
 static void
-l2_st78_tout_200(struct FsmInst *fi, int event, void *arg)
+l2_st7_tout_200(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
 
@@ -1113,12 +1269,28 @@
 		return;
 	}
 	test_and_clear_bit(FLG_T200_RUN, &st->l2.flag);
-	if (fi->state == ST_L2_7) {
-		st->l2.rc = 0;
-		FsmChangeState(fi, ST_L2_8);
+	st->l2.rc = 0;
+	FsmChangeState(fi, ST_L2_8);
+
+	transmit_enquiry(st);
+	st->l2.rc++;
+}
+
+static void
+l2_st8_tout_200(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	if (test_bit(FLG_LAPD, &st->l2.flag) &&
+		test_bit(FLG_DCHAN_BUSY, &st->l2.flag)) {
+		FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9);
+		return;
 	}
+	test_and_clear_bit(FLG_T200_RUN, &st->l2.flag);
 	if (st->l2.rc == st->l2.N200) {
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'I');
 		establishlink(fi);
+		test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
 	} else {
 		transmit_enquiry(st);
 		st->l2.rc++;
@@ -1147,7 +1319,9 @@
 	struct sk_buff *skb, *oskb;
 	struct Layer2 *l2 = &st->l2;
 	u_char header[MAX_HEADER_LEN];
-	int p1, i;
+	int i;
+	int unsigned p1;
+	long flags;
 
 	if (!cansend(st))
 		return;
@@ -1156,14 +1330,17 @@
 	if (!skb)
 		return;
 
-	p1 = l2->vs - l2->va;
-	if (p1 < 0)
-		p1 += test_bit(FLG_MOD128, &l2->flag) ? 128 : 8;
+	save_flags(flags);
+	cli();
+	if(test_bit(FLG_MOD128, &l2->flag))
+		p1 = (l2->vs - l2->va) % 128;
+	else
+		p1 = (l2->vs - l2->va) % 8;
 	p1 = (p1 + l2->sow) % l2->window;
 	if (l2->windowar[p1]) {
 		printk(KERN_WARNING "isdnl2 try overwrite ack queue entry %d\n",
 		       p1);
-		dev_kfree_skb(l2->windowar[p1]);
+		idev_kfree_skb(l2->windowar[p1], FREE_WRITE);
 	}
 	l2->windowar[p1] = skb_clone(skb, GFP_ATOMIC);
 
@@ -1177,6 +1354,8 @@
 		header[i++] = (l2->vr << 5) | (l2->vs << 1);
 		l2->vs = (l2->vs + 1) % 8;
 	}
+	restore_flags(flags);
+
 	p1 = skb->data - skb->head;
 	if (p1 >= i)
 		memcpy(skb_push(skb, i), header, i);
@@ -1185,6 +1364,7 @@
 		"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);
@@ -1200,74 +1380,58 @@
 }
 
 static void
-l2_got_st8_super(struct FsmInst *fi, int event, void *arg)
+l2_st8_got_super(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
 	struct sk_buff *skb = arg;
-	int PollFlag, nr, rsp, rnr = 0;
+	int PollFlag, rsp, rnr = 0;
+	unsigned int nr;
 	struct Layer2 *l2 = &st->l2;
 
 	rsp = *skb->data & 0x2;
 	if (test_bit(FLG_ORIG, &l2->flag))
 		rsp = !rsp;
+
 	skb_pull(skb, l2addrsize(l2));
 
-	if (IsRNR(skb->data, test_bit(FLG_MOD128, &l2->flag))) {
-		test_and_set_bit(FLG_PEER_BUSY, &l2->flag);
+	if (IsRNR(skb->data, st)) {
+		set_peer_busy(l2);
 		rnr = 1;
 	} else
-		test_and_clear_bit(FLG_PEER_BUSY, &l2->flag);
+		clear_peer_busy(l2);
+
 	if (test_bit(FLG_MOD128, &l2->flag)) {
-		if (skb->len == 2) {
-			PollFlag = (skb->data[1] & 0x1) == 0x1;
-			nr = skb->data[1] >> 1;
-		} else {
-			st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
-			FreeSkb(skb);
-			establishlink(fi);
-			return;
-		}
+		PollFlag = (skb->data[1] & 0x1) == 0x1;
+		nr = skb->data[1] >> 1;
 	} else {
-		if (skb->len == 1) {
-			PollFlag = (skb->data[0] & 0x10);
-			nr = (skb->data[0] >> 5) & 0x7;
-		} else {
-			st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
-			FreeSkb(skb);
-			establishlink(fi);
-			return;
-		}
+		PollFlag = (skb->data[0] & 0x10);
+		nr = (skb->data[0] >> 5) & 0x7;
 	}
 	FreeSkb(skb);
 
 	if (rsp && PollFlag) {
 		if (legalnr(st, nr)) {
-			setva(st, nr);
-			if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
-				FsmDelTimer(&st->l2.t200, 7);
-			FsmDelTimer(&l2->t203, 8);
 			if (rnr) {
-				FsmRestartTimer(&l2->t200, l2->T200,
-						EV_L2_T200, NULL, 14);
-				test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
-			} else
+				restart_t200(st, 15);
+			} else {
+				stop_t200(st, 16);
 				FsmAddTimer(&l2->t203, l2->T203,
 					    EV_L2_T203, NULL, 5);
+				setva(st, nr);
+			}
 			invoke_retransmission(st, nr);
 			FsmChangeState(fi, ST_L2_7);
 			if (skb_queue_len(&l2->i_queue) && cansend(st))
 				st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
-			else if (fi->userint & LC_FLUSH_WAIT) {
-				fi->userint &= ~LC_FLUSH_WAIT;
-				st->l2.l2l3(st, DL_FLUSH | INDICATION, NULL);
-			}
-		}
+		} else
+			nrerrorrecovery(fi);
 	} else {
 		if (!rsp && PollFlag)
 			enquiry_response(st);
 		if (legalnr(st, nr)) {
 			setva(st, nr);
-		}
+		} else
+			nrerrorrecovery(fi);
 	}
 }
 
@@ -1278,22 +1442,9 @@
 	struct sk_buff *skb = arg;
 
 	skb_pull(skb, l2addrsize(&st->l2) + 1);
-	if (test_bit(FLG_MOD128, &st->l2.flag)) {
-		if (skb->len < 5)
-			st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
-		else
-			l2m_debug(&st->l2.l2m, "FRMR information %2x %2x %2x %2x %2x",
-				skb->data[0], skb->data[1], skb->data[2],
-				skb->data[3], skb->data[4]);
-	} else {
-		if (skb->len < 3)
-			st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
-		else
-			l2m_debug(&st->l2.l2m, "FRMR information %2x %2x %2x",
-				skb->data[0], skb->data[1], skb->data[2]);
-	}
+
 	if (!(skb->data[0] & 1) || ((skb->data[0] & 3) == 1) ||		/* I or S */
-	    (IsUA(skb->data, 0) && (fi->state == ST_L2_7))) {
+	    (IsUA(skb->data) && (fi->state == ST_L2_7))) {
 		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'K');
 		establishlink(fi);
 		test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
@@ -1302,115 +1453,209 @@
 }
 
 static void
+l2_st24_tei_remove(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	discard_queue(&st->l2.ui_queue);
+	st->l2.tei = -1;
+	FsmChangeState(fi, ST_L2_1);
+}
+
+static void
+l2_st3_tei_remove(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	discard_queue(&st->l2.ui_queue);
+	st->l2.tei = -1;
+	st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
+	FsmChangeState(fi, ST_L2_1);
+}
+
+static void
+l2_st5_tei_remove(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	discard_queue(&st->l2.i_queue);
+	discard_queue(&st->l2.ui_queue);
+	freewin(st);
+	st->l2.tei = -1;
+	stop_t200(st, 17);
+	st5_dl_release_l2l3(st);
+	FsmChangeState(fi, ST_L2_1);
+}
+
+static void
+l2_st6_tei_remove(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	discard_queue(&st->l2.ui_queue);
+	st->l2.tei = -1;
+	stop_t200(st, 18);
+	st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL);
+	FsmChangeState(fi, ST_L2_1);
+}
+
+static void
 l2_tei_remove(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
 
 	discard_queue(&st->l2.i_queue);
 	discard_queue(&st->l2.ui_queue);
+	freewin(st);
 	st->l2.tei = -1;
-	if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
-		FsmDelTimer(&st->l2.t200, 18);
+	stop_t200(st, 17);
 	FsmDelTimer(&st->l2.t203, 19);
-	if (fi->state != ST_L2_4)
-		st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
+	st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
 	FsmChangeState(fi, ST_L2_1);
 }
 
 static void
-l2_persistant_da(struct FsmInst *fi, int event, void *arg)
+l2_st14_persistant_da(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
-	int rel = DL_RELEASE | INDICATION;
-	
 	
 	discard_queue(&st->l2.i_queue);
 	discard_queue(&st->l2.ui_queue);
-	if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
-		FsmDelTimer(&st->l2.t200, 18);
+	if (test_and_clear_bit(FLG_ESTAB_PEND, &st->l2.flag))
+		st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
+}
+
+static void
+l2_st5_persistant_da(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	discard_queue(&st->l2.i_queue);
+	discard_queue(&st->l2.ui_queue);
+	freewin(st);
+	stop_t200(st, 19);
+	st5_dl_release_l2l3(st);
+	FsmChangeState(fi, ST_L2_4);
+}
+
+static void
+l2_st6_persistant_da(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	discard_queue(&st->l2.ui_queue);
+	stop_t200(st, 20);
+	st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL);
+	FsmChangeState(fi, ST_L2_4);
+}
+
+static void
+l2_persistant_da(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	discard_queue(&st->l2.i_queue);
+	discard_queue(&st->l2.ui_queue);
+	freewin(st);
+	stop_t200(st, 19);
 	FsmDelTimer(&st->l2.t203, 19);
-	clear_exception(&st->l2);
-	switch (fi->state) {
-		case ST_L2_1:
-			if (!test_and_clear_bit(FLG_ESTAB_PEND, &st->l2.flag))
-				break;
-		case ST_L2_3:
-			st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
-		case ST_L2_2:
-			FsmChangeState(fi, ST_L2_1);
-			break;
-		case ST_L2_6:
-			rel = DL_RELEASE | CONFIRM;
-		case ST_L2_5:
-			if (test_and_clear_bit(FLG_PEND_REL, &st->l2.flag))
-				rel = DL_RELEASE | CONFIRM;
-		case ST_L2_7:
-		case ST_L2_8:
-			st->l2.l2l3(st, rel, NULL);
-			FsmChangeState(fi, ST_L2_4);
-			break;
-		case ST_L2_4:
-			if (test_and_clear_bit(FLG_ESTAB_PEND, &st->l2.flag))
-				st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
-			break;
+	st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
+	FsmChangeState(fi, ST_L2_4);
+}
+
+static void
+l2_set_own_busy(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	if(!test_and_set_bit(FLG_OWN_BUSY, &st->l2.flag)) {
+		enquiry_cr(st, RNR, RSP, 0);
+		test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
 	}
-	test_and_clear_bit(FLG_PEND_REL, &st->l2.flag);
-	test_and_clear_bit(FLG_L1_ACTIV, &st->l2.flag);
+}
+
+static void
+l2_clear_own_busy(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	if(!test_and_clear_bit(FLG_OWN_BUSY, &st->l2.flag)) {
+		enquiry_cr(st, RR, RSP, 0);
+		test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
+	}
+}
+
+static void
+l2_frame_error(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	st->ma.layer(st, MDL_ERROR | INDICATION, arg);
+}
+
+static void
+l2_frame_error_reest(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	st->ma.layer(st, MDL_ERROR | INDICATION, arg);
+	establishlink(fi);
+	test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
 }
 
 static struct FsmNode L2FnList[] HISAX_INITDATA =
 {
-	{ST_L2_1, EV_L2_DL_ESTABLISH, l2_dl_establish},
-	{ST_L2_2, EV_L2_DL_ESTABLISH, l2_dl_establish},
-	{ST_L2_4, EV_L2_DL_ESTABLISH, l2_establish},
-	{ST_L2_5, EV_L2_DL_ESTABLISH, l2_establish},
-	{ST_L2_7, EV_L2_DL_ESTABLISH, l2_establish},
-	{ST_L2_8, EV_L2_DL_ESTABLISH, l2_establish},
-	{ST_L2_4, EV_L2_DL_RELEASE, l2_dl_release},
-	{ST_L2_5, EV_L2_DL_RELEASE, l2_dl_release},
-	{ST_L2_7, EV_L2_DL_RELEASE, l2_dl_release},
-	{ST_L2_8, EV_L2_DL_RELEASE, l2_dl_release},
-	{ST_L2_5, EV_L2_DL_DATA, l2_feed_iqueue},
-	{ST_L2_7, EV_L2_DL_DATA, l2_feed_iqueue},
+	{ST_L2_1, EV_L2_DL_ESTABLISH_REQ, l2_mdl_assign},
+	{ST_L2_2, EV_L2_DL_ESTABLISH_REQ, l2_go_st3},
+	{ST_L2_4, EV_L2_DL_ESTABLISH_REQ, l2_establish},
+	{ST_L2_5, EV_L2_DL_ESTABLISH_REQ, l2_discard_i_setl3},
+	{ST_L2_7, EV_L2_DL_ESTABLISH_REQ, l2_l3_reestablish},
+	{ST_L2_8, EV_L2_DL_ESTABLISH_REQ, l2_l3_reestablish},
+	{ST_L2_4, EV_L2_DL_RELEASE_REQ, l2_release},
+	{ST_L2_5, EV_L2_DL_RELEASE_REQ, l2_pend_rel},
+	{ST_L2_7, EV_L2_DL_RELEASE_REQ, l2_disconnect},
+	{ST_L2_8, EV_L2_DL_RELEASE_REQ, l2_disconnect},
+	{ST_L2_5, EV_L2_DL_DATA, l2_feed_i_if_reest},
+	{ST_L2_7, EV_L2_DL_DATA, l2_feed_i_pull},
 	{ST_L2_8, EV_L2_DL_DATA, l2_feed_iqueue},
-	{ST_L2_1, EV_L2_DL_UNIT_DATA, l2_put_ui},
-	{ST_L2_2, EV_L2_DL_UNIT_DATA, l2_put_ui},
-	{ST_L2_3, EV_L2_DL_UNIT_DATA, l2_put_ui},
-	{ST_L2_4, EV_L2_DL_UNIT_DATA, l2_put_ui},
-	{ST_L2_5, EV_L2_DL_UNIT_DATA, l2_put_ui},
-	{ST_L2_6, EV_L2_DL_UNIT_DATA, l2_put_ui},
-	{ST_L2_7, EV_L2_DL_UNIT_DATA, l2_put_ui},
-	{ST_L2_8, EV_L2_DL_UNIT_DATA, l2_put_ui},
+	{ST_L2_1, EV_L2_DL_UNIT_DATA, l2_queue_ui_assign},
+	{ST_L2_2, EV_L2_DL_UNIT_DATA, l2_queue_ui},
+	{ST_L2_3, EV_L2_DL_UNIT_DATA, l2_queue_ui},
+	{ST_L2_4, EV_L2_DL_UNIT_DATA, l2_send_ui},
+	{ST_L2_5, EV_L2_DL_UNIT_DATA, l2_send_ui},
+	{ST_L2_6, EV_L2_DL_UNIT_DATA, l2_send_ui},
+	{ST_L2_7, EV_L2_DL_UNIT_DATA, l2_send_ui},
+	{ST_L2_8, EV_L2_DL_UNIT_DATA, l2_send_ui},
 	{ST_L2_1, EV_L2_MDL_ASSIGN, l2_got_tei},
 	{ST_L2_2, EV_L2_MDL_ASSIGN, l2_got_tei},
 	{ST_L2_3, EV_L2_MDL_ASSIGN, l2_got_tei},
-	{ST_L2_2, EV_L2_MDL_ERROR, l2_tei_remove},
-	{ST_L2_3, EV_L2_MDL_ERROR, l2_tei_remove},
-	{ST_L2_4, EV_L2_MDL_REMOVE, l2_tei_remove},
-	{ST_L2_5, EV_L2_MDL_REMOVE, l2_tei_remove},
-	{ST_L2_6, EV_L2_MDL_REMOVE, l2_tei_remove},
+	{ST_L2_2, EV_L2_MDL_ERROR, l2_st24_tei_remove},
+	{ST_L2_3, EV_L2_MDL_ERROR, l2_st3_tei_remove},
+	{ST_L2_4, EV_L2_MDL_REMOVE, l2_st24_tei_remove},
+	{ST_L2_5, EV_L2_MDL_REMOVE, l2_st5_tei_remove},
+	{ST_L2_6, EV_L2_MDL_REMOVE, l2_st6_tei_remove},
 	{ST_L2_7, EV_L2_MDL_REMOVE, l2_tei_remove},
 	{ST_L2_8, EV_L2_MDL_REMOVE, l2_tei_remove},
-	{ST_L2_4, EV_L2_SABMX, l2_got_SABMX},
-	{ST_L2_5, EV_L2_SABMX, l2_got_SABMX},
-	{ST_L2_6, EV_L2_SABMX, l2_got_SABMX},
-	{ST_L2_7, EV_L2_SABMX, l2_got_SABMX},
-	{ST_L2_8, EV_L2_SABMX, l2_got_SABMX},
-	{ST_L2_4, EV_L2_DISC, l2_got_disconn},
-	{ST_L2_5, EV_L2_DISC, l2_got_disconn},
-	{ST_L2_6, EV_L2_DISC, l2_got_disconn},
-	{ST_L2_7, EV_L2_DISC, l2_got_disconn},
-	{ST_L2_8, EV_L2_DISC, l2_got_disconn},
-	{ST_L2_4, EV_L2_UA, l2_mdl_error},
-	{ST_L2_5, EV_L2_UA, l2_got_ua},
-	{ST_L2_6, EV_L2_UA, l2_got_ua},
-	{ST_L2_7, EV_L2_UA, l2_mdl_error},
-	{ST_L2_8, EV_L2_UA, l2_mdl_error},
-	{ST_L2_4, EV_L2_DM, l2_got_dm},
-	{ST_L2_5, EV_L2_DM, l2_got_dm},
-	{ST_L2_6, EV_L2_DM, l2_got_dm},
-	{ST_L2_7, EV_L2_DM, l2_got_dm},
-	{ST_L2_8, EV_L2_DM, l2_got_dm},
+	{ST_L2_4, EV_L2_SABME, l2_start_multi},
+	{ST_L2_5, EV_L2_SABME, l2_send_UA},
+	{ST_L2_6, EV_L2_SABME, l2_send_DM},
+	{ST_L2_7, EV_L2_SABME, l2_restart_multi},
+	{ST_L2_8, EV_L2_SABME, l2_restart_multi},
+	{ST_L2_4, EV_L2_DISC, l2_send_DM},
+	{ST_L2_5, EV_L2_DISC, l2_send_DM},
+	{ST_L2_6, EV_L2_DISC, l2_send_UA},
+	{ST_L2_7, EV_L2_DISC, l2_stop_multi},
+	{ST_L2_8, EV_L2_DISC, l2_stop_multi},
+	{ST_L2_4, EV_L2_UA, l2_mdl_error_ua},
+	{ST_L2_5, EV_L2_UA, l2_connected},
+	{ST_L2_6, EV_L2_UA, l2_released},
+	{ST_L2_7, EV_L2_UA, l2_mdl_error_ua},
+	{ST_L2_8, EV_L2_UA, l2_mdl_error_ua},
+	{ST_L2_4, EV_L2_DM, l2_reestablish},
+	{ST_L2_5, EV_L2_DM, l2_st5_dm_release},
+	{ST_L2_6, EV_L2_DM, l2_st6_dm_release},
+	{ST_L2_7, EV_L2_DM, l2_mdl_error_dm},
+	{ST_L2_8, EV_L2_DM, l2_st8_mdl_error_dm},
 	{ST_L2_1, EV_L2_UI, l2_got_ui},
 	{ST_L2_2, EV_L2_UI, l2_got_ui},
 	{ST_L2_3, EV_L2_UI, l2_got_ui},
@@ -1421,22 +1666,31 @@
 	{ST_L2_8, EV_L2_UI, l2_got_ui},
 	{ST_L2_7, EV_L2_FRMR, l2_got_FRMR},
 	{ST_L2_8, EV_L2_FRMR, l2_got_FRMR},
-	{ST_L2_7, EV_L2_SUPER, l2_got_st7_super},
-	{ST_L2_8, EV_L2_SUPER, l2_got_st8_super},
+	{ST_L2_7, EV_L2_SUPER, l2_st7_got_super},
+	{ST_L2_8, EV_L2_SUPER, l2_st8_got_super},
 	{ST_L2_7, EV_L2_I, l2_got_iframe},
 	{ST_L2_8, EV_L2_I, l2_got_iframe},
 	{ST_L2_5, EV_L2_T200, l2_st5_tout_200},
 	{ST_L2_6, EV_L2_T200, l2_st6_tout_200},
-	{ST_L2_7, EV_L2_T200, l2_st78_tout_200},
-	{ST_L2_8, EV_L2_T200, l2_st78_tout_200},
+	{ST_L2_7, EV_L2_T200, l2_st7_tout_200},
+	{ST_L2_8, EV_L2_T200, l2_st8_tout_200},
 	{ST_L2_7, EV_L2_T203, l2_st7_tout_203},
 	{ST_L2_7, EV_L2_ACK_PULL, l2_pull_iqueue},
-	{ST_L2_1, EV_L1_DEACTIVATE, l2_persistant_da},
-	{ST_L2_2, EV_L1_DEACTIVATE, l2_persistant_da},
-	{ST_L2_3, EV_L1_DEACTIVATE, l2_persistant_da},
-	{ST_L2_4, EV_L1_DEACTIVATE, l2_persistant_da},
-	{ST_L2_5, EV_L1_DEACTIVATE, l2_persistant_da},
-	{ST_L2_6, EV_L1_DEACTIVATE, l2_persistant_da},
+	{ST_L2_7, EV_L2_SET_OWN_BUSY, l2_set_own_busy},
+	{ST_L2_8, EV_L2_SET_OWN_BUSY, l2_set_own_busy},
+	{ST_L2_7, EV_L2_CLEAR_OWN_BUSY, l2_clear_own_busy},
+	{ST_L2_8, EV_L2_CLEAR_OWN_BUSY, l2_clear_own_busy},
+	{ST_L2_4, EV_L2_FRAME_ERROR, l2_frame_error},
+	{ST_L2_5, EV_L2_FRAME_ERROR, l2_frame_error},
+	{ST_L2_6, EV_L2_FRAME_ERROR, l2_frame_error},
+	{ST_L2_7, EV_L2_FRAME_ERROR, l2_frame_error_reest},
+	{ST_L2_8, EV_L2_FRAME_ERROR, l2_frame_error_reest},
+	{ST_L2_1, EV_L1_DEACTIVATE, l2_st14_persistant_da},
+	{ST_L2_2, EV_L1_DEACTIVATE, l2_st24_tei_remove},
+	{ST_L2_3, EV_L1_DEACTIVATE, l2_st3_tei_remove},
+	{ST_L2_4, EV_L1_DEACTIVATE, l2_st14_persistant_da},
+	{ST_L2_5, EV_L1_DEACTIVATE, l2_st5_persistant_da},
+	{ST_L2_6, EV_L1_DEACTIVATE, l2_st6_persistant_da},
 	{ST_L2_7, EV_L1_DEACTIVATE, l2_persistant_da},
 	{ST_L2_8, EV_L1_DEACTIVATE, l2_persistant_da},
 };
@@ -1449,6 +1703,7 @@
 	struct sk_buff *skb = arg;
 	u_char *datap;
 	int ret = 1, len;
+	int c = 0;
 
 	switch (pr) {
 		case (PH_DATA | INDICATION):
@@ -1457,36 +1712,46 @@
 			if (skb->len > len)
 				datap += len;
 			else {
-				st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
+				FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *) 'N');
 				FreeSkb(skb);
 				return;
 			}
-			if (!(*datap & 1))	/* I-Frame */
-				ret = FsmEvent(&st->l2.l2m, EV_L2_I, skb);
-			else if (IsSFrame(datap, test_bit(FLG_MOD128, &st->l2.flag)))
-				ret = FsmEvent(&st->l2.l2m, EV_L2_SUPER, skb);
-			else if (IsUI(datap, test_bit(FLG_MOD128, &st->l2.flag)))
-				ret = FsmEvent(&st->l2.l2m, EV_L2_UI, skb);
-			else if (IsSABMX(datap, test_bit(FLG_MOD128, &st->l2.flag)))
-				ret = FsmEvent(&st->l2.l2m, EV_L2_SABMX, skb);
-			else if (IsUA(datap, test_bit(FLG_MOD128, &st->l2.flag)))
-				ret = FsmEvent(&st->l2.l2m, EV_L2_UA, skb);
-			else if (IsDISC(datap, test_bit(FLG_MOD128, &st->l2.flag)))
-				ret = FsmEvent(&st->l2.l2m, EV_L2_DISC, skb);
-			else if (IsDM(datap, test_bit(FLG_MOD128, &st->l2.flag)))
-				ret = FsmEvent(&st->l2.l2m, EV_L2_DM, skb);
-			else if (IsFRMR(datap, test_bit(FLG_MOD128, &st->l2.flag)))
-				ret = FsmEvent(&st->l2.l2m, EV_L2_FRMR, skb);
-			else {
-				ret = 1;
-				if ((st->l2.l2m.state == ST_L2_7) ||
-					(st->l2.l2m.state == ST_L2_8))
-					establishlink(&st->l2.l2m);
-				st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'L');
+			if (!(*datap & 1)) {	/* I-Frame */
+				if(!(c = iframe_error(st, skb)))
+					ret = FsmEvent(&st->l2.l2m, EV_L2_I, skb);
+			} else if (IsSFrame(datap, st)) {	/* S-Frame */
+				if(!(c = super_error(st, skb)))
+					ret = FsmEvent(&st->l2.l2m, EV_L2_SUPER, skb);
+			} else if (IsUI(datap)) {
+				if(!(c = UI_error(st, skb)))
+					ret = FsmEvent(&st->l2.l2m, EV_L2_UI, skb);
+			} else if (IsSABME(datap, st)) {
+				if(!(c = unnum_error(st, skb, CMD)))
+					ret = FsmEvent(&st->l2.l2m, EV_L2_SABME, skb);
+			} else if (IsUA(datap)) {
+				if(!(c = unnum_error(st, skb, RSP)))
+					ret = FsmEvent(&st->l2.l2m, EV_L2_UA, skb);
+			} else if (IsDISC(datap)) {
+				if(!(c = unnum_error(st, skb, CMD)))
+					ret = FsmEvent(&st->l2.l2m, EV_L2_DISC, skb);
+			} else if (IsDM(datap)) {
+				if(!(c = unnum_error(st, skb, RSP)))
+					ret = FsmEvent(&st->l2.l2m, EV_L2_DM, skb);
+			} else if (IsFRMR(datap)) {
+				if(!(c = FRMR_error(st,skb)))
+					ret = FsmEvent(&st->l2.l2m, EV_L2_FRMR, skb);
+			} else {
+				FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *) 'L');
+				FreeSkb(skb);
+				ret = 0;
 			}
-			if (ret) {
+			if(c) {
 				FreeSkb(skb);
+				FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *) c);
+				ret = 0;
 			}
+			if (ret)
+				FreeSkb(skb);
 			break;
 		case (PH_PULL | CONFIRM):
 			FsmEvent(&st->l2.l2m, EV_L2_ACK_PULL, arg);
@@ -1501,7 +1766,7 @@
 		case (PH_ACTIVATE | INDICATION):
 			test_and_set_bit(FLG_L1_ACTIV, &st->l2.flag);
 			if (test_and_clear_bit(FLG_ESTAB_PEND, &st->l2.flag))
-				FsmEvent(&st->l2.l2m, EV_L2_DL_ESTABLISH, arg);
+				FsmEvent(&st->l2.l2m, EV_L2_DL_ESTABLISH_REQ, arg);
 			break;
 		case (PH_DEACTIVATE | INDICATION):
 		case (PH_DEACTIVATE | CONFIRM):
@@ -1520,19 +1785,19 @@
 	switch (pr) {
 		case (DL_DATA | REQUEST):
 			if (FsmEvent(&st->l2.l2m, EV_L2_DL_DATA, arg)) {
-				dev_kfree_skb((struct sk_buff *) arg);
+				idev_kfree_skb((struct sk_buff *) arg, FREE_READ);
 			}
 			break;
 		case (DL_UNIT_DATA | REQUEST):
 			if (FsmEvent(&st->l2.l2m, EV_L2_DL_UNIT_DATA, arg)) {
-				dev_kfree_skb((struct sk_buff *) arg);
+				idev_kfree_skb((struct sk_buff *) arg, FREE_READ);
 			}
 			break;
 		case (DL_ESTABLISH | REQUEST):
 			if (test_bit(FLG_L1_ACTIV, &st->l2.flag)) {
 				if (test_bit(FLG_LAPD, &st->l2.flag) ||
 					test_bit(FLG_ORIG, &st->l2.flag)) {
-					FsmEvent(&st->l2.l2m, EV_L2_DL_ESTABLISH, arg);
+					FsmEvent(&st->l2.l2m, EV_L2_DL_ESTABLISH_REQ, arg);
 				}
 			} else {
 				if (test_bit(FLG_LAPD, &st->l2.flag) ||
@@ -1546,10 +1811,7 @@
 			if (test_bit(FLG_LAPB, &st->l2.flag)) {
 				st->l2.l2l1(st, PH_DEACTIVATE, NULL);
 			}
-			FsmEvent(&st->l2.l2m, EV_L2_DL_RELEASE, arg);
-			break;
-		case (DL_FLUSH | REQUEST):
-			(&st->l2.l2m)->userint |= LC_FLUSH_WAIT;
+			FsmEvent(&st->l2.l2m, EV_L2_DL_RELEASE_REQ, arg);
 			break;
 		case (MDL_ASSIGN | REQUEST):
 			FsmEvent(&st->l2.l2m, EV_L2_MDL_ASSIGN, arg);
@@ -1566,7 +1828,7 @@
 void
 releasestack_isdnl2(struct PStack *st)
 {
-	FsmDelTimer(&st->l2.t200, 15);
+	FsmDelTimer(&st->l2.t200, 21);
 	FsmDelTimer(&st->l2.t203, 16);
 	discard_queue(&st->l2.i_queue);
 	discard_queue(&st->l2.ui_queue);
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/isdnl3.c linux/drivers/isdn/hisax/isdnl3.c
--- v2.3.13/linux/drivers/isdn/hisax/isdnl3.c	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/hisax/isdnl3.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: isdnl3.c,v 2.8 1998/11/15 23:55:04 keil Exp $
+/* $Id: isdnl3.c,v 2.10 1999/07/21 14:46:19 keil Exp $
 
  * Author       Karsten Keil (keil@isdn4linux.de)
  *              based on the teles driver from Jan den Ouden
@@ -11,6 +11,12 @@
  *              Fritz Elfert
  *
  * $Log: isdnl3.c,v $
+ * Revision 2.10  1999/07/21 14:46:19  keil
+ * changes from EICON certification
+ *
+ * Revision 2.9  1999/07/01 08:11:53  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 2.8  1998/11/15 23:55:04  keil
  * changes from 2.0
  *
@@ -62,7 +68,7 @@
 #include "isdnl3.h"
 #include <linux/config.h>
 
-const char *l3_revision = "$Revision: 2.8 $";
+const char *l3_revision = "$Revision: 2.10 $";
 
 static
 struct Fsm l3fsm =
@@ -71,6 +77,7 @@
 enum {
 	ST_L3_LC_REL,
 	ST_L3_LC_ESTAB_WAIT,
+	ST_L3_LC_REL_DELAY, 
 	ST_L3_LC_REL_WAIT,
 	ST_L3_LC_ESTAB,
 };
@@ -81,6 +88,7 @@
 {
 	"ST_L3_LC_REL",
 	"ST_L3_LC_ESTAB_WAIT",
+	"ST_L3_LC_REL_DELAY",
 	"ST_L3_LC_REL_WAIT",
 	"ST_L3_LC_ESTAB",
 };
@@ -92,9 +100,10 @@
 	EV_RELEASE_REQ,
 	EV_RELEASE_CNF,
 	EV_RELEASE_IND,
+	EV_TIMEOUT,
 };
 
-#define L3_EVENT_COUNT (EV_RELEASE_IND+1)
+#define L3_EVENT_COUNT (EV_TIMEOUT+1)
 
 static char *strL3Event[] =
 {
@@ -104,6 +113,7 @@
 	"EV_RELEASE_REQ",
 	"EV_RELEASE_CNF",
 	"EV_RELEASE_IND",
+	"EV_TIMEOUT",
 };
 
 static void
@@ -142,7 +152,14 @@
 		else {
 			if (codeset == wanted_set) {
 				if (*p == ie)
-					return (p);
+                                  { /* improved length check (Werner Cornelius) */
+                                    if ((pend - p) < 2) 
+                                      return(NULL); 
+                                    if (*(p+1) > (pend - (p+2))) 
+                                      return(NULL); 
+                                    return (p);
+                                  }           
+                                  
 				if (*p > ie)
 					return (NULL);
 			}
@@ -158,15 +175,15 @@
 int
 getcallref(u_char * p)
 {
-	int l, m = 1, cr = 0;
+	int l, cr = 0;
+
 	p++;			/* prot discr */
+	if (*p & 0xfe)		/* wrong callref BRI only 1 octet*/
+		return(-2);
 	l = 0xf & *p++;		/* callref length */
 	if (!l)			/* dummy CallRef */
 		return(-1);
-	while (l--) {
-		cr += m * (*p++);
-		m *= 8;
-	}
+	cr = *p++;
 	return (cr);
 }
 
@@ -186,8 +203,9 @@
 newl3state(struct l3_process *pc, int state)
 {
 	if (pc->debug & L3_DEB_STATE)
-		l3_debug(pc->st, "newstate cr %d %d --> %d", pc->callref,
-			pc->state, state);
+		l3_debug(pc->st, "newstate cr %d %d --> %d", 
+			 pc->callref & 0x7F,
+			 pc->state, state);
 	pc->state = state;
 }
 
@@ -242,6 +260,7 @@
 		printk(KERN_WARNING "HiSax: No skb for D-channel\n");
 		return (NULL);
 	}
+	SET_SKB_FREE(skb);
 	skb_reserve(skb, MAX_HEADER_LEN);
 	return (skb);
 }
@@ -253,10 +272,17 @@
 
 	HiSax_putstatus(st->l1.hardware, "L3", "no D protocol");
 	if (skb) {
-		dev_kfree_skb(skb);
+		idev_kfree_skb(skb, FREE_READ);
 	}
 }
 
+static int
+no_l3_proto_spec(struct PStack *st, isdn_ctrl *ic)
+{
+	printk(KERN_WARNING "HiSax: no specific protocol handler for proto %lu\n",ic->arg & 0xFF);
+	return(-1);
+}
+
 #ifdef	CONFIG_HISAX_EURO
 extern void setstack_dss1(struct PStack *st);
 #endif
@@ -300,7 +326,7 @@
 		np->next = p;
 	}
 	p->next = NULL;
-	p->debug = L3_DEB_WARN;
+	p->debug = st->l3.debug;
 	p->callref = cr;
 	p->state = 0;
 	p->chan = NULL;
@@ -323,8 +349,19 @@
 			StopAllL3Timer(p);
 			if (pp)
 				pp->next = np->next;
-			else
-				p->st->l3.proc = np->next;
+			else if (!(p->st->l3.proc = np->next) &&
+				!test_bit(FLG_PTP, &p->st->l2.flag)) {
+				if (p->debug)
+					l3_debug(p->st, "release_l3_process: last process");
+				if (!skb_queue_len(&p->st->l3.squeue)) {
+					if (p->debug)
+						l3_debug(p->st, "release_l3_process: release link");
+					FsmEvent(&p->st->l3.l3m, EV_RELEASE_REQ, NULL);
+				} else {
+					if (p->debug)
+						l3_debug(p->st, "release_l3_process: not release link");
+				}
+			} 
 			kfree(p);
 			return;
 		}
@@ -335,6 +372,17 @@
 	l3_debug(p->st, "HiSax internal L3 error CR(%d) not in list", p->callref);
 };
 
+static void
+l3ml3p(struct PStack *st, int pr)
+{
+	struct l3_process *p = st->l3.proc;
+
+	while (p) {
+		st->l3.l3ml3(st, pr, p);
+		p = p->next;
+	}
+}
+
 void
 setstack_l3dc(struct PStack *st, struct Channel *chanp)
 {
@@ -349,7 +397,9 @@
 	st->l3.l3m.userdata = st;
 	st->l3.l3m.userint = 0;
 	st->l3.l3m.printdebug = l3m_debug;
+        FsmInitTimer(&st->l3.l3m, &st->l3.l3m_timer);
 	strcpy(st->l3.debug_id, "L3DC ");
+	st->lli.l4l3_proto = no_l3_proto_spec;
 
 #ifdef	CONFIG_HISAX_EURO
 	if (st->protocol == ISDN_PTYPE_EURO) {
@@ -369,10 +419,12 @@
 	if (st->protocol == ISDN_PTYPE_LEASED) {
 		st->lli.l4l3 = no_l3_proto;
 		st->l2.l2l3 = no_l3_proto;
+                st->l3.l3ml3 = no_l3_proto;
 		printk(KERN_INFO "HiSax: Leased line mode\n");
 	} else {
 		st->lli.l4l3 = no_l3_proto;
 		st->l2.l2l3 = no_l3_proto;
+                st->l3.l3ml3 = no_l3_proto;
 		sprintf(tmp, "protocol %s not supported",
 			(st->protocol == ISDN_PTYPE_1TR6) ? "1tr6" :
 			(st->protocol == ISDN_PTYPE_EURO) ? "euro" :
@@ -398,6 +450,7 @@
 		kfree(st->l3.global);
 		st->l3.global = NULL;
 	}
+	FsmDelTimer(&st->l3.l3m_timer, 54);
 	discard_queue(&st->l3.squeue);
 }
 
@@ -418,6 +471,8 @@
 	st->lli.l4l3 = isdnl3_trans;
 }
 
+#define DREL_TIMER_VALUE 40000
+
 static void
 lc_activate(struct FsmInst *fi, int event, void *arg)
 {
@@ -432,12 +487,49 @@
 {
 	struct PStack *st = fi->userdata;
 	struct sk_buff *skb = arg;
+	int dequeued = 0;
 
 	FsmChangeState(fi, ST_L3_LC_ESTAB);
 	while ((skb = skb_dequeue(&st->l3.squeue))) {
 		st->l3.l3l2(st, DL_DATA | REQUEST, skb);
+		dequeued++;
 	}
-	st->l3.l3l4(st, DL_ESTABLISH | INDICATION, NULL);
+	if ((!st->l3.proc) &&  dequeued) {
+		if (st->l3.debug)
+			l3_debug(st, "lc_connect: release link");
+		FsmEvent(&st->l3.l3m, EV_RELEASE_REQ, NULL);
+	} else
+		l3ml3p(st, DL_ESTABLISH | INDICATION);
+}
+
+static void
+lc_connected(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+	struct sk_buff *skb = arg;
+	int dequeued = 0;
+
+	FsmDelTimer(&st->l3.l3m_timer, 51);
+	FsmChangeState(fi, ST_L3_LC_ESTAB);
+	while ((skb = skb_dequeue(&st->l3.squeue))) {
+		st->l3.l3l2(st, DL_DATA | REQUEST, skb);
+		dequeued++;
+	}
+	if ((!st->l3.proc) &&  dequeued) {
+		if (st->l3.debug)
+			l3_debug(st, "lc_connected: release link");
+		FsmEvent(&st->l3.l3m, EV_RELEASE_REQ, NULL);
+	} else
+		l3ml3p(st, DL_ESTABLISH | CONFIRM);
+}
+
+static void
+lc_start_delay(struct FsmInst *fi, int event, void *arg)
+{
+       struct PStack *st = fi->userdata;
+
+       FsmChangeState(fi, ST_L3_LC_REL_DELAY);
+       FsmAddTimer(&st->l3.l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 50);
 }
 
 static void
@@ -445,11 +537,15 @@
 {
 	struct PStack *st = fi->userdata;
 
-	if (fi->state == ST_L3_LC_ESTAB_WAIT)
-		FsmChangeState(fi, ST_L3_LC_REL);
-	else
+	if (test_bit(FLG_L2BLOCK, &st->l2.flag)) {
+		if (st->l3.debug)
+			l3_debug(st, "lc_release_req: l2 blocked");
+		/* restart release timer */
+		FsmAddTimer(&st->l3.l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 51);
+	} else {
 		FsmChangeState(fi, ST_L3_LC_REL_WAIT);
-	st->l3.l3l2(st, DL_RELEASE | REQUEST, NULL);
+		st->l3.l3l2(st, DL_RELEASE | REQUEST, NULL);
+	}
 }
 
 static void
@@ -457,23 +553,38 @@
 {
 	struct PStack *st = fi->userdata;
 
+	FsmDelTimer(&st->l3.l3m_timer, 52);
 	FsmChangeState(fi, ST_L3_LC_REL);
 	discard_queue(&st->l3.squeue);
-	st->l3.l3l4(st, DL_RELEASE | INDICATION, NULL);
+	l3ml3p(st, DL_RELEASE | INDICATION);
 }
 
+static void
+lc_release_cnf(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	FsmChangeState(fi, ST_L3_LC_REL);
+	discard_queue(&st->l3.squeue);
+	l3ml3p(st, DL_RELEASE | CONFIRM);
+}
+
+
 /* *INDENT-OFF* */
 static struct FsmNode L3FnList[] HISAX_INITDATA =
 {
 	{ST_L3_LC_REL,		EV_ESTABLISH_REQ,	lc_activate},
 	{ST_L3_LC_REL,		EV_ESTABLISH_IND,	lc_connect},
 	{ST_L3_LC_REL,		EV_ESTABLISH_CNF,	lc_connect},
-	{ST_L3_LC_ESTAB_WAIT,	EV_ESTABLISH_CNF,	lc_connect},
-	{ST_L3_LC_ESTAB_WAIT,	EV_RELEASE_REQ,		lc_release_req},
+	{ST_L3_LC_ESTAB_WAIT,	EV_ESTABLISH_CNF,	lc_connected},
+	{ST_L3_LC_ESTAB_WAIT,	EV_RELEASE_REQ,		lc_start_delay},
 	{ST_L3_LC_ESTAB_WAIT,	EV_RELEASE_IND,		lc_release_ind},
 	{ST_L3_LC_ESTAB,	EV_RELEASE_IND,		lc_release_ind},
-	{ST_L3_LC_ESTAB,	EV_RELEASE_REQ,		lc_release_req},
-	{ST_L3_LC_REL_WAIT,	EV_RELEASE_CNF,		lc_release_ind},
+	{ST_L3_LC_ESTAB,	EV_RELEASE_REQ,		lc_start_delay},
+        {ST_L3_LC_REL_DELAY,    EV_RELEASE_IND,         lc_release_ind},
+        {ST_L3_LC_REL_DELAY,    EV_ESTABLISH_REQ,       lc_connected},
+        {ST_L3_LC_REL_DELAY,    EV_TIMEOUT,             lc_release_req},
+	{ST_L3_LC_REL_WAIT,	EV_RELEASE_CNF,		lc_release_cnf},
 	{ST_L3_LC_REL_WAIT,	EV_ESTABLISH_REQ,	lc_activate},
 };
 /* *INDENT-ON* */
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/isdnl3.h linux/drivers/isdn/hisax/isdnl3.h
--- v2.3.13/linux/drivers/isdn/hisax/isdnl3.h	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/hisax/isdnl3.h	Thu Aug 12 09:42:33 1999
@@ -1,6 +1,12 @@
-/* $Id: isdnl3.h,v 2.3 1998/11/15 23:55:06 keil Exp $
+/* $Id: isdnl3.h,v 2.5 1999/07/25 16:18:32 keil Exp $
 
  * $Log: isdnl3.h,v $
+ * Revision 2.5  1999/07/25 16:18:32  keil
+ * Fix Suspend/Resume
+ *
+ * Revision 2.4  1999/07/01 08:11:54  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 2.3  1998/11/15 23:55:06  keil
  * changes from 2.0
  *
@@ -31,14 +37,16 @@
  */
 
 #define SBIT(state) (1<<state)
-#define ALL_STATES  0x00ffffff
+#define ALL_STATES  0x03ffffff
 
-#define	PROTO_DIS_EURO	0x08
+#define PROTO_DIS_EURO	0x08
 
 #define L3_DEB_WARN	0x01
-#define	L3_DEB_PROTERR	0x02
-#define	L3_DEB_STATE	0x04
-#define	L3_DEB_CHARGE	0x08
+#define L3_DEB_PROTERR	0x02
+#define L3_DEB_STATE	0x04
+#define L3_DEB_CHARGE	0x08
+#define L3_DEB_CHECK	0x10
+#define L3_DEB_SI	0x20
 
 struct stateentry {
 	int state;
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/isurf.c linux/drivers/isdn/hisax/isurf.c
--- v2.3.13/linux/drivers/isdn/hisax/isurf.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/hisax/isurf.c	Sun Aug 15 11:49:08 1999
@@ -0,0 +1,251 @@
+/* $Id: isurf.c,v 1.3 1999/07/12 21:05:18 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.3  1999/07/12 21:05:18  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 1.2  1999/07/01 08:07:56  keil
+ * Initial version
+ *
+ *
+ *
+ */
+
+#define __NO_VERSION__
+#include "hisax.h"
+#include "isac.h"
+#include "isar.h"
+#include "isdnl1.h"
+
+extern const char *CardType[];
+
+static const char *ISurf_revision = "$Revision: 1.3 $";
+
+#define byteout(addr,val) outb(val,addr)
+#define bytein(addr) inb(addr)
+
+#define ISURF_ISAR_RESET	1
+#define ISURF_ISAC_RESET	2
+#define ISURF_ISAR_EA		4
+#define ISURF_ARCOFI_RESET	8
+#define ISURF_RESET (ISURF_ISAR_RESET | ISURF_ISAC_RESET | ISURF_ARCOFI_RESET)
+
+#define ISURF_ISAR_OFFSET	0
+#define ISURF_ISAC_OFFSET	0x100
+
+/* Interface functions */
+
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
+{
+	return (readb(cs->hw.isurf.isac + offset));
+}
+
+static void
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+	writeb(value, cs->hw.isurf.isac + offset); mb();
+}
+
+static void
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	register int i;
+	for (i = 0; i < size; i++)
+		data[i] = readb(cs->hw.isurf.isac);
+}
+
+static void
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	register int i;
+	for (i = 0; i < size; i++){
+		writeb(data[i], cs->hw.isurf.isac);mb();
+	}
+}
+
+/* ISAR access routines
+ * mode = 0 access with IRQ on
+ * mode = 1 access with IRQ off
+ * mode = 2 access with IRQ off and using last offset
+ */
+  
+static u_char
+ReadISAR(struct IsdnCardState *cs, int mode, u_char offset)
+{	
+	return(readb(cs->hw.isurf.isar + offset));
+}
+
+static void
+WriteISAR(struct IsdnCardState *cs, int mode, u_char offset, u_char value)
+{
+	writeb(value, cs->hw.isurf.isar + offset);mb();
+}
+
+static void
+isurf_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char val;
+	int cnt = 5;
+
+	if (!cs) {
+		printk(KERN_WARNING "ISurf: Spurious interrupt!\n");
+		return;
+	}
+
+	val = readb(cs->hw.isurf.isar + ISAR_IRQBIT);
+      Start_ISAR:
+	if (val & ISAR_IRQSTA)
+		isar_int_main(cs);
+	val = readb(cs->hw.isurf.isac + ISAC_ISTA);
+      Start_ISAC:
+	if (val)
+		isac_interrupt(cs, val);
+	val = readb(cs->hw.isurf.isar + ISAR_IRQBIT);
+	if ((val & ISAR_IRQSTA) && --cnt) {
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "ISAR IntStat after IntRoutine");
+		goto Start_ISAR;
+	}
+	val = readb(cs->hw.isurf.isac + ISAC_ISTA);
+	if (val && --cnt) {
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "ISAC IntStat after IntRoutine");
+		goto Start_ISAC;
+	}
+	if (!cnt)
+		printk(KERN_WARNING "ISurf IRQ LOOP\n");
+
+	writeb(0, cs->hw.isurf.isar + ISAR_IRQBIT); mb();
+	writeb(0xFF, cs->hw.isurf.isac + ISAC_MASK);mb();
+	writeb(0, cs->hw.isurf.isac + ISAC_MASK);mb();
+	writeb(ISAR_IRQMSK, cs->hw.isurf.isar + ISAR_IRQBIT); mb();
+}
+
+void
+release_io_isurf(struct IsdnCardState *cs)
+{
+	release_region(cs->hw.isurf.reset, 1);
+}
+
+static void
+reset_isurf(struct IsdnCardState *cs, u_char chips)
+{
+	long flags;
+
+	printk(KERN_INFO "ISurf: resetting card\n");
+
+	byteout(cs->hw.isurf.reset, chips); /* Reset On */
+	save_flags(flags);
+	sti();
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout((10*HZ)/1000);
+	byteout(cs->hw.isurf.reset, ISURF_ISAR_EA); /* Reset Off */
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout((10*HZ)/1000);
+	restore_flags(flags);
+}
+
+static int
+ISurf_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+	switch (mt) {
+		case CARD_RESET:
+			reset_isurf(cs, ISURF_RESET);
+			return(0);
+		case CARD_RELEASE:
+			release_io_isurf(cs);
+			return(0);
+		case CARD_INIT:
+			clear_pending_isac_ints(cs);
+			writeb(0, cs->hw.isurf.isar+ISAR_IRQBIT);mb();
+			initisac(cs);
+			initisar(cs);
+			/* Reenable ISAC IRQ */
+			cs->writeisac(cs, ISAC_MASK, 0);
+			/* RESET Receiver and Transmitter */
+			cs->writeisac(cs, ISAC_CMDR, 0x41);
+			return(0);
+		case CARD_TEST:
+			return(0);
+		case CARD_LOAD_FIRM:
+			if (isar_load_firmware(cs, arg))
+				return(1);
+			ll_run(cs);
+			reset_isurf(cs, ISURF_ISAR_EA | ISURF_ISAC_RESET |
+				ISURF_ARCOFI_RESET);
+			initisac(cs);
+			cs->writeisac(cs, ISAC_MASK, 0);
+			cs->writeisac(cs, ISAC_CMDR, 0x41);
+			return(0);
+	}
+	return(0);
+}
+
+__initfunc(int
+setup_isurf(struct IsdnCard *card))
+{
+	int ver;
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+
+	strcpy(tmp, ISurf_revision);
+	printk(KERN_INFO "HiSax: ISurf driver Rev. %s\n", HiSax_getrev(tmp));
+	
+ 	if (cs->typ != ISDN_CTYPE_ISURF)
+ 		return(0);
+	if (card->para[1] && card->para[2]) {
+		cs->hw.isurf.reset = card->para[1];
+		cs->hw.isurf.isar = card->para[2] + ISURF_ISAR_OFFSET;
+		cs->hw.isurf.isac = card->para[2] + ISURF_ISAC_OFFSET;
+		cs->irq = card->para[0];
+	} else {
+		printk(KERN_WARNING "HiSax: %s port/mem not set\n",
+			CardType[card->typ]);
+		return (0);
+	}
+	if (check_region(cs->hw.isurf.reset, 1)) {
+		printk(KERN_WARNING
+			"HiSax: %s config port %x already in use\n",
+			CardType[card->typ],
+			cs->hw.isurf.reset);
+			return (0);
+	} else {
+		request_region(cs->hw.isurf.reset, 1, "isurf isdn");
+	}
+
+	printk(KERN_INFO
+	       "ISurf: defined at 0x%x 0x%x IRQ %d\n",
+	       cs->hw.isurf.reset,
+	       cs->hw.isurf.isar,
+	       cs->irq);
+
+	cs->cardmsg = &ISurf_card_msg;
+	cs->irq_func = &isurf_interrupt;
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->bcs[0].hw.isar.reg = &cs->hw.isurf.isar_r;
+	cs->bcs[1].hw.isar.reg = &cs->hw.isurf.isar_r;
+	reset_isurf(cs, ISURF_RESET);
+	test_and_set_bit(HW_ISAR, &cs->HW_Flags);
+	ISACVersion(cs, "ISurf:");
+	cs->BC_Read_Reg = &ReadISAR;
+	cs->BC_Write_Reg = &WriteISAR;
+	cs->BC_Send_Data = &isar_fill_fifo;
+	ver = ISARVersion(cs, "ISurf:");
+	if (ver < 0) {
+		printk(KERN_WARNING
+			"ISurf: wrong ISAR version (ret = %d)\n", ver);
+		release_io_isurf(cs);
+		return (0);
+	}
+	return (1);
+}
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/ix1_micro.c linux/drivers/isdn/hisax/ix1_micro.c
--- v2.3.13/linux/drivers/isdn/hisax/ix1_micro.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/isdn/hisax/ix1_micro.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: ix1_micro.c,v 2.7 1998/04/15 16:44:31 keil Exp $
+/* $Id: ix1_micro.c,v 2.8 1999/07/12 21:05:19 keil Exp $
 
  * ix1_micro.c  low level stuff for ITK ix1-micro Rev.2 isdn cards
  *              derived from the original file teles3.c from Karsten Keil
@@ -11,6 +11,10 @@
  *              Beat Doebeli
  *
  * $Log: ix1_micro.c,v $
+ * Revision 2.8  1999/07/12 21:05:19  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
  * Revision 2.7  1998/04/15 16:44:31  keil
  * new init code
  *
@@ -84,7 +88,7 @@
 #include "isdnl1.h"
 
 extern const char *CardType[];
-const char *ix1_revision = "$Revision: 2.7 $";
+const char *ix1_revision = "$Revision: 2.8 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -199,7 +203,7 @@
 ix1micro_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u_char val, stat = 0;
+	u_char val;
 
 	if (!cs) {
 		printk(KERN_WARNING "IX1: Spurious interrupt!\n");
@@ -207,16 +211,12 @@
 	}
 	val = readreg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_ISTA + 0x40);
       Start_HSCX:
-	if (val) {
+	if (val)
 		hscx_int_main(cs, val);
-		stat |= 1;
-	}
 	val = readreg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_ISTA);
       Start_ISAC:
-	if (val) {
+	if (val)
 		isac_interrupt(cs, val);
-		stat |= 2;
-	}
 	val = readreg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_ISTA + 0x40);
 	if (val) {
 		if (cs->debug & L1_DEB_HSCX)
@@ -229,16 +229,12 @@
 			debugl1(cs, "ISAC IntStat after IntRoutine");
 		goto Start_ISAC;
 	}
-	if (stat & 1) {
-		writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK, 0xFF);
-		writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK + 0x40, 0xFF);
-		writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK, 0);
-		writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK + 0x40, 0);
-	}
-	if (stat & 2) {
-		writereg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_MASK, 0xFF);
-		writereg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_MASK, 0);
-	}
+	writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK, 0xFF);
+	writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK + 0x40, 0xFF);
+	writereg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_MASK, 0);
+	writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK, 0);
+	writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK + 0x40, 0);
 }
 
 void
@@ -276,9 +272,6 @@
 		case CARD_RELEASE:
 			release_io_ix1micro(cs);
 			return(0);
-		case CARD_SETIRQ:
-			return(request_irq(cs->irq, &ix1micro_interrupt,
-					I4L_IRQ_FLAG, "HiSax", cs));
 		case CARD_INIT:
 			inithscxisac(cs, 3);
 			return(0);
@@ -289,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];
@@ -331,6 +324,7 @@
 	cs->BC_Write_Reg = &WriteHSCX;
 	cs->BC_Send_Data = &hscx_fill_fifo;
 	cs->cardmsg = &ix1_card_msg;
+	cs->irq_func = &ix1micro_interrupt;
 	ISACVersion(cs, "ix1-Micro:");
 	if (HscxVersion(cs, "ix1-Micro:")) {
 		printk(KERN_WARNING
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/jade.c linux/drivers/isdn/hisax/jade.c
--- v2.3.13/linux/drivers/isdn/hisax/jade.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/hisax/jade.c	Thu Aug 12 09:42:33 1999
@@ -0,0 +1,326 @@
+/* $Id: jade.c,v 1.2 1999/07/01 08:07:57 keil Exp $
+ *
+ * jade.c   JADE stuff (derived from original hscx.c)
+ *
+ * Author   Roland Klabunde (R.Klabunde@Berkom.de)
+ *
+ * $Log: jade.c,v $
+ * Revision 1.2  1999/07/01 08:07:57  keil
+ * Initial version
+ *
+ *
+ */
+
+
+#define __NO_VERSION__
+#include "hisax.h"
+#include "hscx.h"
+#include "jade.h"
+#include "isdnl1.h"
+#include <linux/interrupt.h>
+
+
+HISAX_INITFUNC(int
+JadeVersion(struct IsdnCardState *cs, char *s))
+{
+    int ver,i;
+    int to = 50;
+    cs->BC_Write_Reg(cs, -1, 0x50, 0x19);
+    i=0;
+    while (to) {
+    	udelay(1);
+	ver = cs->BC_Read_Reg(cs, -1, 0x60);
+	to--;
+	if (ver)
+    	    break;
+	if (!to) {
+	    printk(KERN_INFO "%s JADE version not obtainable\n", s);
+    	    return (0);
+        }
+    }
+    /* Wait for the JADE */
+    udelay(10);
+    /* Read version */
+    ver = cs->BC_Read_Reg(cs, -1, 0x60);
+    printk(KERN_INFO "%s JADE version: %d\n", s, ver);
+    return (1);
+}
+
+/* Write to indirect accessible jade register set */
+static void
+jade_write_indirect(struct IsdnCardState *cs, u_char reg, u_char value)
+{
+    int to = 50;
+    long flags;
+    u_char ret;
+    save_flags(flags);
+    cli();
+    /* Write the data */
+    cs->BC_Write_Reg(cs, -1, COMM_JADE+1, value);
+    /* Say JADE we wanna write indirect reg 'reg' */
+    cs->BC_Write_Reg(cs, -1, COMM_JADE, reg);
+    to = 50;
+    /* Wait for RDY goes high */
+    while (to) {
+    	udelay(1);
+	ret = cs->BC_Read_Reg(cs, -1, COMM_JADE);
+	to--;
+	if (ret & 1)
+	    /* Got acknowledge */
+	    break;
+	if (!to) {
+	    restore_flags(flags);
+    	    printk(KERN_INFO "Can not see ready bit from JADE DSP (reg=0x%X, value=0x%X)\n", reg, value);
+	    return;
+	}
+    }
+    restore_flags(flags);
+}
+
+
+
+void
+modejade(struct BCState *bcs, int mode, int bc)
+{
+    struct IsdnCardState *cs = bcs->cs;
+    int jade = bcs->hw.hscx.hscx;
+
+    if (cs->debug & L1_DEB_HSCX) {
+	char tmp[40];
+	sprintf(tmp, "jade %c mode %d ichan %d",
+		'A' + jade, mode, bc);
+	debugl1(cs, tmp);
+    }
+    bcs->mode = mode;
+    bcs->channel = bc;
+	
+    cs->BC_Write_Reg(cs, jade, jade_HDLC_MODE, (mode == L1_MODE_TRANS ? jadeMODE_TMO:0x00));
+    cs->BC_Write_Reg(cs, jade, jade_HDLC_CCR0, (jadeCCR0_PU|jadeCCR0_ITF));
+    cs->BC_Write_Reg(cs, jade, jade_HDLC_CCR1, 0x00);
+
+    jade_write_indirect(cs, jade_HDLC1SERRXPATH, 0x08);
+    jade_write_indirect(cs, jade_HDLC2SERRXPATH, 0x08);
+    jade_write_indirect(cs, jade_HDLC1SERTXPATH, 0x00);
+    jade_write_indirect(cs, jade_HDLC2SERTXPATH, 0x00);
+
+    cs->BC_Write_Reg(cs, jade, jade_HDLC_XCCR, 0x07);
+    cs->BC_Write_Reg(cs, jade, jade_HDLC_RCCR, 0x07);
+
+    if (bc == 0) {
+	cs->BC_Write_Reg(cs, jade, jade_HDLC_TSAX, 0x00);
+	cs->BC_Write_Reg(cs, jade, jade_HDLC_TSAR, 0x00);
+    } else {
+	cs->BC_Write_Reg(cs, jade, jade_HDLC_TSAX, 0x04);
+	cs->BC_Write_Reg(cs, jade, jade_HDLC_TSAR, 0x04);
+    }
+    switch (mode) {
+	case (L1_MODE_NULL):
+		cs->BC_Write_Reg(cs, jade, jade_HDLC_MODE, jadeMODE_TMO);
+		break;
+	case (L1_MODE_TRANS):
+		cs->BC_Write_Reg(cs, jade, jade_HDLC_MODE, (jadeMODE_TMO|jadeMODE_RAC|jadeMODE_XAC));
+		break;
+	case (L1_MODE_HDLC):
+		cs->BC_Write_Reg(cs, jade, jade_HDLC_MODE, (jadeMODE_RAC|jadeMODE_XAC));
+		break;
+    }
+    if (mode) {
+	cs->BC_Write_Reg(cs, jade, jade_HDLC_RCMD, (jadeRCMD_RRES|jadeRCMD_RMC));
+	cs->BC_Write_Reg(cs, jade, jade_HDLC_XCMD, jadeXCMD_XRES);
+	/* Unmask ints */
+	cs->BC_Write_Reg(cs, jade, jade_HDLC_IMR, 0xF8);
+    }
+    else
+	/* Mask ints */
+	cs->BC_Write_Reg(cs, jade, jade_HDLC_IMR, 0x00);
+}
+
+void
+jade_sched_event(struct BCState *bcs, int event)
+{
+    bcs->event |= 1 << event;
+    queue_task(&bcs->tqueue, &tq_immediate);
+    mark_bh(IMMEDIATE_BH);
+}
+
+static void
+jade_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.hscx.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 "jade_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.hscx.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);
+		modejade(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);
+		modejade(st->l1.bcs, 0, st->l1.bc);
+		st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
+		break;
+    }
+}
+
+void
+close_jadestate(struct BCState *bcs)
+{
+    modejade(bcs, 0, bcs->channel);
+    if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
+	if (bcs->hw.hscx.rcvbuf) {
+		kfree(bcs->hw.hscx.rcvbuf);
+		bcs->hw.hscx.rcvbuf = NULL;
+	}
+	if (bcs->blog) {
+		kfree(bcs->blog);
+		bcs->blog = NULL;
+	}
+	discard_queue(&bcs->rqueue);
+	discard_queue(&bcs->squeue);
+	if (bcs->tx_skb) {
+		idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+		bcs->tx_skb = NULL;
+		test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+	}
+    }
+}
+
+static int
+open_jadestate(struct IsdnCardState *cs, struct BCState *bcs)
+{
+	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
+		if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
+			printk(KERN_WARNING
+			       "HiSax: No memory for hscx.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.hscx.rcvbuf);
+			bcs->hw.hscx.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.hscx.rcvidx = 0;
+	bcs->tx_cnt = 0;
+	return (0);
+}
+
+
+int
+setstack_jade(struct PStack *st, struct BCState *bcs)
+{
+	bcs->channel = st->l1.bc;
+	if (open_jadestate(st->l1.hardware, bcs))
+		return (-1);
+	st->l1.bcs = bcs;
+	st->l2.l2l1 = jade_l2l1;
+	setstack_manager(st);
+	bcs->st = st;
+	setstack_l1_B(st);
+	return (0);
+}
+
+HISAX_INITFUNC(void
+clear_pending_jade_ints(struct IsdnCardState *cs))
+{
+	int val;
+	char tmp[64];
+
+	cs->BC_Write_Reg(cs, 0, jade_HDLC_IMR, 0x00);
+	cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0x00);
+
+	val = cs->BC_Read_Reg(cs, 1, jade_HDLC_ISR);
+	sprintf(tmp, "jade B ISTA %x", val);
+	debugl1(cs, tmp);
+	val = cs->BC_Read_Reg(cs, 0, jade_HDLC_ISR);
+	sprintf(tmp, "jade A ISTA %x", val);
+	debugl1(cs, tmp);
+	val = cs->BC_Read_Reg(cs, 1, jade_HDLC_STAR);
+	sprintf(tmp, "jade B STAR %x", val);
+	debugl1(cs, tmp);
+	val = cs->BC_Read_Reg(cs, 0, jade_HDLC_STAR);
+	sprintf(tmp, "jade A STAR %x", val);
+	debugl1(cs, tmp);
+	/* Unmask ints */
+	cs->BC_Write_Reg(cs, 0, jade_HDLC_IMR, 0xF8);
+	cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0xF8);
+}
+
+HISAX_INITFUNC(void
+initjade(struct IsdnCardState *cs))
+{
+	cs->bcs[0].BC_SetStack = setstack_jade;
+	cs->bcs[1].BC_SetStack = setstack_jade;
+	cs->bcs[0].BC_Close = close_jadestate;
+	cs->bcs[1].BC_Close = close_jadestate;
+	cs->bcs[0].hw.hscx.hscx = 0;
+	cs->bcs[1].hw.hscx.hscx = 1;
+
+	/* Stop DSP audio tx/rx */
+	jade_write_indirect(cs, 0x11, 0x0f);
+	jade_write_indirect(cs, 0x17, 0x2f);
+
+	/* Transparent Mode, RxTx inactive, No Test, No RFS/TFS */
+	cs->BC_Write_Reg(cs, 0, jade_HDLC_MODE, jadeMODE_TMO);
+	cs->BC_Write_Reg(cs, 1, jade_HDLC_MODE, jadeMODE_TMO);
+	/* Power down, 1-Idle, RxTx least significant bit first */
+	cs->BC_Write_Reg(cs, 0, jade_HDLC_CCR0, 0x00);
+	cs->BC_Write_Reg(cs, 1, jade_HDLC_CCR0, 0x00);
+	/* Mask all interrupts */
+	cs->BC_Write_Reg(cs, 0, jade_HDLC_IMR,  0x00);
+	cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR,  0x00);
+	/* Setup host access to hdlc controller */
+	jade_write_indirect(cs, jade_HDLCCNTRACCESS, (jadeINDIRECT_HAH1|jadeINDIRECT_HAH2));
+	/* Unmask HDLC int (donŽt forget DSP int later on)*/
+	cs->BC_Write_Reg(cs, -1,jade_INT, (jadeINT_HDLC1|jadeINT_HDLC2));
+
+	/* once again TRANSPARENT */	
+	modejade(cs->bcs, 0, 0);
+	modejade(cs->bcs + 1, 0, 0);
+}
+
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/jade.h linux/drivers/isdn/hisax/jade.h
--- v2.3.13/linux/drivers/isdn/hisax/jade.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/hisax/jade.h	Thu Aug 12 09:42:33 1999
@@ -0,0 +1,137 @@
+/* $Id: jade.h,v 1.2 1999/07/01 08:07:58 keil Exp $
+ * jade.h   JADE specific defines
+ *
+ * Author   Roland Klabunde (R.Klabunde@Berkom.de)
+ *
+ *
+ * $Log: jade.h,v $
+ * Revision 1.2  1999/07/01 08:07:58  keil
+ * Initial version
+ *
+ *
+ */
+
+/* All Registers original Siemens Spec  */
+#ifndef	__JADE_H__
+#define	__JADE_H__
+
+/* Special registers for access to indirect accessible JADE regs */
+#define	DIRECT_IO_JADE	0x0000	/* Jade direct io access area */
+#define	COMM_JADE	0x0040	/* Jade communication area */	   	
+
+/********************************************************************/
+/* JADE-HDLC registers         									    */
+/********************************************************************/
+#define jade_HDLC_RFIFO	   				0x00				   /* R */
+#define jade_HDLC_XFIFO	   				0x00				   /* W */
+
+#define	jade_HDLC_STAR	   				0x20				   /* R */
+	#define	jadeSTAR_XDOV				0x80
+	#define	jadeSTAR_XFW 				0x40 /* Does not work*/
+	#define	jadeSTAR_XCEC 				0x20
+	#define	jadeSTAR_RCEC				0x10
+	#define	jadeSTAR_BSY 				0x08
+	#define	jadeSTAR_RNA 				0x04
+	#define	jadeSTAR_STR 				0x02
+	#define	jadeSTAR_STX				0x01
+
+#define	jade_HDLC_XCMD	   				0x20				   /* W */
+	#define	jadeXCMD_XF				0x80
+	#define	jadeXCMD_XME				0x40
+	#define	jadeXCMD_XRES				0x20
+	#define	jadeXCMD_STX				0x01
+
+#define	jade_HDLC_RSTA	   				0x21				   /* R */
+    #define	jadeRSTA_VFR				0x80
+    #define	jadeRSTA_RDO				0x40
+    #define	jadeRSTA_CRC				0x20
+    #define	jadeRSTA_RAB				0x10
+    #define	jadeRSTA_MASK			   	0xF0
+
+#define	jade_HDLC_MODE					0x22				   /* RW*/
+    #define	jadeMODE_TMO				0x80
+    #define	jadeMODE_RAC				0x40
+    #define	jadeMODE_XAC				0x20
+    #define	jadeMODE_TLP				0x10
+    #define	jadeMODE_ERFS				0x02
+    #define	jadeMODE_ETFS				0x01
+
+#define	jade_HDLC_RBCH					0x24				   /* R */
+
+#define	jade_HDLC_RBCL	 				0x25				   /* R */
+#define	jade_HDLC_RCMD	 				0x25				   /* W */
+	#define	jadeRCMD_RMC 				0x80
+	#define	jadeRCMD_RRES				0x40
+	#define	jadeRCMD_RMD				0x20
+	#define	jadeRCMD_STR				0x02
+
+#define	jade_HDLC_CCR0					0x26				   /* RW*/
+	#define	jadeCCR0_PU  				0x80
+	#define	jadeCCR0_ITF				0x40
+	#define	jadeCCR0_C32				0x20
+	#define	jadeCCR0_CRL				0x10
+	#define	jadeCCR0_RCRC				0x08
+	#define	jadeCCR0_XCRC				0x04
+	#define	jadeCCR0_RMSB				0x02
+	#define	jadeCCR0_XMSB				0x01
+
+#define	jade_HDLC_CCR1					0x27				   /* RW*/
+    #define	jadeCCR1_RCS0				0x80
+    #define	jadeCCR1_RCONT				0x40
+    #define	jadeCCR1_RFDIS				0x20
+    #define	jadeCCR1_XCS0				0x10
+    #define	jadeCCR1_XCONT				0x08
+    #define	jadeCCR1_XFDIS				0x04
+
+#define	jade_HDLC_TSAR					0x28				   /* RW*/
+#define	jade_HDLC_TSAX					0x29				   /* RW*/
+#define	jade_HDLC_RCCR					0x2A				   /* RW*/
+#define	jade_HDLC_XCCR					0x2B				   /* RW*/
+
+#define	jade_HDLC_ISR 					0x2C				   /* R */
+#define	jade_HDLC_IMR 					0x2C				   /* W */
+	#define	jadeISR_RME					0x80
+	#define	jadeISR_RPF					0x40
+	#define	jadeISR_RFO					0x20
+	#define	jadeISR_XPR					0x10
+	#define	jadeISR_XDU					0x08
+	#define	jadeISR_ALLS				0x04
+
+#define jade_INT            			0x75
+    #define jadeINT_HDLC1   			0x02
+    #define jadeINT_HDLC2   			0x01
+    #define jadeINT_DSP				0x04
+#define jade_INTR            			0x70
+
+/********************************************************************/
+/* Indirect accessible JADE registers of common interest		   	*/
+/********************************************************************/
+#define	jade_CHIPVERSIONNR				0x00 /* Does not work*/
+
+#define	jade_HDLCCNTRACCESS				0x10		
+	#define	jadeINDIRECT_HAH1			0x02
+	#define	jadeINDIRECT_HAH2			0x01
+
+#define	jade_HDLC1SERRXPATH				0x1D
+#define	jade_HDLC1SERTXPATH				0x1E
+#define	jade_HDLC2SERRXPATH				0x1F
+#define	jade_HDLC2SERTXPATH				0x20
+	#define	jadeINDIRECT_SLIN1			0x10
+	#define	jadeINDIRECT_SLIN0			0x08
+	#define	jadeINDIRECT_LMOD1			0x04
+	#define	jadeINDIRECT_LMOD0			0x02
+	#define	jadeINDIRECT_HHR			0x01
+	#define	jadeINDIRECT_HHX			0x01
+
+#define	jade_RXAUDIOCH1CFG				0x11
+#define	jade_RXAUDIOCH2CFG				0x14
+#define	jade_TXAUDIOCH1CFG				0x17
+#define	jade_TXAUDIOCH2CFG				0x1A
+
+extern int JadeVersion(struct IsdnCardState *cs, char *s);
+extern void jade_sched_event(struct BCState *bcs, int event);
+extern void modejade(struct BCState *bcs, int mode, int bc);
+extern void clear_pending_jade_ints(struct IsdnCardState *cs);
+extern void initjade(struct IsdnCardState *cs);
+
+#endif	/* __JADE_H__ */
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/jade_irq.c linux/drivers/isdn/hisax/jade_irq.c
--- v2.3.13/linux/drivers/isdn/hisax/jade_irq.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/hisax/jade_irq.c	Thu Aug 12 09:42:33 1999
@@ -0,0 +1,247 @@
+/* $Id: jade_irq.c,v 1.2 1999/07/01 08:07:59 keil Exp $
+ *
+ * jade_irq.c   Low level JADE IRQ stuff (derived from original hscx_irq.c)
+ *
+ * Author   Roland Klabunde (R.Klabunde@Berkom.de)
+ *
+ * $Log: jade_irq.c,v $
+ * Revision 1.2  1999/07/01 08:07:59  keil
+ * Initial version
+ *
+ *
+ */
+
+static inline void
+waitforCEC(struct IsdnCardState *cs, int jade, int reg)
+{
+  	int to = 50;
+  	int mask = (reg == jade_HDLC_XCMD ? jadeSTAR_XCEC : jadeSTAR_RCEC);
+  	while ((READJADE(cs, jade, jade_HDLC_STAR) & mask) && to) {
+  		udelay(1);
+  		to--;
+  	}
+  	if (!to)
+  		printk(KERN_WARNING "HiSax: waitforCEC (jade) timeout\n");
+}
+
+
+static inline void
+waitforXFW(struct IsdnCardState *cs, int jade)
+{
+  	/* Does not work on older jade versions, don't care */
+}
+
+static inline void
+WriteJADECMDR(struct IsdnCardState *cs, int jade, int reg, u_char data)
+{
+	long flags;
+
+	save_flags(flags);
+	cli();
+	waitforCEC(cs, jade, reg);
+	WRITEJADE(cs, jade, reg, data);
+	restore_flags(flags);
+}
+
+
+
+static void
+jade_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, "jade_empty_fifo");
+
+	if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) {
+		if (cs->debug & L1_DEB_WARN)
+			debugl1(cs, "jade_empty_fifo: incoming packet too large");
+		WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_RCMD, jadeRCMD_RMC);
+		bcs->hw.hscx.rcvidx = 0;
+		return;
+	}
+	ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
+	bcs->hw.hscx.rcvidx += count;
+	save_flags(flags);
+	cli();
+	READJADEFIFO(cs, bcs->hw.hscx.hscx, ptr, count);
+	WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_RCMD, jadeRCMD_RMC);
+	restore_flags(flags);
+	if (cs->debug & L1_DEB_HSCX_FIFO) {
+		char *t = bcs->blog;
+
+		t += sprintf(t, "jade_empty_fifo %c cnt %d",
+			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
+		QuickHex(t, ptr, count);
+		debugl1(cs, bcs->blog);
+	}
+}
+
+static void
+jade_fill_fifo(struct BCState *bcs)
+{
+	struct IsdnCardState *cs = bcs->cs;
+	int more, count;
+	int fifo_size = 32;
+	u_char *ptr;
+	long flags;
+
+	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+		debugl1(cs, "jade_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 > fifo_size) {
+		more = !0;
+		count = fifo_size;
+	} else
+		count = bcs->tx_skb->len;
+
+	waitforXFW(cs, bcs->hw.hscx.hscx);
+	save_flags(flags);
+	cli();
+	ptr = bcs->tx_skb->data;
+	skb_pull(bcs->tx_skb, count);
+	bcs->tx_cnt -= count;
+	bcs->hw.hscx.count += count;
+	WRITEJADEFIFO(cs, bcs->hw.hscx.hscx, ptr, count);
+	WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_XCMD, more ? jadeXCMD_XF : (jadeXCMD_XF|jadeXCMD_XME));
+	restore_flags(flags);
+	if (cs->debug & L1_DEB_HSCX_FIFO) {
+		char *t = bcs->blog;
+
+		t += sprintf(t, "jade_fill_fifo %c cnt %d",
+			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
+		QuickHex(t, ptr, count);
+		debugl1(cs, bcs->blog);
+	}
+}
+
+
+static inline void
+jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade)
+{
+	u_char r;
+	struct BCState *bcs = cs->bcs + jade;
+	struct sk_buff *skb;
+	int fifo_size = 32;
+	int count;
+	int i_jade = (int) jade; /* To satisfy the compiler */
+	
+	if (!test_bit(BC_FLG_INIT, &bcs->Flag))
+		return;
+
+	if (val & 0x80) {	/* RME */
+		r = READJADE(cs, i_jade, jade_HDLC_RSTA);
+		if ((r & 0xf0) != 0xa0) {
+			if (!(r & 0x80))
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "JADE %s invalid frame", (jade ? "B":"A"));
+			if ((r & 0x40) && bcs->mode)
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "JADE %c RDO mode=%d", 'A'+jade, bcs->mode);
+			if (!(r & 0x20))
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "JADE %c CRC error", 'A'+jade);
+			WriteJADECMDR(cs, jade, jade_HDLC_RCMD, jadeRCMD_RMC);
+		} else {
+			count = READJADE(cs, i_jade, jade_HDLC_RBCL) & 0x1F;
+			if (count == 0)
+				count = fifo_size;
+			jade_empty_fifo(bcs, count);
+			if ((count = bcs->hw.hscx.rcvidx - 1) > 0) {
+				if (cs->debug & L1_DEB_HSCX_FIFO)
+					debugl1(cs, "HX Frame %d", count);
+				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);
+				}
+			}
+		}
+		bcs->hw.hscx.rcvidx = 0;
+		jade_sched_event(bcs, B_RCVBUFREADY);
+	}
+	if (val & 0x40) {	/* RPF */
+		jade_empty_fifo(bcs, fifo_size);
+		if (bcs->mode == L1_MODE_TRANS) {
+			/* receive audio data */
+			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);
+			}
+			bcs->hw.hscx.rcvidx = 0;
+			jade_sched_event(bcs, B_RCVBUFREADY);
+		}
+	}
+	if (val & 0x10) {	/* XPR */
+		if (bcs->tx_skb) {
+			if (bcs->tx_skb->len) {
+				jade_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.hscx.count);
+				idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+				bcs->hw.hscx.count = 0;
+				bcs->tx_skb = NULL;
+			}
+		}
+		if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+			bcs->hw.hscx.count = 0;
+			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+			jade_fill_fifo(bcs);
+		} else {
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+			jade_sched_event(bcs, B_XMTBUFREADY);
+		}
+	}
+}
+
+static inline void
+jade_int_main(struct IsdnCardState *cs, u_char val, int jade)
+{
+	struct BCState *bcs;
+	bcs = cs->bcs + jade;
+	
+	if (val & jadeISR_RFO) {
+		/* handled with RDO */
+		val &= ~jadeISR_RFO;
+	}
+	if (val & jadeISR_XDU) {
+		/* relevant in HDLC mode only */
+		/* don't reset XPR here */
+		if (bcs->mode == 1)
+			jade_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.hscx.count);
+				bcs->tx_cnt += bcs->hw.hscx.count;
+				bcs->hw.hscx.count = 0;
+			}
+			WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_XCMD, jadeXCMD_XRES);
+			if (cs->debug & L1_DEB_WARN)
+				debugl1(cs, "JADE %c EXIR %x Lost TX", 'A'+jade, val);
+		}
+	}
+	if (val & (jadeISR_RME|jadeISR_RPF|jadeISR_XPR)) {
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "JADE %c interrupt %x", 'A'+jade, val);
+		jade_interrupt(cs, val, jade);
+	}
+}
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/l3_1tr6.c linux/drivers/isdn/hisax/l3_1tr6.c
--- v2.3.13/linux/drivers/isdn/hisax/l3_1tr6.c	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/hisax/l3_1tr6.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: l3_1tr6.c,v 2.8 1998/11/15 23:55:08 keil Exp $
+/* $Id: l3_1tr6.c,v 2.9 1999/07/01 08:11:55 keil Exp $
 
  *  German 1TR6 D-channel protocol
  *
@@ -10,6 +10,9 @@
  *
  *
  * $Log: l3_1tr6.c,v $
+ * Revision 2.9  1999/07/01 08:11:55  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 2.8  1998/11/15 23:55:08  keil
  * changes from 2.0
  *
@@ -56,7 +59,7 @@
 #include <linux/ctype.h>
 
 extern char *HiSax_getrev(const char *revision);
-const char *l3_1tr6_revision = "$Revision: 2.8 $";
+const char *l3_1tr6_revision = "$Revision: 2.9 $";
 
 #define MsgHead(ptr, cref, mty, dis) \
 	*ptr++ = dis; \
@@ -91,14 +94,14 @@
 {
 	struct sk_buff *skb = arg;
 
-	dev_kfree_skb(skb);
+	idev_kfree_skb(skb, FREE_READ);
 	l3_1tr6_release_req(pc, 0, NULL);
 }
 
 static void
 l3_1tr6_error(struct l3_process *pc, u_char *msg, struct sk_buff *skb)
 {
-	dev_kfree_skb(skb);
+	idev_kfree_skb(skb, FREE_READ);
 	if (pc->st->l3.debug & L3_DEB_WARN)
 		l3_debug(pc->st, msg);
 	l3_1tr6_release_req(pc, 0, NULL);
@@ -248,7 +251,7 @@
 		if ((FAC_SPV == p[3]) || (FAC_Activate == p[3]))
 			pc->para.spv = 1;
 	}
-	dev_kfree_skb(skb);
+	idev_kfree_skb(skb, FREE_READ);
 
 	/* Signal all services, linklevel takes care of Service-Indicator */
 	if (bcfound) {
@@ -287,7 +290,7 @@
 		l3_1tr6_error(pc, "missing setup_ack WE0_chanID", skb);
 		return;
 	}
-	dev_kfree_skb(skb);
+	idev_kfree_skb(skb, FREE_READ);
 	L3AddTimer(&pc->timer, T304, CC_T304);
 	pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);
 }
@@ -318,7 +321,7 @@
 		l3_1tr6_error(pc, "missing call sent WE0_chanID", skb);
 		return;
 	}
-	dev_kfree_skb(skb);
+	idev_kfree_skb(skb, FREE_READ);
 	L3AddTimer(&pc->timer, T310, CC_T310);
 	newl3state(pc, 3);
 	pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc);
@@ -329,7 +332,7 @@
 {
 	struct sk_buff *skb = arg;
 
-	dev_kfree_skb(skb);
+	idev_kfree_skb(skb, FREE_READ);
 	L3DelTimer(&pc->timer);	/* T304 */
 	newl3state(pc, 4);
 	pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc);
@@ -360,7 +363,7 @@
 		}
 	} else if (pc->st->l3.debug & L3_DEB_CHARGE)
 		l3_debug(pc->st, "charging info not found");
-	dev_kfree_skb(skb);
+	idev_kfree_skb(skb, FREE_READ);
 
 }
 
@@ -369,7 +372,7 @@
 {
 	struct sk_buff *skb = arg;
 
-	dev_kfree_skb(skb);
+	idev_kfree_skb(skb, FREE_READ);
 }
 
 static void
@@ -383,7 +386,7 @@
 		return;
 	}
 	newl3state(pc, 10);
-	dev_kfree_skb(skb);
+	idev_kfree_skb(skb, FREE_READ);
 	pc->para.chargeinfo = 0;
 	pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc);
 }
@@ -407,11 +410,11 @@
 			pc->para.loc = 0;
 		}
 	} else {
-		pc->para.cause = -1;
+		pc->para.cause = NO_CAUSE;
 		l3_1tr6_error(pc, "missing REL cause", skb);
 		return;
 	}
-	dev_kfree_skb(skb);
+	idev_kfree_skb(skb, FREE_READ);
 	StopAllL3Timer(pc);
 	newl3state(pc, 0);
 	l3_1TR6_message(pc, MT_N1_REL_ACK, PROTO_DIS_N1);
@@ -424,10 +427,10 @@
 {
 	struct sk_buff *skb = arg;
 
-	dev_kfree_skb(skb);
+	idev_kfree_skb(skb, FREE_READ);
 	StopAllL3Timer(pc);
 	newl3state(pc, 0);
-	pc->para.cause = -1;
+	pc->para.cause = NO_CAUSE;
 	pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc);
 	release_l3_process(pc);
 }
@@ -475,13 +478,13 @@
 	} else {
 		if (pc->st->l3.debug & L3_DEB_WARN)
 			l3_debug(pc->st, "cause not found");
-		pc->para.cause = -1;
+		pc->para.cause = NO_CAUSE;
 	}
 	if (!findie(skb->data, skb->len, WE6_date, 6)) {
 		l3_1tr6_error(pc, "missing connack date", skb);
 		return;
 	}
-	dev_kfree_skb(skb);
+	idev_kfree_skb(skb, FREE_READ);
 	newl3state(pc, 12);
 	pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc);
 }
@@ -496,7 +499,7 @@
 		l3_1tr6_error(pc, "missing connack date", skb);
 		return;
 	}
-	dev_kfree_skb(skb);
+	idev_kfree_skb(skb, FREE_READ);
 	newl3state(pc, 10);
 	pc->para.chargeinfo = 0;
 	L3DelTimer(&pc->timer);
@@ -567,6 +570,9 @@
 		case 0x10:
 			clen = 0;
 			break;
+                case 0x11:
+                        cause = CAUSE_UserBusy;
+                        break;
 		case 0x15:
 			cause = CAUSE_CallRejected;
 			break;
@@ -620,7 +626,7 @@
 	u_char clen = 1;
 
 	L3DelTimer(&pc->timer);
-	if (pc->para.cause > 0)
+	if (pc->para.cause != NO_CAUSE)
 		cause = pc->para.cause;
 	/* Map DSS1 causes */
 	switch (cause & 0x7f) {
@@ -679,6 +685,24 @@
 	pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc);
 	release_l3_process(pc);
 }
+
+static void
+l3_1tr6_dl_reset(struct l3_process *pc, u_char pr, void *arg)
+{
+        pc->para.cause = CAUSE_LocalProcErr;
+        l3_1tr6_disconnect_req(pc, pr, NULL);
+        pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
+}
+
+static void
+l3_1tr6_dl_release(struct l3_process *pc, u_char pr, void *arg)
+{
+        newl3state(pc, 0);
+        pc->para.cause = 0x1b;          /* Destination out of order */
+        pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
+        release_l3_process(pc);
+}
+
 /* *INDENT-OFF* */
 static struct stateentry downstl[] =
 {
@@ -689,8 +713,6 @@
     	 CC_DISCONNECT | REQUEST, l3_1tr6_disconnect_req},
 	{SBIT(12),
 	 CC_RELEASE | REQUEST, l3_1tr6_release_req},
-	{ALL_STATES,
-	 CC_DLRL | REQUEST, l3_1tr6_reset},
 	{SBIT(6),
 	 CC_IGNORE | REQUEST, l3_1tr6_reset},
 	{SBIT(6),
@@ -751,11 +773,22 @@
 	{SBIT(19),
 	 MT_N1_REL_ACK, l3_1tr6_rel_ack}
 };
-/* *INDENT-ON* */
 
 #define DATASTLN1_LEN \
 	(sizeof(datastln1) / sizeof(struct stateentry))
 
+static struct stateentry manstatelist[] =
+{
+        {SBIT(2),
+         DL_ESTABLISH | INDICATION, l3_1tr6_dl_reset},
+        {ALL_STATES,
+         DL_RELEASE | INDICATION, l3_1tr6_dl_release},
+};
+ 
+#define MANSLLEN \
+        (sizeof(manstatelist) / sizeof(struct stateentry))
+/* *INDENT-ON* */
+
 static void
 up1tr6(struct PStack *st, int pr, void *arg)
 {
@@ -778,20 +811,20 @@
 	}
 	if (skb->len < 4) {
 		if (st->l3.debug & L3_DEB_PROTERR) {
-			sprintf(tmp, "up1tr6 len only %ld", skb->len);
+			sprintf(tmp, "up1tr6 len only %d", skb->len);
 			l3_debug(st, tmp);
 		}
-		dev_kfree_skb(skb);
+		idev_kfree_skb(skb, FREE_READ);
 		return;
 	}
 	if ((skb->data[0] & 0xfe) != PROTO_DIS_N0) {
 		if (st->l3.debug & L3_DEB_PROTERR) {
-			sprintf(tmp, "up1tr6%sunexpected discriminator %x message len %ld",
+			sprintf(tmp, "up1tr6%sunexpected discriminator %x message len %d",
 				(pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
 				skb->data[0], skb->len);
 			l3_debug(st, tmp);
 		}
-		dev_kfree_skb(skb);
+		idev_kfree_skb(skb, FREE_READ);
 		return;
 	}
 	if (skb->data[1] != 1) {
@@ -799,13 +832,13 @@
 			sprintf(tmp, "up1tr6 CR len not 1");
 			l3_debug(st, tmp);
 		}
-		dev_kfree_skb(skb);
+		idev_kfree_skb(skb, FREE_READ);
 		return;
 	}
 	cr = skb->data[2];
 	mt = skb->data[3];
 	if (skb->data[0] == PROTO_DIS_N0) {
-		dev_kfree_skb(skb);
+		idev_kfree_skb(skb, FREE_READ);
 		if (st->l3.debug & L3_DEB_STATE) {
 			sprintf(tmp, "up1tr6%s N0 mt %x unhandled",
 			     (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", mt);
@@ -820,11 +853,11 @@
 							sprintf(tmp, "up1tr6 no roc mem");
 							l3_debug(st, tmp);
 						}
-						dev_kfree_skb(skb);
+						idev_kfree_skb(skb, FREE_READ);
 						return;
 					}
 				} else {
-					dev_kfree_skb(skb);
+					idev_kfree_skb(skb, FREE_READ);
 					return;
 				}
 			} else if ((mt == MT_N1_REL) || (mt == MT_N1_REL_ACK) ||
@@ -832,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)) {
-				dev_kfree_skb(skb);
+				idev_kfree_skb(skb, FREE_READ);
 				return;
 			} else {
 				if (!(proc = new_l3_process(st, cr))) {
@@ -840,7 +873,7 @@
 						sprintf(tmp, "up1tr6 no roc mem");
 						l3_debug(st, tmp);
 					}
-					dev_kfree_skb(skb);
+					idev_kfree_skb(skb, FREE_READ);
 					return;
 				}
 				mt = MT_N1_INVALID;
@@ -851,7 +884,7 @@
 			    ((1 << proc->state) & datastln1[i].state))
 				break;
 		if (i == DATASTLN1_LEN) {
-			dev_kfree_skb(skb);
+			idev_kfree_skb(skb, FREE_READ);
 			if (st->l3.debug & L3_DEB_STATE) {
 				sprintf(tmp, "up1tr6%sstate %d mt %x unhandled",
 				  (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
@@ -879,7 +912,7 @@
 	struct Channel *chan;
 	char tmp[80];
 
-	if (((DL_ESTABLISH | REQUEST)== pr) || ((DL_RELEASE | REQUEST)== pr)) {
+	if ((DL_ESTABLISH | REQUEST)== pr) {
 		l3_msg(st, pr, NULL);
 		return;
 	} else if ((CC_SETUP | REQUEST) == pr) {
@@ -918,6 +951,34 @@
 	}
 }
 
+static void
+man1tr6(struct PStack *st, int pr, void *arg)
+{
+        int i;
+        struct l3_process *proc = arg;
+ 
+        if (!proc) {
+                printk(KERN_ERR "HiSax man1tr6 without proc pr=%04x\n", pr);
+                return;
+        }
+        for (i = 0; i < MANSLLEN; i++)
+                if ((pr == manstatelist[i].primitive) &&
+                    ((1 << proc->state) & manstatelist[i].state))
+                        break;
+        if (i == MANSLLEN) {
+                if (st->l3.debug & L3_DEB_STATE) {
+                        l3_debug(st, "cr %d man1tr6 state %d prim %d unhandled",
+                                proc->callref & 0x7f, proc->state, pr);
+                }
+        } else {
+                if (st->l3.debug & L3_DEB_STATE) {
+                        l3_debug(st, "cr %d man1tr6 state %d prim %d",
+                                proc->callref & 0x7f, proc->state, pr);
+                }
+                manstatelist[i].rout(proc, pr, arg);
+        }
+}
+ 
 void
 setstack_1tr6(struct PStack *st)
 {
@@ -925,6 +986,7 @@
 
 	st->lli.l4l3 = down1tr6;
 	st->l2.l2l3 = up1tr6;
+	st->l3.l3ml3 = man1tr6;
 	st->l3.N303 = 0;
 
 	strcpy(tmp, l3_1tr6_revision);
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/l3dss1.c linux/drivers/isdn/hisax/l3dss1.c
--- v2.3.13/linux/drivers/isdn/hisax/l3dss1.c	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/hisax/l3dss1.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: l3dss1.c,v 2.12 1998/11/15 23:55:10 keil Exp $
+/* $Id: l3dss1.c,v 2.18 1999/08/11 20:54:39 keil Exp $
 
  * EURO/DSS1 D-channel protocol
  *
@@ -13,6 +13,21 @@
  *              Fritz Elfert
  *
  * $Log: l3dss1.c,v $
+ * Revision 2.18  1999/08/11 20:54:39  keil
+ * High layer compatibility is valid in SETUP
+ *
+ * Revision 2.17  1999/07/25 16:18:25  keil
+ * Fix Suspend/Resume
+ *
+ * Revision 2.16  1999/07/21 14:46:23  keil
+ * changes from EICON certification
+ *
+ * Revision 2.14  1999/07/09 08:30:08  keil
+ * cosmetics
+ *
+ * Revision 2.13  1999/07/01 08:11:58  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 2.12  1998/11/15 23:55:10  keil
  * changes from 2.0
  *
@@ -72,29 +87,227 @@
 #include <linux/ctype.h>
 
 extern char *HiSax_getrev(const char *revision);
-const char *dss1_revision = "$Revision: 2.12 $";
+const char *dss1_revision = "$Revision: 2.18 $";
+
+#define EXT_BEARER_CAPS 1
 
 #define	MsgHead(ptr, cref, mty) \
 	*ptr++ = 0x8; \
-	*ptr++ = 0x1; \
-	*ptr++ = cref^0x80; \
+	if (cref == -1) { \
+		*ptr++ = 0x0; \
+	} else { \
+		*ptr++ = 0x1; \
+		*ptr++ = cref^0x80; \
+	} \
 	*ptr++ = mty
 
 
-#if HISAX_DE_AOC
+/**********************************************/
+/* get a new invoke id for remote operations. */
+/* Only a return value != 0 is valid          */
+/**********************************************/
+static unsigned char new_invoke_id(struct PStack *p)
+{
+	unsigned char retval;
+	int flags,i;
+  
+	i = 32; /* maximum search depth */
+
+	save_flags(flags);
+	cli();
+
+	retval = p->prot.dss1.last_invoke_id + 1; /* try new id */
+	while ((i) && (p->prot.dss1.invoke_used[retval >> 3] == 0xFF)) {
+		p->prot.dss1.last_invoke_id = (retval & 0xF8) + 8;
+		i--;
+	}  
+	if (i) {
+		while (p->prot.dss1.invoke_used[retval >> 3] & (1 << (retval & 7)))
+		retval++; 
+	} else
+		retval = 0;
+	p->prot.dss1.last_invoke_id = retval;
+	p->prot.dss1.invoke_used[retval >> 3] |= (1 << (retval & 7));
+	restore_flags(flags);
+
+	return(retval);  
+} /* new_invoke_id */
+
+/*************************/
+/* free a used invoke id */
+/*************************/
+static void free_invoke_id(struct PStack *p, unsigned char id)
+{ int flags;
+
+  if (!id) return; /* 0 = invalid value */
+
+  save_flags(flags);
+  cli();
+  p->prot.dss1.invoke_used[id >> 3] &= ~(1 << (id & 7));
+  restore_flags(flags);
+} /* free_invoke_id */  
+
+
+/**********************************************************/
+/* create a new l3 process and fill in dss1 specific data */
+/**********************************************************/
+static struct l3_process
+*dss1_new_l3_process(struct PStack *st, int cr)
+{  struct l3_process *proc;
+
+   if (!(proc = new_l3_process(st, cr))) 
+     return(NULL);
+
+   proc->prot.dss1.invoke_id = 0;
+   proc->prot.dss1.remote_operation = 0;
+   proc->prot.dss1.uus1_data[0] = '\0';
+   
+   return(proc);
+} /* dss1_new_l3_process */
+
+/************************************************/
+/* free a l3 process and all dss1 specific data */
+/************************************************/ 
+static void
+dss1_release_l3_process(struct l3_process *p)
+{
+   free_invoke_id(p->st,p->prot.dss1.invoke_id);
+   release_l3_process(p);
+} /* dss1_release_l3_process */
+ 
+/********************************************************/
+/* search a process with invoke id id and dummy callref */
+/********************************************************/
+static struct l3_process *
+l3dss1_search_dummy_proc(struct PStack *st, int id)
+{ struct l3_process *pc = st->l3.proc; /* start of processes */
+
+  if (!id) return(NULL);
+
+  while (pc)
+   { if ((pc->callref == -1) && (pc->prot.dss1.invoke_id == id))
+       return(pc);
+     pc = pc->next;
+   } 
+  return(NULL);
+} /* l3dss1_search_dummy_proc */
+
+/*******************************************************************/
+/* called when a facility message with a dummy callref is received */
+/* and a return result is delivered. id specifies the invoke id.   */
+/*******************************************************************/ 
+static void 
+l3dss1_dummy_return_result(struct PStack *st, int id, u_char *p, u_char nlen)
+{ isdn_ctrl ic;
+  struct IsdnCardState *cs;
+  struct l3_process *pc = NULL; 
+
+  if ((pc = l3dss1_search_dummy_proc(st, id)))
+   { L3DelTimer(&pc->timer); /* remove timer */
+
+     cs = pc->st->l1.hardware;
+     ic.driver = cs->myid;
+     ic.command = ISDN_STAT_PROT;
+     ic.arg = DSS1_STAT_INVOKE_RES;
+     ic.parm.dss1_io.hl_id = pc->prot.dss1.invoke_id;
+     ic.parm.dss1_io.ll_id = pc->prot.dss1.ll_id;
+     ic.parm.dss1_io.proc = pc->prot.dss1.proc;
+     ic.parm.dss1_io.timeout= 0;
+     ic.parm.dss1_io.datalen = nlen;
+     ic.parm.dss1_io.data = p;
+     free_invoke_id(pc->st, pc->prot.dss1.invoke_id);
+     pc->prot.dss1.invoke_id = 0; /* reset id */
+
+     cs->iif.statcallb(&ic);
+     dss1_release_l3_process(pc); 
+   }
+  else
+   l3_debug(st, "dummy return result id=0x%x result len=%d",id,nlen);
+} /* l3dss1_dummy_return_result */
+
+/*******************************************************************/
+/* called when a facility message with a dummy callref is received */
+/* and a return error is delivered. id specifies the invoke id.    */
+/*******************************************************************/ 
+static void 
+l3dss1_dummy_error_return(struct PStack *st, int id, ulong error)
+{ isdn_ctrl ic;
+  struct IsdnCardState *cs;
+  struct l3_process *pc = NULL; 
+
+  if ((pc = l3dss1_search_dummy_proc(st, id)))
+   { L3DelTimer(&pc->timer); /* remove timer */
+
+     cs = pc->st->l1.hardware;
+     ic.driver = cs->myid;
+     ic.command = ISDN_STAT_PROT;
+     ic.arg = DSS1_STAT_INVOKE_ERR;
+     ic.parm.dss1_io.hl_id = pc->prot.dss1.invoke_id;
+     ic.parm.dss1_io.ll_id = pc->prot.dss1.ll_id;
+     ic.parm.dss1_io.proc = pc->prot.dss1.proc;
+     ic.parm.dss1_io.timeout= error;
+     ic.parm.dss1_io.datalen = 0;
+     ic.parm.dss1_io.data = NULL;
+     free_invoke_id(pc->st, pc->prot.dss1.invoke_id);
+     pc->prot.dss1.invoke_id = 0; /* reset id */
+
+     cs->iif.statcallb(&ic);
+     dss1_release_l3_process(pc); 
+   }
+  else
+   l3_debug(st, "dummy return error id=0x%x error=0x%lx",id,error);
+} /* l3dss1_error_return */
+
+/*******************************************************************/
+/* called when a facility message with a dummy callref is received */
+/* and a invoke is delivered. id specifies the invoke id.          */
+/*******************************************************************/ 
+static void 
+l3dss1_dummy_invoke(struct PStack *st, int cr, int id, 
+                    int ident, u_char *p, u_char nlen)
+{ isdn_ctrl ic;
+  struct IsdnCardState *cs;
+  
+  l3_debug(st, "dummy invoke %s id=0x%x ident=0x%x datalen=%d",
+               (cr == -1) ? "local" : "broadcast",id,ident,nlen);
+  if (cr >= -1) return; /* ignore local data */
+
+  cs = st->l1.hardware;
+  ic.driver = cs->myid;
+  ic.command = ISDN_STAT_PROT;
+  ic.arg = DSS1_STAT_INVOKE_BRD;
+  ic.parm.dss1_io.hl_id = id;
+  ic.parm.dss1_io.ll_id = 0;
+  ic.parm.dss1_io.proc = ident;
+  ic.parm.dss1_io.timeout= 0;
+  ic.parm.dss1_io.datalen = nlen;
+  ic.parm.dss1_io.data = p;
+
+  cs->iif.statcallb(&ic);
+} /* l3dss1_dummy_invoke */
+
 static void
-l3dss1_parse_facility(struct l3_process *pc, u_char * p)
+l3dss1_parse_facility(struct PStack *st, struct l3_process *pc,
+                      int cr, u_char * p)
 {
 	int qd_len = 0;
+	unsigned char nlen = 0, ilen, cp_tag;
+	int ident, id;
+	ulong err_ret;
+
+	if (pc) 
+		st = pc->st; /* valid Stack */
+	else
+		if ((!st) || (cr >= 0)) return; /* neither pc nor st specified */
 
 	p++;
 	qd_len = *p++;
 	if (qd_len == 0) {
-		l3_debug(pc->st, "qd_len == 0");
+		l3_debug(st, "qd_len == 0");
 		return;
 	}
 	if ((*p & 0x1F) != 0x11) {	/* Service discriminator, supplementary service */
-		l3_debug(pc->st, "supplementary service != 0x11");
+		l3_debug(st, "supplementary service != 0x11");
 		return;
 	}
 	while (qd_len > 0 && !(*p & 0x80)) {	/* extension ? */
@@ -102,72 +315,92 @@
 		qd_len--;
 	}
 	if (qd_len < 2) {
-		l3_debug(pc->st, "qd_len < 2");
+		l3_debug(st, "qd_len < 2");
 		return;
 	}
 	p++;
 	qd_len--;
 	if ((*p & 0xE0) != 0xA0) {	/* class and form */
-		l3_debug(pc->st, "class and form != 0xA0");
+		l3_debug(st, "class and form != 0xA0");
 		return;
 	}
-	switch (*p & 0x1F) {	/* component tag */
-		case 1:	/* invoke */
-			{
-				unsigned char nlen = 0, ilen;
-				int ident;
-
-				p++;
-				qd_len--;
-				if (qd_len < 1) {
-					l3_debug(pc->st, "qd_len < 1");
-					break;
-				}
-				if (*p & 0x80) {	/* length format */
-					l3_debug(pc->st, "*p & 0x80 length format");
-					break;
-				}
-				nlen = *p++;
-				qd_len--;
-				if (qd_len < nlen) {
-					l3_debug(pc->st, "qd_len < nlen");
-					return;
-				}
-				qd_len -= nlen;
+       
+        cp_tag = *p & 0x1F; /* remember tag value */
 
-				if (nlen < 2) {
-					l3_debug(pc->st, "nlen < 2");
-					return;
-				}
-				if (*p != 0x02) {	/* invoke identifier tag */
-					l3_debug(pc->st, "invoke identifier tag !=0x02");
-					return;
-				}
-				p++;
-				nlen--;
-				if (*p & 0x80) {	/* length format */
-					l3_debug(pc->st, "*p & 0x80 length format 2");
-					break;
-				}
-				ilen = *p++;
-				nlen--;
-				if (ilen > nlen || ilen == 0) {
-					l3_debug(pc->st, "ilen > nlen || ilen == 0");
-					return;
-				}
-				nlen -= ilen;
-				ident = 0;
-				while (ilen > 0) {
-					ident = (ident << 8) | (*p++ & 0xFF);	/* invoke identifier */
-					ilen--;
-				}
+        p++;
+	qd_len--;
+	if (qd_len < 1) 
+          { l3_debug(st, "qd_len < 1");
+	    return;
+	  }
+	if (*p & 0x80) 
+          { /* length format indefinite or limited */
+	    nlen = *p++ & 0x7F; /* number of len bytes or indefinite */
+            if ((qd_len-- < ((!nlen) ? 3 : (1 + nlen))) ||
+                (nlen > 1))   
+	     { l3_debug(st, "length format error or not implemented");
+	       return;
+             }
+            if (nlen == 1)
+	     { nlen = *p++; /* complete length */
+               qd_len--;
+             } 
+            else
+	     { qd_len -= 2; /* trailing null bytes */
+               if ((*(p+qd_len)) || (*(p+qd_len+1)))
+		{ l3_debug(st,"length format indefinite error");
+                  return;
+                }
+               nlen = qd_len;
+             }
+	  }
+        else
+	  { nlen = *p++;
+	    qd_len--;
+          } 
+	if (qd_len < nlen) 
+          { l3_debug(st, "qd_len < nlen");
+	    return;
+	  }
+	qd_len -= nlen;
+
+	if (nlen < 2) 
+          { l3_debug(st, "nlen < 2");
+	    return;
+	  }
+        if (*p != 0x02) 
+          {  /* invoke identifier tag */
+	     l3_debug(st, "invoke identifier tag !=0x02");
+	     return;
+	  }
+	p++;
+	nlen--;
+	if (*p & 0x80) 
+          { /* length format */
+	    l3_debug(st, "invoke id length format 2");
+	    return;
+	  }
+	ilen = *p++;
+	nlen--;
+	if (ilen > nlen || ilen == 0) 
+          { l3_debug(st, "ilen > nlen || ilen == 0");
+	    return;
+	  }
+	nlen -= ilen;
+	id = 0;
+	while (ilen > 0) 
+          { id = (id << 8) | (*p++ & 0xFF);	/* invoke identifier */
+	    ilen--;
+	  }
 
+	switch (cp_tag) {	/* component tag */
+		case 1:	/* invoke */
 				if (nlen < 2) {
-					l3_debug(pc->st, "nlen < 2 22");
+					l3_debug(st, "nlen < 2 22");
 					return;
 				}
 				if (*p != 0x02) {	/* operation value */
-					l3_debug(pc->st, "operation value !=0x02");
+					l3_debug(st, "operation value !=0x02");
 					return;
 				}
 				p++;
@@ -175,7 +408,7 @@
 				ilen = *p++;
 				nlen--;
 				if (ilen > nlen || ilen == 0) {
-					l3_debug(pc->st, "ilen > nlen || ilen == 0 22");
+					l3_debug(st, "ilen > nlen || ilen == 0 22");
 					return;
 				}
 				nlen -= ilen;
@@ -185,11 +418,18 @@
 					ilen--;
 				}
 
+                                if (!pc) 
+			         { l3dss1_dummy_invoke(st, cr, id, ident, p, nlen);
+                                   return;
+                                 } 
+#if HISAX_DE_AOC
+			{
+
 #define FOO1(s,a,b) \
 	    while(nlen > 1) {		\
 		    int ilen = p[1];	\
 		    if(nlen < ilen+2) {	\
-			    l3_debug(pc->st, "FOO1  nlen < ilen+2"); \
+			    l3_debug(st, "FOO1  nlen < ilen+2"); \
 			    return;		\
 		    }			\
 		    nlen -= ilen+2;		\
@@ -203,8 +443,6 @@
 	    }
 
 				switch (ident) {
-					default:
-						break;
 					case 0x22:	/* during */
 						FOO1("1A", 0x30, FOO1("1C", 0xA1, FOO1("1D", 0x30, FOO1("1E", 0x02, ( {
 							       ident = 0;
@@ -215,14 +453,14 @@
 									}
 														     if (ident > pc->para.chargeinfo) {
 														     pc->para.chargeinfo = ident;
-														     pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);
+														     st->l3.l3l4(st, CC_CHARGE | INDICATION, pc);
 									}
-														     if (pc->st->l3.debug & L3_DEB_CHARGE) {
+														     if (st->l3.debug & L3_DEB_CHARGE) {
 														     if (*(p + 2) == 0) {
-														     l3_debug(pc->st, "charging info during %d", pc->para.chargeinfo);
+														     l3_debug(st, "charging info during %d", pc->para.chargeinfo);
 									}
 								   else {
-														     l3_debug(pc->st, "charging info final %d", pc->para.chargeinfo);
+														     l3_debug(st, "charging info final %d", pc->para.chargeinfo);
 									}
 									}
 									}
@@ -238,113 +476,553 @@
 									}
 																      if (ident > pc->para.chargeinfo) {
 																      pc->para.chargeinfo = ident;
-																      pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);
+																      st->l3.l3l4(st, CC_CHARGE | INDICATION, pc);
 									}
-																      if (pc->st->l3.debug & L3_DEB_CHARGE) {
-																      l3_debug(pc->st, "charging info final %d", pc->para.chargeinfo);
+																      if (st->l3.debug & L3_DEB_CHARGE) {
+																      l3_debug(st, "charging info final %d", pc->para.chargeinfo);
 									}
 									}
 								   ))))))
 							break;
+					default:
+                                                       l3_debug(st, "invoke break invalid ident %02x",ident);
+						break;
 				}
 #undef FOO1
 
 			}
+#else  not HISAX_DE_AOC
+                        l3_debug(st, "invoke break");
+#endif not HISAX_DE_AOC 
 			break;
 		case 2:	/* return result */
-			l3_debug(pc->st, "return result break");
+			 /* if no process available handle separately */ 
+                        if (!pc)
+			 { if (cr == -1) 
+                             l3dss1_dummy_return_result(st, id, p, nlen);
+                           return; 
+                         }   
+                        if ((pc->prot.dss1.invoke_id) && (pc->prot.dss1.invoke_id == id))
+                          { /* Diversion successfull */
+                            free_invoke_id(st,pc->prot.dss1.invoke_id);
+                            pc->prot.dss1.remote_result = 0; /* success */     
+                            pc->prot.dss1.invoke_id = 0;
+                            pc->redir_result = pc->prot.dss1.remote_result; 
+                            st->l3.l3l4(st, CC_REDIR | INDICATION, pc);                                  } /* Diversion successfull */
+                        else
+                          l3_debug(st,"return error unknown identifier");
 			break;
 		case 3:	/* return error */
-			l3_debug(pc->st, "return error break");
+                            err_ret = 0;
+	                    if (nlen < 2) 
+                              { l3_debug(st, "return error nlen < 2");
+	                        return;
+	                      }
+                            if (*p != 0x02) 
+                              { /* result tag */
+	                        l3_debug(st, "invoke error tag !=0x02");
+	                        return;
+	                      }
+	                    p++;
+	                    nlen--;
+	                    if (*p > 4) 
+                              { /* length format */
+	                        l3_debug(st, "invoke return errlen > 4 ");
+	                        return;
+	                      }
+	                    ilen = *p++;
+	                    nlen--;
+	                    if (ilen > nlen || ilen == 0) 
+                              { l3_debug(st, "error return ilen > nlen || ilen == 0");
+	                        return;
+	                       }
+	                    nlen -= ilen;
+	                    while (ilen > 0) 
+                             { err_ret = (err_ret << 8) | (*p++ & 0xFF);	/* error value */
+	                       ilen--;
+	                     }
+			 /* if no process available handle separately */ 
+                        if (!pc)
+			 { if (cr == -1)
+                             l3dss1_dummy_error_return(st, id, err_ret);
+                           return; 
+                         }   
+                        if ((pc->prot.dss1.invoke_id) && (pc->prot.dss1.invoke_id == id))
+                          { /* Deflection error */
+                            free_invoke_id(st,pc->prot.dss1.invoke_id);
+                            pc->prot.dss1.remote_result = err_ret; /* result */
+                            pc->prot.dss1.invoke_id = 0; 
+                            pc->redir_result = pc->prot.dss1.remote_result; 
+                            st->l3.l3l4(st, CC_REDIR | INDICATION, pc);  
+                          } /* Deflection error */
+                        else
+                          l3_debug(st,"return result unknown identifier");
 			break;
 		default:
-			l3_debug(pc->st, "default break");
+			l3_debug(st, "facility default break tag=0x%02x",cp_tag);
 			break;
 	}
 }
+
+static void
+l3dss1_message(struct l3_process *pc, u_char mt)
+{
+	struct sk_buff *skb;
+	u_char *p;
+
+	if (!(skb = l3_alloc_skb(4)))
+		return;
+	p = skb_put(skb, 4);
+	MsgHead(p, pc->callref, mt);
+	l3_msg(pc->st, DL_DATA | REQUEST, skb);
+}
+
+static void
+l3dss1_message_cause(struct l3_process *pc, u_char mt, u_char cause)
+{
+	struct sk_buff *skb;
+	u_char tmp[16];
+	u_char *p = tmp;
+	int l;
+
+	MsgHead(p, pc->callref, mt);
+	*p++ = IE_CAUSE;
+	*p++ = 0x2;
+	*p++ = 0x80;
+	*p++ = cause | 0x80;
+
+	l = p - tmp;
+	if (!(skb = l3_alloc_skb(l)))
+		return;
+	memcpy(skb_put(skb, l), tmp, l);
+	l3_msg(pc->st, DL_DATA | REQUEST, skb);
+}
+
+static void
+l3dss1_status_send(struct l3_process *pc, u_char pr, void *arg)
+{
+	u_char tmp[16];
+	u_char *p = tmp;
+	int l;
+	struct sk_buff *skb;
+
+	MsgHead(p, pc->callref, MT_STATUS);
+
+	*p++ = IE_CAUSE;
+	*p++ = 0x2;
+	*p++ = 0x80;
+	*p++ = pc->para.cause | 0x80;
+
+	*p++ = IE_CALL_STATE;
+	*p++ = 0x1;
+	*p++ = pc->state & 0x3f;
+
+	l = p - tmp;
+	if (!(skb = l3_alloc_skb(l)))
+		return;
+	memcpy(skb_put(skb, l), tmp, l);
+	l3_msg(pc->st, DL_DATA | REQUEST, skb);
+}
+
+static void
+l3dss1_msg_without_setup(struct l3_process *pc, u_char pr, void *arg)
+{
+	/* This routine is called if here was no SETUP made (checks in dss1up and in
+	 * l3dss1_setup) and a RELEASE_COMPLETE have to be sent with an error code
+	 * MT_STATUS_ENQUIRE in the NULL state is handled too
+	 */
+	u_char tmp[16];
+	u_char *p = tmp;
+	int l;
+	struct sk_buff *skb;
+
+	switch (pc->para.cause) {
+		case 81:	/* invalid callreference */
+		case 88:	/* incomp destination */
+		case 96:	/* mandory IE missing */
+		case 100:       /* invalid IE contents */
+		case 101:	/* incompatible Callstate */
+			MsgHead(p, pc->callref, MT_RELEASE_COMPLETE);
+			*p++ = IE_CAUSE;
+			*p++ = 0x2;
+			*p++ = 0x80;
+			*p++ = pc->para.cause | 0x80;
+			break;
+		default:
+			printk(KERN_ERR "HiSax l3dss1_msg_without_setup wrong cause %d\n",
+				pc->para.cause);
+			return;
+	}
+	l = p - tmp;
+	if (!(skb = l3_alloc_skb(l)))
+		return;
+	memcpy(skb_put(skb, l), tmp, l);
+	l3_msg(pc->st, DL_DATA | REQUEST, skb);
+	dss1_release_l3_process(pc);
+}
+
+static int ie_ALERTING[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1,
+		IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_HLC, IE_USER_USER, -1};
+static int ie_CALL_PROCEEDING[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1,
+		IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_HLC, -1};
+static int ie_CONNECT[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1, 
+		IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_DATE, IE_CONNECT_PN,
+		IE_CONNECT_SUB, IE_LLC, IE_HLC, IE_USER_USER, -1};
+static int ie_CONNECT_ACKNOWLEDGE[] = {IE_CHANNEL_ID, IE_DISPLAY, -1};
+static int ie_DISCONNECT[] = {IE_CAUSE | IE_MANDATORY, IE_FACILITY,
+		IE_PROGRESS, IE_DISPLAY, IE_USER_USER, -1};
+static int ie_INFORMATION[] = {IE_COMPLETE, IE_DISPLAY, IE_KEYPAD,
+		IE_CALLED_PN, -1};
+static int ie_NOTIFY[] = {IE_BEARER, IE_NOTIFY | IE_MANDATORY, IE_DISPLAY, -1};
+static int ie_PROGRESS[] = {IE_BEARER, IE_CAUSE, IE_FACILITY, IE_PROGRESS |
+		IE_MANDATORY, IE_DISPLAY, IE_HLC, IE_USER_USER, -1};
+static int ie_RELEASE[] = {IE_CAUSE | IE_MANDATORY_1, IE_FACILITY, IE_DISPLAY, IE_USER_USER, -1};
+/* a RELEASE_COMPLETE with errors don't require special actions 
+static int ie_RELEASE_COMPLETE[] = {IE_CAUSE | IE_MANDATORY_1, IE_DISPLAY, IE_USER_USER, -1};
+*/
+static int ie_RESUME_ACKNOWLEDGE[] = {IE_CHANNEL_ID| IE_MANDATORY, IE_FACILITY,
+		IE_DISPLAY, -1};
+static int ie_RESUME_REJECT[] = {IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1};
+static int ie_SETUP[] = {IE_COMPLETE, IE_BEARER  | IE_MANDATORY,
+		IE_CHANNEL_ID| IE_MANDATORY, IE_FACILITY, IE_PROGRESS,
+		IE_NET_FAC, IE_DISPLAY, IE_KEYPAD, IE_CALLING_PN,
+		IE_CALLING_SUB, IE_CALLED_PN, IE_CALLED_SUB, IE_LLC, IE_HLC,
+		IE_USER_USER, -1};
+static int ie_SETUP_ACKNOWLEDGE[] = {IE_CHANNEL_ID | IE_MANDATORY, IE_FACILITY,
+		IE_PROGRESS, IE_DISPLAY, -1};
+static int ie_STATUS[] = {IE_CAUSE | IE_MANDATORY, IE_CALL_STATE |
+		IE_MANDATORY, IE_DISPLAY, -1};
+static int ie_STATUS_ENQUIRY[] = {IE_DISPLAY, -1};
+static int ie_SUSPEND_ACKNOWLEDGE[] = {IE_DISPLAY, IE_FACILITY, -1};
+static int ie_SUSPEND_REJECT[] = {IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1};
+/* not used 
+ * static int ie_CONGESTION_CONTROL[] = {IE_CONGESTION | IE_MANDATORY,
+ *		IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1};
+ * static int ie_USER_INFORMATION[] = {IE_MORE_DATA, IE_USER_USER | IE_MANDATORY, -1};
+ * static int ie_RESTART[] = {IE_CHANNEL_ID, IE_DISPLAY, IE_RESTART_IND |
+ *		IE_MANDATORY, -1};
+ */
+static int ie_FACILITY[] = {IE_FACILITY | IE_MANDATORY, IE_DISPLAY, -1};
+static int comp_required[] = {1,2,3,5,6,7,9,10,11,14,15,-1};
+static int l3_valid_states[] = {0,1,2,3,4,6,7,8,9,10,11,12,15,17,19,25,-1};
+
+struct ie_len {
+	int ie;
+	int len;
+};
+
+static
+struct ie_len max_ie_len[] = {
+	{IE_SEGMENT, 4},
+	{IE_BEARER, 12},
+	{IE_CAUSE, 32},
+	{IE_CALL_ID, 10},
+	{IE_CALL_STATE, 3},
+	{IE_CHANNEL_ID,	34},
+	{IE_FACILITY, 255},
+	{IE_PROGRESS, 4},
+	{IE_NET_FAC, 255},
+	{IE_NOTIFY, 3},
+	{IE_DISPLAY, 82},
+	{IE_DATE, 8},
+	{IE_KEYPAD, 34},
+	{IE_SIGNAL, 3},
+	{IE_INFORATE, 6},
+	{IE_E2E_TDELAY, 11},
+	{IE_TDELAY_SEL, 5},
+	{IE_PACK_BINPARA, 3},
+	{IE_PACK_WINSIZE, 4},
+	{IE_PACK_SIZE, 4},
+	{IE_CUG, 7},
+	{IE_REV_CHARGE, 3},
+	{IE_CALLING_PN, 24},
+	{IE_CALLING_SUB, 23},
+	{IE_CALLED_PN, 24},
+	{IE_CALLED_SUB, 23},
+	{IE_REDIR_NR, 255},
+	{IE_TRANS_SEL, 255},
+	{IE_RESTART_IND, 3},
+	{IE_LLC, 18},
+	{IE_HLC, 5},
+	{IE_USER_USER, 131},
+	{-1,0},
+};
+
+static int
+getmax_ie_len(u_char ie) {
+	int i = 0;
+	while (max_ie_len[i].ie != -1) {
+		if (max_ie_len[i].ie == ie)
+			return(max_ie_len[i].len);
+		i++;
+	}
+	return(255);
+}
+
+static int
+ie_in_set(struct l3_process *pc, u_char ie, int *checklist) {
+	int ret = 1;
+
+	while (*checklist != -1) {
+#if 0
+		if (pc->debug & L3_DEB_CHECK)
+			l3_debug(pc->st, "ie_in_set ie(%x) cl(%x)",
+				ie, *checklist);
 #endif
+		if ((*checklist & 0xff) == ie) {
+			if (ie & 0x80)
+				return(-ret);
+			else
+				return(ret);
+		}
+		ret++;
+		checklist++;
+	}
+	return(0);
+}
+
+static int
+check_infoelements(struct l3_process *pc, struct sk_buff *skb, int *checklist)
+{
+	int *cl = checklist;
+	u_char mt;
+	u_char *p, ie;
+	int l, newpos, oldpos;
+	int err_seq = 0, err_len = 0, err_compr = 0, err_ureg = 0;
+	
+	p = skb->data;
+	/* skip cr */
+	p++;
+	l = (*p++) & 0xf;
+	p += l;
+	mt = *p++;
+	oldpos = 0;
+/* shift codeset procedure not implemented in the moment */
+	while ((p - skb->data) < skb->len) {
+		if ((newpos = ie_in_set(pc, *p, cl))) {
+			if (newpos > 0) {
+				if (newpos < oldpos)
+					err_seq++;
+				else
+					oldpos = newpos;
+			}
+		} else {
+			if (ie_in_set(pc, *p, comp_required))
+				err_compr++;
+			else
+				err_ureg++;
+		}
+		ie = *p++;
+		if (ie & 0x80) {
+			l = 1;
+		} else {
+			l = *p++;
+			p += l;
+			l += 2;
+		}
+		if (l > getmax_ie_len(ie))
+			err_len++;
+	}
+	if (err_compr | err_ureg | err_len | err_seq) {
+		if (pc->debug & L3_DEB_CHECK)
+			l3_debug(pc->st, "check_infoelements mt %x %d/%d/%d/%d",
+				mt, err_compr, err_ureg, err_len, err_seq);
+		if (err_compr)
+			return(ERR_IE_COMPREHENSION);
+		if (err_ureg)
+			return(ERR_IE_UNRECOGNIZED);
+		if (err_len)
+			return(ERR_IE_LENGTH);
+		if (err_seq)
+			return(ERR_IE_SEQUENCE);
+	} 
+	return(0);
+}
 
+/* verify if a message type exists and contain no IE error */
 static int
-l3dss1_check_messagetype_validity(int mt)
+l3dss1_check_messagetype_validity(struct l3_process *pc, int mt, void *arg)
 {
-/* verify if a message type exists */
 	switch (mt) {
 		case MT_ALERTING:
 		case MT_CALL_PROCEEDING:
 		case MT_CONNECT:
 		case MT_CONNECT_ACKNOWLEDGE:
+		case MT_DISCONNECT:
+		case MT_INFORMATION:
+		case MT_FACILITY:
+		case MT_NOTIFY:
 		case MT_PROGRESS:
+		case MT_RELEASE:
+		case MT_RELEASE_COMPLETE:
 		case MT_SETUP:
 		case MT_SETUP_ACKNOWLEDGE:
-		case MT_RESUME:
 		case MT_RESUME_ACKNOWLEDGE:
 		case MT_RESUME_REJECT:
-		case MT_SUSPEND:
 		case MT_SUSPEND_ACKNOWLEDGE:
 		case MT_SUSPEND_REJECT:
 		case MT_USER_INFORMATION:
-		case MT_DISCONNECT:
-		case MT_RELEASE:
-		case MT_RELEASE_COMPLETE:
 		case MT_RESTART:
 		case MT_RESTART_ACKNOWLEDGE:
-		case MT_SEGMENT:
 		case MT_CONGESTION_CONTROL:
-		case MT_INFORMATION:
-		case MT_FACILITY:
-		case MT_NOTIFY:
 		case MT_STATUS:
 		case MT_STATUS_ENQUIRY:
+			if (pc->debug & L3_DEB_CHECK)
+				l3_debug(pc->st, "l3dss1_check_messagetype_validity mt(%x) OK", mt);
+			break;
+		case MT_RESUME: /* RESUME only in user->net */
+		case MT_SUSPEND: /* SUSPEND only in user->net */
+		default:
+			if (pc->debug & (L3_DEB_CHECK | L3_DEB_WARN))
+				l3_debug(pc->st, "l3dss1_check_messagetype_validity mt(%x) fail", mt);
+			pc->para.cause = 97;
+			l3dss1_status_send(pc, 0, NULL);
 			return(1);
+	}
+	return(0);
+}
+
+static void
+l3dss1_std_ie_err(struct l3_process *pc, int ret) {
+
+	if (pc->debug & L3_DEB_CHECK)
+		l3_debug(pc->st, "check_infoelements ret %d", ret);
+	switch(ret) {
+		case 0: 
+			break;
+		case ERR_IE_COMPREHENSION:
+			pc->para.cause = 96;
+			l3dss1_status_send(pc, 0, NULL);
+			break;
+		case ERR_IE_UNRECOGNIZED:
+			pc->para.cause = 99;
+			l3dss1_status_send(pc, 0, NULL);
+			break;
+		case ERR_IE_LENGTH:
+			pc->para.cause = 100;
+			l3dss1_status_send(pc, 0, NULL);
+			break;
+		case ERR_IE_SEQUENCE:
 		default:
-			return(0);
+			break;
 	}
+}
+
+static int
+l3dss1_get_channel_id(struct l3_process *pc, struct sk_buff *skb) {
+	u_char *p;
+
+	p = skb->data;
+	if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
+		p++;
+		if (*p != 1) { /* len for BRI = 1 */
+			if (pc->debug & L3_DEB_WARN)
+				l3_debug(pc->st, "wrong chid len %d", *p);
+			return (-2);
+		}
+		p++;
+		if (*p & 0x60) { /* only base rate interface */
+			if (pc->debug & L3_DEB_WARN)
+				l3_debug(pc->st, "wrong chid %x", *p);
+			return (-3);
+		}
+		return(*p & 0x3);
+	} else
+		return(-1);
+}
+
+static int
+l3dss1_get_cause(struct l3_process *pc, struct sk_buff *skb) {
+	u_char l, i=0;
+	u_char *p;
+
+	p = skb->data;
+	pc->para.cause = 31;
+	pc->para.loc = 0;
+	if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
+		p++;
+		l = *p++;
+		if (l>30)
+			return(1);
+		if (l) {
+			pc->para.loc = *p++;
+			l--;
+		} else {
+			return(2);
+		}
+		if (l && !(pc->para.loc & 0x80)) {
+			l--;
+			p++; /* skip recommendation */
+		}
+		if (l) {
+			pc->para.cause = *p++;
+			l--;
+			if (!(pc->para.cause & 0x80))
+				return(3);
+		} else
+			return(4);
+		while (l && (i<6)) {
+			pc->para.diag[i++] = *p++;
+			l--;
+		}
+	} else
+		return(-1);
 	return(0);
 }
 
 static void
-l3dss1_message(struct l3_process *pc, u_char mt)
+l3dss1_msg_with_uus(struct l3_process *pc, u_char cmd)
 {
 	struct sk_buff *skb;
-	u_char *p;
+	u_char tmp[16+40];
+	u_char *p = tmp;
+	int l;
 
-	if (!(skb = l3_alloc_skb(4)))
+	MsgHead(p, pc->callref, cmd);
+
+        if (pc->prot.dss1.uus1_data[0])
+	 { *p++ = IE_USER_USER; /* UUS info element */
+           *p++ = strlen(pc->prot.dss1.uus1_data) + 1;
+           *p++ = 0x04; /* IA5 chars */
+           strcpy(p,pc->prot.dss1.uus1_data);
+           p += strlen(pc->prot.dss1.uus1_data);
+           pc->prot.dss1.uus1_data[0] = '\0';   
+         } 
+
+	l = p - tmp;
+	if (!(skb = l3_alloc_skb(l)))
 		return;
-	p = skb_put(skb, 4);
-	MsgHead(p, pc->callref, mt);
+	memcpy(skb_put(skb, l), tmp, l);
 	l3_msg(pc->st, DL_DATA | REQUEST, skb);
-}
+} /* l3dss1_msg_with_uus */
 
 static void
 l3dss1_release_req(struct l3_process *pc, u_char pr, void *arg)
 {
 	StopAllL3Timer(pc);
 	newl3state(pc, 19);
-	l3dss1_message(pc, MT_RELEASE);
+	if (!pc->prot.dss1.uus1_data[0]) 
+		l3dss1_message(pc, MT_RELEASE);
+	else
+		l3dss1_msg_with_uus(pc, MT_RELEASE);
 	L3AddTimer(&pc->timer, T308, CC_T308_1);
 }
 
 static void
 l3dss1_release_cmpl(struct l3_process *pc, u_char pr, void *arg)
 {
-	u_char *p;
 	struct sk_buff *skb = arg;
-	int cause = -1;
+	int ret;
 
-	p = skb->data;
-	pc->para.loc = 0;
-	if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
-		p++;
-		if (*p++ == 2)
-			pc->para.loc = *p++;
-		cause = *p & 0x7f;
-	}
-	dev_kfree_skb(skb);
+	if ((ret = l3dss1_get_cause(pc, skb))>0) {
+		if (pc->debug & L3_DEB_WARN)
+			l3_debug(pc->st, "RELCMPL get_cause ret(%d)",ret);
+	} else if (ret < 0)
+		pc->para.cause = NO_CAUSE;
 	StopAllL3Timer(pc);
-	pc->para.cause = cause;
 	newl3state(pc, 0);
 	pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc);
-	release_l3_process(pc);
+	dss1_release_l3_process(pc);
 }
 
 #if EXT_BEARER_CAPS
@@ -574,9 +1252,8 @@
 
 				break;
 			case 0x08:	// if (p[5] == 0x02) // sync. Bitratenadaption
-
-				return DecodeSyncParams(176, p[5]);	// V.120
-
+				if (p[1] > 3) 
+					return DecodeSyncParams(176, p[5]);	// V.120
 				break;
 		}
 	}
@@ -594,6 +1271,7 @@
 	u_char tmp[128];
 	u_char *p = tmp;
 	u_char channel = 0;
+        u_char send_keypad;
 	u_char screen = 0x80;
 	u_char *teln;
 	u_char *msn;
@@ -603,13 +1281,17 @@
 
 	MsgHead(p, pc->callref, MT_SETUP);
 
+	teln = pc->para.setup.phone;
+        send_keypad = (strchr(teln,'*') || strchr(teln,'#')) ? 1 : 0; 
 	/*
 	 * Set Bearer Capability, Map info from 1TR6-convention to EDSS1
 	 */
 #if HISAX_EURO_SENDCOMPLETE
-	*p++ = 0xa1;		/* complete indicator */
+	if (!send_keypad)
+	  *p++ = 0xa1;		/* complete indicator */
 #endif
-	switch (pc->para.setup.si1) {
+        if (!send_keypad)
+	  switch (pc->para.setup.si1) {
 		case 1:	/* Telephony                               */
 			*p++ = 0x4;	/* BC-IE-code                              */
 			*p++ = 0x3;	/* Length                                  */
@@ -625,12 +1307,26 @@
 			*p++ = 0x88;	/* Coding Std. CCITT, unrestr. dig. Inform. */
 			*p++ = 0x90;	/* Circuit-Mode 64kbps                      */
 			break;
-	}
+	  }
+	else {  *p++ = 0x4; /* assumptions for bearer services with keypad  */
+		*p++ = 0x3;
+		*p++ = 0x80;
+                *p++ = 0x90;
+                *p++ = 0xa3;
+		*p++ = 0x18; /* no specific channel */
+                *p++ = 0x01;
+                *p++ = 0x83;
+		*p++ = 0x2C; /* IE keypad */
+		*p++ = strlen(teln);
+		while (*teln)
+		  *p++ = (*teln++) & 0x7F;
+	  }
+	  
+       
 	/*
 	 * What about info2? Mapping to High-Layer-Compatibility?
 	 */
-	teln = pc->para.setup.phone;
-	if (*teln) {
+	if ((*teln) && (!send_keypad)) {
 		/* parse number for special things */
 		if (!isdigit(*teln)) {
 			switch (0x5f & *teln) {
@@ -650,7 +1346,8 @@
 				case 'D':
 					screen = 0x80;
 					break;
-				default:
+				
+			        default:
 					if (pc->debug & L3_DEB_WARN)
 						l3_debug(pc->st, "Wrong MSN Code");
 					break;
@@ -703,24 +1400,33 @@
 		} else
 			sp++;
 	}
-	*p++ = 0x70;
-	*p++ = strlen(teln) + 1;
-	/* Classify as AnyPref. */
-	*p++ = 0x81;		/* Ext = '1'B, Type = '000'B, Plan = '0001'B. */
-	while (*teln)
-		*p++ = *teln++ & 0x7f;
-
-	if (sub) {
-		*sub++ = '.';
-		*p++ = 0x71;	/* Called party subaddress */
-		*p++ = strlen(sub) + 2;
-		*p++ = 0x80;	/* NSAP coded */
-		*p++ = 0x50;	/* local IDI format */
-		while (*sub)
-			*p++ = *sub++ & 0x7f;
-	}
+	
+        if (!send_keypad) {      
+	  *p++ = 0x70;
+	  *p++ = strlen(teln) + 1;
+	  /* Classify as AnyPref. */
+	  *p++ = 0x81;		/* Ext = '1'B, Type = '000'B, Plan = '0001'B. */
+	  while (*teln)
+		  *p++ = *teln++ & 0x7f;
+
+	  if (sub) {
+		  *sub++ = '.';
+		  *p++ = 0x71;	/* Called party subaddress */
+		  *p++ = strlen(sub) + 2;
+		  *p++ = 0x80;	/* NSAP coded */
+		  *p++ = 0x50;	/* local IDI format */
+		  while (*sub)
+			  *p++ = *sub++ & 0x7f;
+	  }
+        }
 #if EXT_BEARER_CAPS
-	if ((pc->para.setup.si2 >= 160) && (pc->para.setup.si2 <= 175)) {	// sync. Bitratenadaption, V.110/X.30
+        if (send_keypad) { /* special handling independant of si2 */
+                *p++ = 0x7c;
+                *p++ = 0x03;
+                *p++ = 0x80;
+                *p++ = 0x90;
+                *p++ = 0xa3;
+	} else if ((pc->para.setup.si2 >= 160) && (pc->para.setup.si2 <= 175)) {	// sync. Bitratenadaption, V.110/X.30
 
 		*p++ = 0x7c;
 		*p++ = 0x04;
@@ -767,74 +1473,136 @@
 static void
 l3dss1_call_proc(struct l3_process *pc, u_char pr, void *arg)
 {
-	u_char *p;
 	struct sk_buff *skb = arg;
+	int id, ret;
 
+	if ((id = l3dss1_get_channel_id(pc, skb)) >= 0) {
+		if ((0 == id) || ((3 == id) && (0x10 == pc->para.moderate))) {
+			if (pc->debug & L3_DEB_WARN)
+				l3_debug(pc->st, "setup answer with wrong chid %x", id);
+			pc->para.cause = 100;
+			l3dss1_status_send(pc, pr, NULL);
+			return;
+		}
+		pc->para.bchannel = id;
+	} else if (1 == pc->state) {
+		if (pc->debug & L3_DEB_WARN)
+			l3_debug(pc->st, "setup answer wrong chid (ret %d)", id);
+		if (id == -1)
+			pc->para.cause = 96;
+		else
+			pc->para.cause = 100;
+		l3dss1_status_send(pc, pr, NULL);
+		return;
+	}
+	/* Now we are on none mandatory IEs */
+	ret = check_infoelements(pc, skb, ie_CALL_PROCEEDING);
+	if (ERR_IE_COMPREHENSION == ret) {
+		l3dss1_std_ie_err(pc, ret);
+		return;
+	}
 	L3DelTimer(&pc->timer);
-	p = skb->data;
-	if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
-		pc->para.bchannel = p[2] & 0x3;
-		if ((!pc->para.bchannel) && (pc->debug & L3_DEB_WARN))
-			l3_debug(pc->st, "setup answer without bchannel");
-	} else if (pc->debug & L3_DEB_WARN)
-		l3_debug(pc->st, "setup answer without bchannel");
-	dev_kfree_skb(skb);
 	newl3state(pc, 3);
 	L3AddTimer(&pc->timer, T310, CC_T310);
+	if (ret) /* STATUS for none mandatory IE errors after actions are taken */
+		l3dss1_std_ie_err(pc, ret);
 	pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc);
 }
 
 static void
 l3dss1_setup_ack(struct l3_process *pc, u_char pr, void *arg)
 {
-	u_char *p;
 	struct sk_buff *skb = arg;
+	int id, ret;
 
+	if ((id = l3dss1_get_channel_id(pc, skb)) >= 0) {
+		if ((0 == id) || ((3 == id) && (0x10 == pc->para.moderate))) {
+			if (pc->debug & L3_DEB_WARN)
+				l3_debug(pc->st, "setup answer with wrong chid %x", id);
+			pc->para.cause = 100;
+			l3dss1_status_send(pc, pr, NULL);
+			return;
+		}
+		pc->para.bchannel = id;
+	} else {
+		if (pc->debug & L3_DEB_WARN)
+			l3_debug(pc->st, "setup answer wrong chid (ret %d)", id);
+		if (id == -1)
+			pc->para.cause = 96;
+		else
+			pc->para.cause = 100;
+		l3dss1_status_send(pc, pr, NULL);
+		return;
+	}
+	/* Now we are on none mandatory IEs */
+	ret = check_infoelements(pc, skb, ie_SETUP_ACKNOWLEDGE);
+	if (ERR_IE_COMPREHENSION == ret) {
+		l3dss1_std_ie_err(pc, ret);
+		return;
+	}
 	L3DelTimer(&pc->timer);
-	p = skb->data;
-	if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
-		pc->para.bchannel = p[2] & 0x3;
-		if ((!pc->para.bchannel) && (pc->debug & L3_DEB_WARN))
-			l3_debug(pc->st, "setup answer without bchannel");
-	} else if (pc->debug & L3_DEB_WARN)
-		l3_debug(pc->st, "setup answer without bchannel");
-	dev_kfree_skb(skb);
 	newl3state(pc, 2);
 	L3AddTimer(&pc->timer, T304, CC_T304);
+	if (ret) /* STATUS for none mandatory IE errors after actions are taken */
+		l3dss1_std_ie_err(pc, ret);
 	pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);
 }
 
 static void
 l3dss1_disconnect(struct l3_process *pc, u_char pr, void *arg)
 {
-	u_char *p;
 	struct sk_buff *skb = arg;
-	int cause = -1;
+	u_char *p;
+	int ret;
+	u_char cause = 0;
 
 	StopAllL3Timer(pc);
-	p = skb->data;
-	pc->para.loc = 0;
-	if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
-		p++;
-		if (*p++ == 2)
-			pc->para.loc = *p++;
-		cause = *p & 0x7f;
-	}
-	dev_kfree_skb(skb);
+	if ((ret = l3dss1_get_cause(pc, skb))) {
+		if (pc->debug & L3_DEB_WARN)
+			l3_debug(pc->st, "DISC get_cause ret(%d)", ret);
+		if (ret < 0)
+			cause = 96;
+		else if (ret > 0)
+			cause = 100;
+	} 
+	if ((p = findie(skb->data, skb->len, IE_FACILITY, 0)))
+		l3dss1_parse_facility(pc->st, pc, pc->callref, p);
+	ret = check_infoelements(pc, skb, ie_DISCONNECT);
+	if (ERR_IE_COMPREHENSION == ret)
+		cause = 96;
+	else if ((!cause) && (ERR_IE_UNRECOGNIZED == ret))
+		cause = 99;
+	ret = pc->state;
 	newl3state(pc, 12);
-	pc->para.cause = cause;
-	pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc);
+	if (cause)
+		newl3state(pc, 19);
+       	if (11 != ret)
+		pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc);
+       	else if (!cause)
+		   l3dss1_release_req(pc, pr, NULL);
+	if (cause) {
+		l3dss1_message_cause(pc, MT_RELEASE, cause);
+		L3AddTimer(&pc->timer, T308, CC_T308_1);
+	}
 }
 
 static void
 l3dss1_connect(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
+	int ret;
 
-	dev_kfree_skb(skb);
+	ret = check_infoelements(pc, skb, ie_CONNECT);
+	if (ERR_IE_COMPREHENSION == ret) {
+		l3dss1_std_ie_err(pc, ret);
+		return;
+	}
 	L3DelTimer(&pc->timer);	/* T310 */
 	newl3state(pc, 10);
 	pc->para.chargeinfo = 0;
+	/* here should inserted COLP handling KKe */
+	if (ret)
+		l3dss1_std_ie_err(pc, ret);
 	pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc);
 }
 
@@ -842,143 +1610,142 @@
 l3dss1_alerting(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
+	int ret;
 
-	dev_kfree_skb(skb);
+	ret = check_infoelements(pc, skb, ie_ALERTING);
+	if (ERR_IE_COMPREHENSION == ret) {
+		l3dss1_std_ie_err(pc, ret);
+		return;
+	}
 	L3DelTimer(&pc->timer);	/* T304 */
 	newl3state(pc, 4);
+	if (ret)
+		l3dss1_std_ie_err(pc, ret);
 	pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc);
 }
 
 static void
-l3dss1_msg_without_setup(struct l3_process *pc, u_char pr, void *arg)
-{
-	/* This routine is called if here was no SETUP made (checks in dss1up and in
-	 * l3dss1_setup) and a RELEASE_COMPLETE have to be sent with an error code
-	 * MT_STATUS_ENQUIRE in the NULL state is handled too
-	 */
-	u_char tmp[16];
-	u_char *p = tmp;
-	int l;
-	struct sk_buff *skb;
-
-	switch (pc->para.cause) {
-		case 81:	/* 0x51 invalid callreference */
-		case 88:	/* 0x58 incomp destination */
-		case 96:	/* 0x60 mandory IE missing */
-		case 101:	/* 0x65 incompatible Callstate */
-			MsgHead(p, pc->callref, MT_RELEASE_COMPLETE);
-			*p++ = IE_CAUSE;
-			*p++ = 0x2;
-			*p++ = 0x80;
-			*p++ = pc->para.cause | 0x80;
-			break;
-		default:
-			printk(KERN_ERR "HiSax internal error l3dss1_msg_without_setup\n");
-			return;
-	}
-	l = p - tmp;
-	if (!(skb = l3_alloc_skb(l)))
-		return;
-	memcpy(skb_put(skb, l), tmp, l);
-	l3_msg(pc->st, DL_DATA | REQUEST, skb);
-	release_l3_process(pc);
-}
-
-static void
 l3dss1_setup(struct l3_process *pc, u_char pr, void *arg)
 {
-	u_char *p, *ptmp[8];
-	int i;
+	u_char *p;
 	int bcfound = 0;
 	char tmp[80];
 	struct sk_buff *skb = arg;
+	int id;
+	int err = 0;
 
-	/* ETS 300-104 1.3.4 and 1.3.5
-	 * we need to detect unknown inform. element from 0 to 7
+	/*
+	 * Bearer Capabilities
 	 */
 	p = skb->data;
-	for (i = 0; i < 8; i++)
-		ptmp[i] = skb->data;
-	if (findie(ptmp[1], skb->len, 0x01, 0)
-	    || findie(ptmp[2], skb->len, 0x02, 0)
-	    || findie(ptmp[3], skb->len, 0x03, 0)
-	    || findie(ptmp[5], skb->len, 0x05, 0)
-	    || findie(ptmp[6], skb->len, 0x06, 0)
-	    || findie(ptmp[7], skb->len, 0x07, 0)) {
-		/* if ie is < 8 and not 0 nor 4, send RELEASE_COMPLETE
-		 * cause 0x60
-		 */
-		pc->para.cause = 0x60;
-		dev_kfree_skb(skb);
+	/* only the first occurence 'll be detected ! */
+	if ((p = findie(p, skb->len, 0x04, 0))) {
+		if ((p[1] < 2) || (p[1] > 11))
+			err = 1;
+		else {
+			pc->para.setup.si2 = 0;
+			switch (p[2] & 0x7f) {
+				case 0x00: /* Speech */
+				case 0x10: /* 3.1 Khz audio */
+					pc->para.setup.si1 = 1;
+					break;
+				case 0x08: /* Unrestricted digital information */
+					pc->para.setup.si1 = 7;
+/* JIM, 05.11.97 I wanna set service indicator 2 */
+#if EXT_BEARER_CAPS
+					pc->para.setup.si2 = DecodeSI2(skb);
+#endif
+					break;
+				case 0x09: /* Restricted digital information */
+					pc->para.setup.si1 = 2;
+					break;
+				case 0x11:
+					/* Unrestr. digital information  with 
+					 * tones/announcements ( or 7 kHz audio
+					 */
+					pc->para.setup.si1 = 3;
+					break;
+				case 0x18: /* Video */
+					pc->para.setup.si1 = 4;
+					break;
+				default:
+					err = 2;
+					break;
+			}
+			switch (p[3] & 0x7f) {
+				case 0x40: /* packed mode */
+					pc->para.setup.si1 = 8;
+					break;
+				case 0x10: /* 64 kbit */
+				case 0x11: /* 2*64 kbit */
+				case 0x13: /* 384 kbit */
+				case 0x15: /* 1536 kbit */
+				case 0x17: /* 1920 kbit */
+					pc->para.moderate = p[3] & 0x7f;
+					break;
+				default:
+					err = 3;
+					break;
+			}
+		}
+		if (pc->debug & L3_DEB_SI)
+			l3_debug(pc->st, "SI=%d, AI=%d",
+				pc->para.setup.si1, pc->para.setup.si2);
+		if (err) {
+			if (pc->debug & L3_DEB_WARN)
+				l3_debug(pc->st, "setup with wrong bearer(l=%d:%x,%x)",
+					p[1], p[2], p[3]);
+			pc->para.cause = 100;
+			l3dss1_msg_without_setup(pc, pr, NULL);
+			return;
+		}
+	} else {
+		if (pc->debug & L3_DEB_WARN)
+			l3_debug(pc->st, "setup without bearer capabilities");
+		/* ETS 300-104 1.3.3 */
+		pc->para.cause = 96;
 		l3dss1_msg_without_setup(pc, pr, NULL);
 		return;
 	}
 	/*
 	 * Channel Identification
 	 */
-	p = skb->data;
-	if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
-		pc->para.bchannel = p[2] & 0x3;
-		if (pc->para.bchannel)
+	if ((id = l3dss1_get_channel_id(pc, skb)) >= 0) {
+		if ((pc->para.bchannel = id)) {
+			if ((3 == id) && (0x10 == pc->para.moderate)) {
+				if (pc->debug & L3_DEB_WARN)
+					l3_debug(pc->st, "setup with wrong chid %x",
+						id);
+				pc->para.cause = 100;
+				l3dss1_msg_without_setup(pc, pr, NULL);
+				return;
+			}
 			bcfound++;
-		else if (pc->debug & L3_DEB_WARN)
-			l3_debug(pc->st, "setup without bchannel");
+		} else 
+                   { if (pc->debug & L3_DEB_WARN)
+			 l3_debug(pc->st, "setup without bchannel, call waiting");
+                     bcfound++;
+                   } 
 	} else {
 		if (pc->debug & L3_DEB_WARN)
-			l3_debug(pc->st, "setup without bchannel");
-		pc->para.cause = 0x60;
-		dev_kfree_skb(skb);
+			l3_debug(pc->st, "setup with wrong chid ret %d", id);
+		if (id == -1)
+			pc->para.cause = 96;
+		else
+			pc->para.cause = 100;
 		l3dss1_msg_without_setup(pc, pr, NULL);
 		return;
 	}
-	/*
-	   * Bearer Capabilities
-	 */
-	p = skb->data;
-	if ((p = findie(p, skb->len, 0x04, 0))) {
-		pc->para.setup.si2 = 0;
-		switch (p[2] & 0x1f) {
-			case 0x00:
-				/* Speech */
-			case 0x10:
-				/* 3.1 Khz audio */
-				pc->para.setup.si1 = 1;
-				break;
-			case 0x08:
-				/* Unrestricted digital information */
-				pc->para.setup.si1 = 7;
-/* JIM, 05.11.97 I wanna set service indicator 2 */
-#if EXT_BEARER_CAPS
-				pc->para.setup.si2 = DecodeSI2(skb);
-				printk(KERN_DEBUG "HiSax: SI=%d, AI=%d\n",
-				 pc->para.setup.si1, pc->para.setup.si2);
-#endif
-				break;
-			case 0x09:
-				/* Restricted digital information */
-				pc->para.setup.si1 = 2;
-				break;
-			case 0x11:
-				/* Unrestr. digital information  with tones/announcements */
-				pc->para.setup.si1 = 3;
-				break;
-			case 0x18:
-				/* Video */
-				pc->para.setup.si1 = 4;
-				break;
-			default:
-				pc->para.setup.si1 = 0;
-		}
-	} else {
-		if (pc->debug & L3_DEB_WARN)
-			l3_debug(pc->st, "setup without bearer capabilities");
-		/* ETS 300-104 1.3.3 */
-		pc->para.cause = 0x60;
-		dev_kfree_skb(skb);
+	/* Now we are on none mandatory IEs */
+#if 1
+/* !!!!!! this check seems to be a problem ? info bugfix to Karsten */
+	err = check_infoelements(pc, skb, ie_SETUP);
+	if (ERR_IE_COMPREHENSION == err) {
+		pc->para.cause = 96;
 		l3dss1_msg_without_setup(pc, pr, NULL);
 		return;
 	}
-
+#endif
 	p = skb->data;
 	if ((p = findie(p, skb->len, 0x70, 0)))
 		iecpy(pc->para.setup.eazmsn, p, 1);
@@ -1020,8 +1787,8 @@
 		} else if (pc->debug & L3_DEB_WARN)
 			l3_debug(pc->st, "wrong calling subaddress");
 	}
-	dev_kfree_skb(skb);
 
+#if 0
 	if (bcfound) {
 		if ((pc->para.setup.si1 != 7) && (pc->debug & L3_DEB_WARN)) {
 			l3_debug(pc->st, "non-digital call: %s -> %s",
@@ -1029,53 +1796,38 @@
 		}
 		if ((pc->para.setup.si1 != 7) &&
 		    test_bit(FLG_PTP, &pc->st->l2.flag)) {
-			pc->para.cause = 0x58;
+			pc->para.cause = 88; /* incompatible destination */
 			l3dss1_msg_without_setup(pc, pr, NULL);
 			return;
 		}
 		newl3state(pc, 6);
 		pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc);
 	} else
-		release_l3_process(pc);
-}
-
-static void
-l3dss1_reset(struct l3_process *pc, u_char pr, void *arg)
-{
-	release_l3_process(pc);
-}
-
-static void
-l3dss1_setup_rsp(struct l3_process *pc, u_char pr,
-		 void *arg)
-{
-	newl3state(pc, 8);
-	l3dss1_message(pc, MT_CONNECT);
-	L3DelTimer(&pc->timer);
-	L3AddTimer(&pc->timer, T313, CC_T313);
+		dss1_release_l3_process(pc);
+#else
+	newl3state(pc, 6);
+	if (err) /* STATUS for none mandatory IE errors after actions are taken */
+		l3dss1_std_ie_err(pc, err);
+	pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc);
+#endif
 }
 
 static void
-l3dss1_connect_ack(struct l3_process *pc, u_char pr, void *arg)
+l3dss1_reset(struct l3_process *pc, u_char pr, void *arg)
 {
-	struct sk_buff *skb = arg;
-
-	dev_kfree_skb(skb);
-	newl3state(pc, 10);
-	L3DelTimer(&pc->timer);
-	pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc);
+	dss1_release_l3_process(pc);
 }
 
 static void
 l3dss1_disconnect_req(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb;
-	u_char tmp[16];
+	u_char tmp[16+40];
 	u_char *p = tmp;
 	int l;
-	u_char cause = 0x10;
+	u_char cause = 16;
 
-	if (pc->para.cause > 0)
+	if (pc->para.cause != NO_CAUSE)
 		cause = pc->para.cause;
 
 	StopAllL3Timer(pc);
@@ -1087,6 +1839,15 @@
 	*p++ = 0x80;
 	*p++ = cause | 0x80;
 
+        if (pc->prot.dss1.uus1_data[0])
+	 { *p++ = IE_USER_USER; /* UUS info element */
+           *p++ = strlen(pc->prot.dss1.uus1_data) + 1;
+           *p++ = 0x04; /* IA5 chars */
+           strcpy(p,pc->prot.dss1.uus1_data);
+           p += strlen(pc->prot.dss1.uus1_data);
+           pc->prot.dss1.uus1_data[0] = '\0';   
+         } 
+
 	l = p - tmp;
 	if (!(skb = l3_alloc_skb(l)))
 		return;
@@ -1097,15 +1858,49 @@
 }
 
 static void
+l3dss1_setup_rsp(struct l3_process *pc, u_char pr,
+		 void *arg)
+{
+        if (!pc->para.bchannel) 
+	 { if (pc->debug & L3_DEB_WARN)
+	       l3_debug(pc->st, "D-chan connect for waiting call");
+           l3dss1_disconnect_req(pc, pr, arg);
+           return;
+         }
+	newl3state(pc, 8);
+	l3dss1_message(pc, MT_CONNECT);
+	L3DelTimer(&pc->timer);
+	L3AddTimer(&pc->timer, T313, CC_T313);
+}
+
+static void
+l3dss1_connect_ack(struct l3_process *pc, u_char pr, void *arg)
+{
+	struct sk_buff *skb = arg;
+	int ret;
+
+	ret = check_infoelements(pc, skb, ie_CONNECT_ACKNOWLEDGE);
+	if (ERR_IE_COMPREHENSION == ret) {
+		l3dss1_std_ie_err(pc, ret);
+		return;
+	}
+	newl3state(pc, 10);
+	L3DelTimer(&pc->timer);
+	if (ret)
+		l3dss1_std_ie_err(pc, ret);
+	pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc);
+}
+
+static void
 l3dss1_reject_req(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb;
 	u_char tmp[16];
 	u_char *p = tmp;
 	int l;
-	u_char cause = 0x95;
+	u_char cause = 21;
 
-	if (pc->para.cause > 0)
+	if (pc->para.cause != NO_CAUSE)
 		cause = pc->para.cause;
 
 	MsgHead(p, pc->callref, MT_RELEASE_COMPLETE);
@@ -1113,7 +1908,7 @@
 	*p++ = IE_CAUSE;
 	*p++ = 0x2;
 	*p++ = 0x80;
-	*p++ = cause;
+	*p++ = cause | 0x80;
 
 	l = p - tmp;
 	if (!(skb = l3_alloc_skb(l)))
@@ -1122,38 +1917,41 @@
 	l3_msg(pc->st, DL_DATA | REQUEST, skb);
 	pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
 	newl3state(pc, 0);
-	release_l3_process(pc);
+	dss1_release_l3_process(pc);
 }
 
 static void
 l3dss1_release(struct l3_process *pc, u_char pr, void *arg)
 {
-	u_char *p;
 	struct sk_buff *skb = arg;
-	int cause = -1;
+	u_char *p;
+	int ret, cause=0;
 
-	p = skb->data;
-	if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
-		p++;
-		if (*p++ == 2)
-			pc->para.loc = *p++;
-		cause = *p & 0x7f;
-	}
-	p = skb->data;
-	if ((p = findie(p, skb->len, IE_FACILITY, 0))) {
-#if HISAX_DE_AOC
-		l3dss1_parse_facility(pc, p);
-#else
-		p = NULL;
-#endif
-	}
-	dev_kfree_skb(skb);
 	StopAllL3Timer(pc);
-	pc->para.cause = cause;
-	l3dss1_message(pc, MT_RELEASE_COMPLETE);
+	if ((ret = l3dss1_get_cause(pc, skb))>0) {
+		if (pc->debug & L3_DEB_WARN)
+			l3_debug(pc->st, "REL get_cause ret(%d)", ret);
+	} else if (ret<0)
+		pc->para.cause = NO_CAUSE;
+	if ((p = findie(skb->data, skb->len, IE_FACILITY, 0))) {
+		l3dss1_parse_facility(pc->st, pc, pc->callref, p);
+	}
+	if ((ret<0) && (pc->state != 11))
+		cause = 96;
+	else if (ret>0)
+		cause = 100;
+	ret = check_infoelements(pc, skb, ie_RELEASE);
+	if (ERR_IE_COMPREHENSION == ret)
+		cause = 96;
+	else if ((ERR_IE_UNRECOGNIZED == ret) && (!cause))
+		cause = 99;  
+	if (cause)
+		l3dss1_message_cause(pc, MT_RELEASE_COMPLETE, cause);
+	else
+		l3dss1_message(pc, MT_RELEASE_COMPLETE);
 	pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
 	newl3state(pc, 0);
-	release_l3_process(pc);
+	dss1_release_l3_process(pc);
 }
 
 static void
@@ -1161,66 +1959,360 @@
 		 void *arg)
 {
 	newl3state(pc, 7);
-	l3dss1_message(pc, MT_ALERTING);
+	if (!pc->prot.dss1.uus1_data[0]) 
+		l3dss1_message(pc, MT_ALERTING);
+	else
+		l3dss1_msg_with_uus(pc, MT_ALERTING); 
 }
 
 static void
-l3dss1_status_enq(struct l3_process *pc, u_char pr, void *arg)
+l3dss1_proceed_req(struct l3_process *pc, u_char pr,
+		   void *arg)
 {
-	u_char tmp[16];
-	u_char *p = tmp;
-	int l;
-	struct sk_buff *skb = arg;
+	newl3state(pc, 9);
+	l3dss1_message(pc, MT_CALL_PROCEEDING);
+	pc->st->l3.l3l4(pc->st, CC_PROCEED_SEND | INDICATION, pc); 
+}
 
-	dev_kfree_skb(skb);
+/********************************************/
+/* deliver a incoming display message to HL */
+/********************************************/
+static void
+l3dss1_deliver_display(struct l3_process *pc, int pr, u_char *infp)
+{       u_char len;
+        isdn_ctrl ic; 
+	struct IsdnCardState *cs;
+        char *p; 
 
-	MsgHead(p, pc->callref, MT_STATUS);
+        if (*infp++ != IE_DISPLAY) return;
+        if ((len = *infp++) > 80) return; /* total length <= 82 */
+	if (!pc->chan) return;
 
-	*p++ = IE_CAUSE;
-	*p++ = 0x2;
-	*p++ = 0x80;
-	*p++ = 0x9E;		/* answer status enquire */
+	p = ic.parm.display; 
+        while (len--)
+	  *p++ = *infp++;
+	*p = '\0';
+	ic.command = ISDN_STAT_DISPLAY;
+	cs = pc->st->l1.hardware;
+	ic.driver = cs->myid;
+	ic.arg = pc->chan->chan; 
+	cs->iif.statcallb(&ic);
+} /* l3dss1_deliver_display */
 
-	*p++ = 0x14;		/* CallState */
-	*p++ = 0x1;
-	*p++ = pc->state & 0x3f;
 
-	l = p - tmp;
-	if (!(skb = l3_alloc_skb(l)))
+static void
+l3dss1_progress(struct l3_process *pc, u_char pr, void *arg)
+{
+	struct sk_buff *skb = arg;
+	int err = 0;
+	u_char *p;
+
+	if ((p = findie(skb->data, skb->len, IE_PROGRESS, 0))) {
+		if (p[1] != 2) {
+			err = 1;
+			pc->para.cause = 100;
+		} else if (p[2] & 0x60) {
+			switch (p[2]) {
+				case 0x80:
+				case 0x81:
+				case 0x82:
+				case 0x84:
+				case 0x85:
+				case 0x87:
+				case 0x8a:
+					switch (p[3]) {
+						case 0x81:
+						case 0x82:
+						case 0x83:
+						case 0x84:
+						case 0x88:
+							break;
+						default:
+							err = 2;
+							pc->para.cause = 100;
+							break;
+					}
+					break;
+				default:
+					err = 3;
+					pc->para.cause = 100;
+					break;
+			}
+		}
+	} else {
+		pc->para.cause = 96;
+		err = 4;
+	}
+	if (err) {	
+		if (pc->debug & L3_DEB_WARN)
+			l3_debug(pc->st, "progress error %d", err);
+		l3dss1_status_send(pc, pr, NULL);
 		return;
-	memcpy(skb_put(skb, l), tmp, l);
-	l3_msg(pc->st, DL_DATA | REQUEST, skb);
+	}
+	/* Now we are on none mandatory IEs */
+	err = check_infoelements(pc, skb, ie_PROGRESS);
+	if (err)
+		l3dss1_std_ie_err(pc, err);
+	if (ERR_IE_COMPREHENSION != err)
+		pc->st->l3.l3l4(pc->st, CC_PROGRESS | INDICATION, pc);
 }
 
 static void
-l3dss1_status_req(struct l3_process *pc, u_char pr, void *arg)
+l3dss1_notify(struct l3_process *pc, u_char pr, void *arg)
 {
-	/* ETS 300-104 7.4.1, 8.4.1, 10.3.1, 11.4.1, 12.4.1, 13.4.1, 14.4.1...
-	   if setup has been made and a non expected message type is received, we must send MT_STATUS cause 0x62  */
-	u_char tmp[16];
-	u_char *p = tmp;
-	int l;
+	struct sk_buff *skb = arg;
+	int err = 0;
+	u_char *p;
+
+	if ((p = findie(skb->data, skb->len, IE_NOTIFY, 0))) {
+		if (p[1] != 1) {
+			err = 1;
+			pc->para.cause = 100;
+		} else {
+			switch (p[2]) {
+				case 0x80:
+				case 0x81:
+				case 0x82:
+					break;
+				default:
+					pc->para.cause = 100;
+					err = 2;
+					break;
+			}
+		}
+	} else {
+		pc->para.cause = 96;
+		err = 3;
+	}
+	if (err) {	
+		if (pc->debug & L3_DEB_WARN)
+			l3_debug(pc->st, "notify error %d", err);
+		l3dss1_status_send(pc, pr, NULL);
+		return;
+	}
+	/* Now we are on none mandatory IEs */
+	err = check_infoelements(pc, skb, ie_NOTIFY);
+	if (err)
+		l3dss1_std_ie_err(pc, err);
+	if (ERR_IE_COMPREHENSION != err)
+		pc->st->l3.l3l4(pc->st, CC_NOTIFY | INDICATION, pc);
+}
+
+static void
+l3dss1_status_enq(struct l3_process *pc, u_char pr, void *arg)
+{
+	int ret;
 	struct sk_buff *skb = arg;
 
-	dev_kfree_skb(skb);
+	ret = check_infoelements(pc, skb, ie_STATUS_ENQUIRY);
+	l3dss1_std_ie_err(pc, ret);
+// KKe 19.7.99 test eicon
+//        idev_kfree_skb(skb, FREE_READ);
+	pc->para.cause = 30; /* response to STATUS_ENQUIRY */
+        l3dss1_status_send(pc, pr, NULL);
+}
 
-	MsgHead(p, pc->callref, MT_STATUS);
+static void
+l3dss1_information(struct l3_process *pc, u_char pr, void *arg)
+{
+	int ret;
+	struct sk_buff *skb = arg;
 
-	*p++ = IE_CAUSE;
-	*p++ = 0x2;
-	*p++ = 0x80;
-	*p++ = 0x62 | 0x80;	/* status sending */
+	ret = check_infoelements(pc, skb, ie_INFORMATION);
+	l3dss1_std_ie_err(pc, ret);
+}
 
-	*p++ = 0x14;		/* CallState */
-	*p++ = 0x1;
-	*p++ = pc->state & 0x3f;
+/******************************/
+/* handle deflection requests */
+/******************************/
+static void l3dss1_redir_req(struct l3_process *pc, u_char pr, void *arg)
+{
+	struct sk_buff *skb;
+	u_char tmp[128];
+	u_char *p = tmp;
+        u_char *subp;
+        u_char len_phone = 0;
+        u_char len_sub = 0;
+	int l; 
+
+
+        strcpy(pc->prot.dss1.uus1_data,pc->chan->setup.eazmsn); /* copy uus element if available */
+        if (!pc->chan->setup.phone[0])
+          { pc->para.cause = -1;
+            l3dss1_disconnect_req(pc,pr,arg); /* disconnect immediately */
+            return;
+          } /* only uus */
+ 
+        if (pc->prot.dss1.invoke_id) 
+          free_invoke_id(pc->st,pc->prot.dss1.invoke_id);
+ 
+        if (!(pc->prot.dss1.invoke_id = new_invoke_id(pc->st))) 
+          return;
+
+        MsgHead(p, pc->callref, MT_FACILITY);
+
+        for (subp = pc->chan->setup.phone; (*subp) && (*subp != '.'); subp++) len_phone++; /* len of phone number */
+        if (*subp++ == '.') len_sub = strlen(subp) + 2; /* length including info subadress element */ 
+
+	*p++ = 0x1c;   /* Facility info element */
+        *p++ = len_phone + len_sub + 2 + 2 + 8 + 3 + 3; /* length of element */
+        *p++ = 0x91;  /* remote operations protocol */
+        *p++ = 0xa1;  /* invoke component */
+	  
+        *p++ = len_phone + len_sub + 2 + 2 + 8 + 3; /* length of data */
+        *p++ = 0x02;  /* invoke id tag, integer */
+	*p++ = 0x01;  /* length */
+        *p++ = pc->prot.dss1.invoke_id;  /* invoke id */ 
+        *p++ = 0x02;  /* operation value tag, integer */
+	*p++ = 0x01;  /* length */
+        *p++ = 0x0D;  /* Call Deflect */
+	  
+        *p++ = 0x30;  /* sequence phone number */
+        *p++ = len_phone + 2 + 2 + 3 + len_sub; /* length */
+	  
+        *p++ = 0x30;  /* Deflected to UserNumber */
+        *p++ = len_phone+2+len_sub; /* length */
+        *p++ = 0x80; /* NumberDigits */
+	*p++ = len_phone; /* length */
+        for (l = 0; l < len_phone; l++)
+	 *p++ = pc->chan->setup.phone[l];
+
+        if (len_sub)
+	  { *p++ = 0x04; /* called party subadress */
+            *p++ = len_sub - 2;
+            while (*subp) *p++ = *subp++;
+          }
+
+        *p++ = 0x01; /* screening identifier */
+        *p++ = 0x01;
+        *p++ = pc->chan->setup.screen;
 
 	l = p - tmp;
-	if (!(skb = l3_alloc_skb(l)))
-		return;
+	if (!(skb = l3_alloc_skb(l))) return;
 	memcpy(skb_put(skb, l), tmp, l);
-	l3_msg(pc->st, DL_DATA | REQUEST, skb);
-}
+
+        l3_msg(pc->st, DL_DATA | REQUEST, skb);
+} /* l3dss1_redir_req */
+
+/********************************************/
+/* handle deflection request in early state */
+/********************************************/
+static void l3dss1_redir_req_early(struct l3_process *pc, u_char pr, void *arg)
+{
+  l3dss1_proceed_req(pc,pr,arg);
+  l3dss1_redir_req(pc,pr,arg);
+} /* l3dss1_redir_req_early */
+
+/***********************************************/
+/* handle special commands for this protocol.  */
+/* Examples are call independant services like */
+/* remote operations with dummy  callref.      */
+/***********************************************/
+static int l3dss1_cmd_global(struct PStack *st, isdn_ctrl *ic)
+{ u_char id;
+  u_char temp[265];
+  u_char *p = temp;
+  int i, l, proc_len; 
+  struct sk_buff *skb;
+  struct l3_process *pc = NULL;
+
+  switch (ic->arg)
+   { case DSS1_CMD_INVOKE:
+       if (ic->parm.dss1_io.datalen < 0) return(-2); /* invalid parameter */ 
+
+       for (proc_len = 1, i = ic->parm.dss1_io.proc >> 8; i; i++) 
+         i = i >> 8; /* add one byte */    
+       l = ic->parm.dss1_io.datalen + proc_len + 8; /* length excluding ie header */
+       if (l > 255) 
+         return(-2); /* too long */
+
+       if (!(id = new_invoke_id(st))) 
+         return(0); /* first get a invoke id -> return if no available */
+       
+       i = -1; 
+       MsgHead(p, i, MT_FACILITY); /* build message head */
+       *p++ = 0x1C; /* Facility IE */
+       *p++ = l; /* length of ie */
+       *p++ = 0x91; /* remote operations */
+       *p++ = 0xA1; /* invoke */
+       *p++ = l - 3; /* length of invoke */
+       *p++ = 0x02; /* invoke id tag */
+       *p++ = 0x01; /* length is 1 */
+       *p++ = id; /* invoke id */
+       *p++ = 0x02; /* operation */
+       *p++ = proc_len; /* length of operation */
+       
+       for (i = proc_len; i; i--)
+         *p++ = (ic->parm.dss1_io.proc >> (i-1)) & 0xFF;
+       memcpy(p, ic->parm.dss1_io.data, ic->parm.dss1_io.datalen); /* copy data */
+       l = (p - temp) + ic->parm.dss1_io.datalen; /* total length */         
+
+       if (ic->parm.dss1_io.timeout > 0)
+        if (!(pc = dss1_new_l3_process(st, -1)))
+          { free_invoke_id(st, id);
+            return(-2);
+          } 
+       pc->prot.dss1.ll_id = ic->parm.dss1_io.ll_id; /* remember id */ 
+       pc->prot.dss1.proc = ic->parm.dss1_io.proc; /* and procedure */
+
+       if (!(skb = l3_alloc_skb(l))) 
+         { free_invoke_id(st, id);
+           if (pc) dss1_release_l3_process(pc);
+           return(-2);
+         }
+       memcpy(skb_put(skb, l), temp, l);
+       
+       if (pc)
+        { pc->prot.dss1.invoke_id = id; /* remember id */
+          L3AddTimer(&pc->timer, ic->parm.dss1_io.timeout, CC_TDSS1_IO | REQUEST);
+        }
+       
+       l3_msg(st, DL_DATA | REQUEST, skb);
+       ic->parm.dss1_io.hl_id = id; /* return id */
+       return(0);
+
+     case DSS1_CMD_INVOKE_ABORT:
+       if ((pc = l3dss1_search_dummy_proc(st, ic->parm.dss1_io.hl_id)))
+	{ L3DelTimer(&pc->timer); /* remove timer */
+          dss1_release_l3_process(pc);
+          return(0); 
+        } 
+       else
+	{ l3_debug(st, "l3dss1_cmd_global abort unknown id");
+          return(-2);
+        } 
+       break;
+    
+     default: 
+       l3_debug(st, "l3dss1_cmd_global unknown cmd 0x%lx", ic->arg);
+       return(-1);  
+   } /* switch ic-> arg */
+  return(-1);
+} /* l3dss1_cmd_global */
+
+static void 
+l3dss1_io_timer(struct l3_process *pc)
+{ isdn_ctrl ic;
+  struct IsdnCardState *cs = pc->st->l1.hardware;
+
+  L3DelTimer(&pc->timer); /* remove timer */
+
+  ic.driver = cs->myid;
+  ic.command = ISDN_STAT_PROT;
+  ic.arg = DSS1_STAT_INVOKE_ERR;
+  ic.parm.dss1_io.hl_id = pc->prot.dss1.invoke_id;
+  ic.parm.dss1_io.ll_id = pc->prot.dss1.ll_id;
+  ic.parm.dss1_io.proc = pc->prot.dss1.proc;
+  ic.parm.dss1_io.timeout= -1;
+  ic.parm.dss1_io.datalen = 0;
+  ic.parm.dss1_io.data = NULL;
+  free_invoke_id(pc->st, pc->prot.dss1.invoke_id);
+  pc->prot.dss1.invoke_id = 0; /* reset id */
+
+  cs->iif.statcallb(&ic);
+
+  dss1_release_l3_process(pc); 
+} /* l3dss1_io_timer */
 
 static void
 l3dss1_release_ind(struct l3_process *pc, u_char pr, void *arg)
@@ -1241,13 +2333,18 @@
 		 */
 		pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
 		newl3state(pc, 0);
-		release_l3_process(pc);
+		dss1_release_l3_process(pc);
 	} else {
 		pc->st->l3.l3l4(pc->st, CC_IGNORE | INDICATION, pc);
 	}
 }
 
 static void
+l3dss1_dummy(struct l3_process *pc, u_char pr, void *arg)
+{
+}
+
+static void
 l3dss1_t303(struct l3_process *pc, u_char pr, void *arg)
 {
 	if (pc->N303 > 0) {
@@ -1256,8 +2353,9 @@
 		l3dss1_setup_req(pc, pr, arg);
 	} else {
 		L3DelTimer(&pc->timer);
+		l3dss1_message_cause(pc, MT_RELEASE_COMPLETE, 102);
 		pc->st->l3.l3l4(pc->st, CC_NOSETUP_RSP, pc);
-		release_l3_process(pc);
+		dss1_release_l3_process(pc);
 	}
 }
 
@@ -1265,7 +2363,7 @@
 l3dss1_t304(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
-	pc->para.cause = 0xE6;
+	pc->para.cause = 102;
 	l3dss1_disconnect_req(pc, pr, NULL);
 	pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
 
@@ -1278,18 +2376,18 @@
 	u_char *p = tmp;
 	int l;
 	struct sk_buff *skb;
-	u_char cause = 0x90;
+	u_char cause = 16;
 
 	L3DelTimer(&pc->timer);
-	if (pc->para.cause > 0)
-		cause = pc->para.cause | 0x80;
+	if (pc->para.cause != NO_CAUSE)
+		cause = pc->para.cause;
 
 	MsgHead(p, pc->callref, MT_RELEASE);
 
 	*p++ = IE_CAUSE;
 	*p++ = 0x2;
 	*p++ = 0x80;
-	*p++ = cause;
+	*p++ = cause | 0x80;
 
 	l = p - tmp;
 	if (!(skb = l3_alloc_skb(l)))
@@ -1304,7 +2402,7 @@
 l3dss1_t310(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
-	pc->para.cause = 0xE6;
+	pc->para.cause = 102;
 	l3dss1_disconnect_req(pc, pr, NULL);
 	pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
 }
@@ -1313,7 +2411,7 @@
 l3dss1_t313(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
-	pc->para.cause = 0xE6;
+	pc->para.cause = 102;
 	l3dss1_disconnect_req(pc, pr, NULL);
 	pc->st->l3.l3l4(pc->st, CC_CONNECT_ERR, pc);
 }
@@ -1332,14 +2430,14 @@
 {
 	L3DelTimer(&pc->timer);
 	pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc);
-	release_l3_process(pc);
+	dss1_release_l3_process(pc);
 }
 
 static void
 l3dss1_t318(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
-	pc->para.cause = 0x66;	/* Timer expiry */
+	pc->para.cause = 102;	/* Timer expiry */
 	pc->para.loc = 0;	/* local */
 	pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc);
 	newl3state(pc, 19);
@@ -1351,7 +2449,7 @@
 l3dss1_t319(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
-	pc->para.cause = 0x66;	/* Timer expiry */
+	pc->para.cause = 102;	/* Timer expiry */
 	pc->para.loc = 0;	/* local */
 	pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc);
 	newl3state(pc, 10);
@@ -1361,69 +2459,80 @@
 l3dss1_restart(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
-	pc->st->l3.l3l4(pc->st, CC_DLRL | INDICATION, pc);
-	release_l3_process(pc);
+	pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
+	dss1_release_l3_process(pc);
 }
 
 static void
 l3dss1_status(struct l3_process *pc, u_char pr, void *arg)
 {
 	u_char *p;
-	char tmp[64], *t;
-	int l;
 	struct sk_buff *skb = arg;
-	int cause, callState;
-
-	cause = callState = -1;
-	p = skb->data;
-	t = tmp;
-	if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
-		p++;
-		l = *p++;
-		t += sprintf(t, "Status CR %x Cause:", pc->callref);
-		while (l--) {
-			cause = *p;
-			t += sprintf(t, " %2x", *p++);
-		}
-	} else
-		sprintf(t, "Status CR %x no Cause", pc->callref);
-	l3_debug(pc->st, tmp);
-	p = skb->data;
-	t = tmp;
-	t += sprintf(t, "Status state %x ", pc->state);
-	if ((p = findie(p, skb->len, IE_CALL_STATE, 0))) {
+	int ret; 
+	u_char cause = 0, callState = 0;
+	
+	if ((ret = l3dss1_get_cause(pc, skb))) {
+		if (pc->debug & L3_DEB_WARN)
+			l3_debug(pc->st, "STATUS get_cause ret(%d)",ret);
+		if (ret < 0)
+			cause = 96;
+		else if (ret > 0)
+			cause = 100;
+	}
+	if ((p = findie(skb->data, skb->len, IE_CALL_STATE, 0))) {
 		p++;
 		if (1 == *p++) {
 			callState = *p;
-			t += sprintf(t, "peer state %x", *p);
+			if (!ie_in_set(pc, *p, l3_valid_states))
+				cause = 100;
 		} else
-			t += sprintf(t, "peer state len error");
+			cause = 100;
 	} else
-		sprintf(t, "no peer state");
-	l3_debug(pc->st, tmp);
-	if (((cause & 0x7f) == 0x6f) && (callState == 0)) {
+		cause = 96;
+	if (!cause) { /*  no error before */
+		ret = check_infoelements(pc, skb, ie_STATUS);
+		if (ERR_IE_COMPREHENSION == ret)
+			cause = 96;
+		else if (ERR_IE_UNRECOGNIZED == ret)
+			cause = 99;
+	}
+	if (cause) {
+		u_char tmp;
+		
+		if (pc->debug & L3_DEB_WARN)
+			l3_debug(pc->st, "STATUS error(%d/%d)",ret,cause);
+		tmp = pc->para.cause;
+		pc->para.cause = cause;
+		l3dss1_status_send(pc, 0, NULL);
+		if (cause == 99)
+			pc->para.cause = tmp;
+		else
+			return;
+	}
+	cause = pc->para.cause;
+	if (((cause & 0x7f) == 111) && (callState == 0)) {
 		/* ETS 300-104 7.6.1, 8.6.1, 10.6.1...
-		 * if received MT_STATUS with cause == 0x6f and call
+		 * if received MT_STATUS with cause == 111 and call
 		 * state == 0, then we must set down layer 3
 		 */
-		l3dss1_release_ind(pc, pr, arg);
-	} else
-		dev_kfree_skb(skb);
+		pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
+		newl3state(pc, 0);
+		dss1_release_l3_process(pc);
+	}
 }
 
 static void
 l3dss1_facility(struct l3_process *pc, u_char pr, void *arg)
 {
-	u_char *p;
 	struct sk_buff *skb = arg;
-
-	p = skb->data;
-	if ((p = findie(p, skb->len, IE_FACILITY, 0))) {
-#if HISAX_DE_AOC
-		l3dss1_parse_facility(pc, p);
-#else
-		p = NULL;
-#endif
+	int ret;
+	
+	ret = check_infoelements(pc, skb, ie_FACILITY);
+	l3dss1_std_ie_err(pc, ret);
+ 	  {
+		u_char *p;
+		if ((p = findie(skb->data, skb->len, IE_FACILITY, 0)))
+			l3dss1_parse_facility(pc->st, pc, pc->callref, p);
 	}
 }
 
@@ -1438,14 +2547,14 @@
 
 	MsgHead(p, pc->callref, MT_SUSPEND);
 
-	*p++ = IE_CALLID;
+	*p++ = IE_CALL_ID;
 	l = *msg++;
 	if (l && (l <= 10)) {	/* Max length 10 octets */
 		*p++ = l;
 		for (i = 0; i < l; i++)
 			*p++ = *msg++;
 	} else {
-		l3_debug(pc->st, "SUS wrong CALLID len %d", l);
+		l3_debug(pc->st, "SUS wrong CALL_ID len %d", l);
 		return;
 	}
 	l = p - tmp;
@@ -1461,34 +2570,45 @@
 l3dss1_suspend_ack(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
+	int ret;
 
 	L3DelTimer(&pc->timer);
 	newl3state(pc, 0);
-	dev_kfree_skb(skb);
-	pc->para.cause = -1;
+	pc->para.cause = NO_CAUSE;
 	pc->st->l3.l3l4(pc->st, CC_SUSPEND | CONFIRM, pc);
-	release_l3_process(pc);
+	/* We don't handle suspend_ack for IE errors now */
+	if ((ret = check_infoelements(pc, skb, ie_SUSPEND_ACKNOWLEDGE)))
+		if (pc->debug & L3_DEB_WARN)
+			l3_debug(pc->st, "SUSPACK check ie(%d)",ret);
+	dss1_release_l3_process(pc);
 }
 
 static void
 l3dss1_suspend_rej(struct l3_process *pc, u_char pr, void *arg)
 {
-	u_char *p;
 	struct sk_buff *skb = arg;
-	int cause = -1;
+	int ret;
 
-	L3DelTimer(&pc->timer);
-	p = skb->data;
-	if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
-		p++;
-		if (*p++ == 2)
-			pc->para.loc = *p++;
-		cause = *p & 0x7f;
+	if ((ret = l3dss1_get_cause(pc, skb))) {
+		if (pc->debug & L3_DEB_WARN)
+			l3_debug(pc->st, "SUSP_REJ get_cause ret(%d)",ret);
+		if (ret < 0) 
+			pc->para.cause = 96;
+		else
+			pc->para.cause = 100;
+		l3dss1_status_send(pc, pr, NULL);
+		return;
+	}
+	ret = check_infoelements(pc, skb, ie_SUSPEND_REJECT);
+	if (ERR_IE_COMPREHENSION == ret) {
+		l3dss1_std_ie_err(pc, ret);
+		return;
 	}
-	dev_kfree_skb(skb);
-	pc->para.cause = cause;
+	L3DelTimer(&pc->timer);
 	pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc);
 	newl3state(pc, 10);
+	if (ret) /* STATUS for none mandatory IE errors after actions are taken */
+		l3dss1_std_ie_err(pc, ret);
 }
 
 static void
@@ -1502,14 +2622,14 @@
 
 	MsgHead(p, pc->callref, MT_RESUME);
 
-	*p++ = IE_CALLID;
+	*p++ = IE_CALL_ID;
 	l = *msg++;
 	if (l && (l <= 10)) {	/* Max length 10 octets */
 		*p++ = l;
 		for (i = 0; i < l; i++)
 			*p++ = *msg++;
 	} else {
-		l3_debug(pc->st, "RES wrong CALLID len %d", l);
+		l3_debug(pc->st, "RES wrong CALL_ID len %d", l);
 		return;
 	}
 	l = p - tmp;
@@ -1518,48 +2638,70 @@
 	memcpy(skb_put(skb, l), tmp, l);
 	l3_msg(pc->st, DL_DATA | REQUEST, skb);
 	newl3state(pc, 17);
-	L3AddTimer(&pc->timer, T319, CC_T319);
+	L3AddTimer(&pc->timer, T318, CC_T318);
 }
 
 static void
 l3dss1_resume_ack(struct l3_process *pc, u_char pr, void *arg)
 {
-	u_char *p;
 	struct sk_buff *skb = arg;
+	int id, ret;
 
+	if ((id = l3dss1_get_channel_id(pc, skb)) > 0) {
+		if ((0 == id) || ((3 == id) && (0x10 == pc->para.moderate))) {
+			if (pc->debug & L3_DEB_WARN)
+				l3_debug(pc->st, "resume ack with wrong chid %x", id);
+			pc->para.cause = 100;
+			l3dss1_status_send(pc, pr, NULL);
+			return;
+		}
+		pc->para.bchannel = id;
+	} else if (1 == pc->state) {
+		if (pc->debug & L3_DEB_WARN)
+			l3_debug(pc->st, "resume ack without chid (ret %d)", id);
+		pc->para.cause = 96;
+		l3dss1_status_send(pc, pr, NULL);
+		return;
+	}
+	ret = check_infoelements(pc, skb, ie_RESUME_ACKNOWLEDGE);
+	if (ERR_IE_COMPREHENSION == ret) {
+		l3dss1_std_ie_err(pc, ret);
+		return;
+	}
 	L3DelTimer(&pc->timer);
-	p = skb->data;
-	if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
-		pc->para.bchannel = p[2] & 0x3;
-		if ((!pc->para.bchannel) && (pc->debug & L3_DEB_WARN))
-			l3_debug(pc->st, "resume ack without bchannel");
-	} else if (pc->debug & L3_DEB_WARN)
-		l3_debug(pc->st, "resume ack without bchannel");
-	dev_kfree_skb(skb);
 	pc->st->l3.l3l4(pc->st, CC_RESUME | CONFIRM, pc);
 	newl3state(pc, 10);
+	if (ret) /* STATUS for none mandatory IE errors after actions are taken */
+		l3dss1_std_ie_err(pc, ret);
 }
 
 static void
 l3dss1_resume_rej(struct l3_process *pc, u_char pr, void *arg)
 {
-	u_char *p;
 	struct sk_buff *skb = arg;
-	int cause = -1;
+	int ret;
 
-	L3DelTimer(&pc->timer);
-	p = skb->data;
-	if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
-		p++;
-		if (*p++ == 2)
-			pc->para.loc = *p++;
-		cause = *p & 0x7f;
+	if ((ret = l3dss1_get_cause(pc, skb))) {
+		if (pc->debug & L3_DEB_WARN)
+			l3_debug(pc->st, "RES_REJ get_cause ret(%d)",ret);
+		if (ret < 0) 
+			pc->para.cause = 96;
+		else
+			pc->para.cause = 100;
+		l3dss1_status_send(pc, pr, NULL);
+		return;
 	}
-	dev_kfree_skb(skb);
-	pc->para.cause = cause;
-	newl3state(pc, 0);
+	ret = check_infoelements(pc, skb, ie_RESUME_REJECT);
+	if (ERR_IE_COMPREHENSION == ret) {
+		l3dss1_std_ie_err(pc, ret);
+		return;
+	}
+	L3DelTimer(&pc->timer);
 	pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc);
-	release_l3_process(pc);
+	newl3state(pc, 0);
+	if (ret) /* STATUS for none mandatory IE errors after actions are taken */
+		l3dss1_std_ie_err(pc, ret);
+	dss1_release_l3_process(pc);
 }
 
 static void
@@ -1589,7 +2731,6 @@
 		if (pc->st->l3.debug)
 			l3_debug(pc->st, "Restart for channel %d", chan);
 	}
-	dev_kfree_skb(skb);
 	newl3state(pc, 2);
 	up = pc->st->l3.proc;
 	while (up) {
@@ -1616,6 +2757,41 @@
 	newl3state(pc, 0);
 	l3_msg(pc->st, DL_DATA | REQUEST, skb);
 }
+
+static void
+l3dss1_dl_reset(struct l3_process *pc, u_char pr, void *arg)
+{
+        pc->para.cause = 0x29;          /* Temporary failure */
+        l3dss1_disconnect_req(pc, pr, NULL);
+        pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
+}
+
+static void
+l3dss1_dl_release(struct l3_process *pc, u_char pr, void *arg)
+{
+        newl3state(pc, 0);
+        pc->para.cause = 0x1b;          /* Destination out of order */
+        pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
+        release_l3_process(pc);
+}
+
+static void
+l3dss1_dl_reestablish(struct l3_process *pc, u_char pr, void *arg)
+{
+        L3DelTimer(&pc->timer);
+        L3AddTimer(&pc->timer, T309, CC_T309);
+        l3_msg(pc->st, DL_ESTABLISH | REQUEST, NULL);
+}
+ 
+static void
+l3dss1_dl_reest_status(struct l3_process *pc, u_char pr, void *arg)
+{
+	L3DelTimer(&pc->timer);
+ 
+ 	pc->para.cause = 0x1F; /* normal, unspecified */
+	l3dss1_status_send(pc, 0, NULL);
+}
+
 /* *INDENT-OFF* */
 static struct stateentry downstatelist[] =
 {
@@ -1623,24 +2799,32 @@
 	 CC_SETUP | REQUEST, l3dss1_setup_req},
 	{SBIT(0),
 	 CC_RESUME | REQUEST, l3dss1_resume_req},
-	{SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(6) | SBIT(7) | SBIT(8) | SBIT(10),
+	{SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(6) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10),
 	 CC_DISCONNECT | REQUEST, l3dss1_disconnect_req},
 	{SBIT(12),
 	 CC_RELEASE | REQUEST, l3dss1_release_req},
 	{ALL_STATES,
-	 CC_DLRL | REQUEST, l3dss1_reset},
-	{ALL_STATES,
 	 CC_RESTART | REQUEST, l3dss1_restart},
 	{SBIT(6),
 	 CC_IGNORE | REQUEST, l3dss1_reset},
 	{SBIT(6),
 	 CC_REJECT | REQUEST, l3dss1_reject_req},
 	{SBIT(6),
+	 CC_PROCEED_SEND | REQUEST, l3dss1_proceed_req},
+	{SBIT(6) | SBIT(9),
 	 CC_ALERTING | REQUEST, l3dss1_alert_req},
-	{SBIT(6) | SBIT(7),
+	{SBIT(6) | SBIT(7) | SBIT(9),
 	 CC_SETUP | RESPONSE, l3dss1_setup_rsp},
 	{SBIT(10),
 	 CC_SUSPEND | REQUEST, l3dss1_suspend_req},
+        {SBIT(6),
+         CC_PROCEED_SEND | REQUEST, l3dss1_proceed_req},
+        {SBIT(7) | SBIT(9),
+         CC_REDIR | REQUEST, l3dss1_redir_req},
+        {SBIT(6),
+         CC_REDIR | REQUEST, l3dss1_redir_req_early},
+        {SBIT(9) | SBIT(25),
+         CC_DISCONNECT | REQUEST, l3dss1_disconnect_req},
 	{SBIT(1),
 	 CC_T303, l3dss1_t303},
 	{SBIT(2),
@@ -1659,6 +2843,8 @@
 	 CC_T308_1, l3dss1_t308_1},
 	{SBIT(19),
 	 CC_T308_2, l3dss1_t308_2},
+	{SBIT(10),
+	 CC_T309, l3dss1_dl_release},
 };
 
 #define DOWNSLLEN \
@@ -1674,37 +2860,37 @@
 	 MT_STATUS, l3dss1_release_ind},
 	{ALL_STATES,
 	 MT_STATUS, l3dss1_status},
-	{SBIT(0) | SBIT(6),
+	{SBIT(0),
 	 MT_SETUP, l3dss1_setup},
+	{SBIT(6) | SBIT(7),
+	 MT_SETUP, l3dss1_dummy},
 	{SBIT(1) | SBIT(2),
 	 MT_CALL_PROCEEDING, l3dss1_call_proc},
-	{SBIT(3) | SBIT(4) | SBIT(8) | SBIT(10) | SBIT(11) | SBIT(19),
-	 MT_CALL_PROCEEDING, l3dss1_status_req},
 	{SBIT(1),
 	 MT_SETUP_ACKNOWLEDGE, l3dss1_setup_ack},
-	{SBIT(2) | SBIT(3) | SBIT(4) | SBIT(8) | SBIT(10) | SBIT(11) | SBIT(19),
-	 MT_SETUP_ACKNOWLEDGE, l3dss1_status_req},
-	{SBIT(1) | SBIT(2) | SBIT(3),
+	{SBIT(2) | SBIT(3),
 	 MT_ALERTING, l3dss1_alerting},
-	{SBIT(4) | SBIT(8) | SBIT(10) | SBIT(11) | SBIT(19),
-	 MT_ALERTING, l3dss1_status_req},
+	{SBIT(2) | SBIT(3),
+	 MT_PROGRESS, l3dss1_progress},
+	{SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) |
+	 SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(19) | SBIT(25),
+	 MT_INFORMATION, l3dss1_information},
+	{SBIT(10) | SBIT(11) | SBIT(15),
+	 MT_NOTIFY, l3dss1_notify},
 	{SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(10) |
-	 SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(19),
+	 SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(19) | SBIT(25),
 	 MT_RELEASE_COMPLETE, l3dss1_release_cmpl},
-	{SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(10) |
-	 SBIT(11) | SBIT(12) | SBIT(15) /* | SBIT(17) | SBIT(19)*/,
+	{SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(25),
 	 MT_RELEASE, l3dss1_release},
 	{SBIT(19),  MT_RELEASE, l3dss1_release_ind},
-	{SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(10) | SBIT(15),
+	{SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(11) | SBIT(15) | SBIT(17) | SBIT(25),
 	 MT_DISCONNECT, l3dss1_disconnect},
-	{SBIT(11),
-	 MT_DISCONNECT, l3dss1_release_req},
+//	{SBIT(11),
+//	 MT_DISCONNECT, l3dss1_release_req},
+	{SBIT(19),
+	 MT_DISCONNECT, l3dss1_dummy},
 	{SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4),
 	 MT_CONNECT, l3dss1_connect},
-	{SBIT(8) | SBIT(10) | SBIT(11) | SBIT(19),
-	 MT_CONNECT, l3dss1_status_req},
-	{SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(11) | SBIT(19),
-	 MT_CONNECT_ACKNOWLEDGE, l3dss1_status_req},
 	{SBIT(8),
 	 MT_CONNECT_ACKNOWLEDGE, l3dss1_connect_ack},
 	{SBIT(15),
@@ -1715,8 +2901,6 @@
 	 MT_RESUME_ACKNOWLEDGE, l3dss1_resume_ack},
 	{SBIT(17),
 	 MT_RESUME_REJECT, l3dss1_resume_rej},
-	{SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(8) | SBIT(10) | SBIT(11) | SBIT(15) | SBIT(17) | SBIT(19),
-	 MT_INVALID, l3dss1_status_req},
 };
 
 #define DATASLLEN \
@@ -1734,26 +2918,56 @@
 };
 #define GLOBALM_LEN \
 	(sizeof(globalmes_list) / sizeof(struct stateentry))
+
+static struct stateentry manstatelist[] =
+{
+        {SBIT(2),
+         DL_ESTABLISH | INDICATION, l3dss1_dl_reset},
+        {SBIT(10),
+         DL_ESTABLISH | CONFIRM, l3dss1_dl_reest_status},
+        {SBIT(10),
+         DL_RELEASE | INDICATION, l3dss1_dl_reestablish},
+        {ALL_STATES,
+         DL_RELEASE | INDICATION, l3dss1_dl_release},
+};
+
+#define MANSLLEN \
+        (sizeof(manstatelist) / sizeof(struct stateentry))
 /* *INDENT-ON* */
 
 
 static void
 global_handler(struct PStack *st, int mt, struct sk_buff *skb)
 {
+	u_char tmp[16];
+	u_char *p = tmp;
+	int l;
 	int i;
 	struct l3_process *proc = st->l3.global;
 
+	proc->callref = skb->data[2]; /* cr flag */
 	for (i = 0; i < GLOBALM_LEN; i++)
 		if ((mt == globalmes_list[i].primitive) &&
 		    ((1 << proc->state) & globalmes_list[i].state))
 			break;
 	if (i == GLOBALM_LEN) {
-		dev_kfree_skb(skb);
 		if (st->l3.debug & L3_DEB_STATE) {
 			l3_debug(st, "dss1 global state %d mt %x unhandled",
 				proc->state, mt);
 		}
-		return;
+		MsgHead(p, proc->callref, MT_STATUS);
+		*p++ = IE_CAUSE;
+		*p++ = 0x2;
+		*p++ = 0x80;
+		*p++ = 81 |0x80;	/* invalid cr */
+		*p++ = 0x14;		/* CallState */
+		*p++ = 0x1;
+		*p++ = proc->state & 0x3f;
+		l = p - tmp;
+		if (!(skb = l3_alloc_skb(l)))
+			return;
+		memcpy(skb_put(skb, l), tmp, l);
+		l3_msg(proc->st, DL_DATA | REQUEST, skb);
 	} else {
 		if (st->l3.debug & L3_DEB_STATE) {
 			l3_debug(st, "dss1 global %d mt %x",
@@ -1768,6 +2982,7 @@
 {
 	int i, mt, cr, cause, callState;
 	char *ptr;
+	u_char *p;
 	struct sk_buff *skb = arg;
 	struct l3_process *proc;
 
@@ -1782,23 +2997,57 @@
 			l3_msg(st, pr, arg);
 			return;
 			break;
+                default:
+                        printk(KERN_ERR "HiSax dss1up unknown pr=%04x\n", pr);
+                        return;
+	}
+	if (skb->len < 3) {
+		l3_debug(st, "dss1up frame too short(%d)", skb->len);
+		idev_kfree_skb(skb, FREE_READ);
+		return;
 	}
+
 	if (skb->data[0] != PROTO_DIS_EURO) {
 		if (st->l3.debug & L3_DEB_PROTERR) {
 			l3_debug(st, "dss1up%sunexpected discriminator %x message len %d",
 				 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
 				 skb->data[0], skb->len);
 		}
-		dev_kfree_skb(skb);
+		idev_kfree_skb(skb, FREE_READ);
 		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);
+		return;
+	}
 	mt = skb->data[skb->data[1] + 2];
-	if (!cr) {		/* Global CallRef */
-		global_handler(st, mt, skb);
+	if (st->l3.debug & L3_DEB_STATE)
+		l3_debug(st, "dss1up cr %d", cr);
+	if (cr == -2) {  /* wrong Callref */
+		if (st->l3.debug & L3_DEB_WARN)
+			l3_debug(st, "dss1up wrong Callref");
+		idev_kfree_skb(skb, FREE_READ);
 		return;
 	} else if (cr == -1) {	/* Dummy Callref */
-		dev_kfree_skb(skb);
+		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);
+				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);
+		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);
 		return;
 	} else if (!(proc = getl3proc(st, cr))) {
 		/* No transaction process exist, that means no call with
@@ -1806,12 +3055,19 @@
 		 */
 		if (mt == MT_SETUP) {
 			/* Setup creates a new transaction process */
-			if (!(proc = new_l3_process(st, cr))) {
+			if (skb->data[2] & 0x80) {
+				/* 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);
+				return;
+			}
+			if (!(proc = dss1_new_l3_process(st, cr))) {
 				/* May be to answer with RELEASE_COMPLETE and
 				 * CAUSE 0x2f "Resource unavailable", but this
 				 * need a new_l3_process too ... arghh
 				 */
-				dev_kfree_skb(skb);
+				idev_kfree_skb(skb, FREE_READ);
 				return;
 			}
 		} else if (mt == MT_STATUS) {
@@ -1829,62 +3085,60 @@
 					ptr++;
 				callState = *ptr;
 			}
-			if (callState == 0) {
-				/* ETS 300-104 part 2.4.1
-				 * if setup has not been made and a message type
-				 * MT_STATUS is received with call state == 0,
-				 * we must send nothing
-				 */
-				dev_kfree_skb(skb);
-				return;
-			} else {
+			/* ETS 300-104 part 2.4.1
+			 * if setup has not been made and a message type
+			 * MT_STATUS is received with call state == 0,
+			 * we must send nothing
+			 */
+			if (callState != 0) {
 				/* ETS 300-104 part 2.4.2
 				 * if setup has not been made and a message type
 				 * MT_STATUS is received with call state != 0,
 				 * we must send MT_RELEASE_COMPLETE cause 101
 				 */
-				dev_kfree_skb(skb);
-				if ((proc = new_l3_process(st, cr))) {
-					proc->para.cause = 0x65;	/* 101 */
+				if ((proc = dss1_new_l3_process(st, cr))) {
+					proc->para.cause = 101;
 					l3dss1_msg_without_setup(proc, 0, NULL);
 				}
-				return;
 			}
+			idev_kfree_skb(skb, FREE_READ);
+			return;
 		} else if (mt == MT_RELEASE_COMPLETE) {
-			dev_kfree_skb(skb);
+			idev_kfree_skb(skb, FREE_READ);
 			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 */
-			dev_kfree_skb(skb);
-			if ((proc = new_l3_process(st, cr))) {
-				proc->para.cause = 0x51;	/* 81 */
+			idev_kfree_skb(skb, FREE_READ);
+			if ((proc = dss1_new_l3_process(st, cr))) {
+				proc->para.cause = 81;
 				l3dss1_msg_without_setup(proc, 0, NULL);
 			}
 			return;
 		}
-	} else if (!l3dss1_check_messagetype_validity(mt)) {
-		/* ETS 300-104 7.4.2, 8.4.2, 10.3.2, 11.4.2, 12.4.2, 13.4.2,
-		 * 14.4.2...
-		 * if setup has been made and invalid message type is received,
-		 * we must send MT_STATUS cause 0x62
-		 */
-		mt = MT_INVALID;	/* sorry, not clean, but do the right thing ;-) */
 	}
+	if (l3dss1_check_messagetype_validity(proc, mt, skb)) {
+		idev_kfree_skb(skb, FREE_READ);
+		return;
+	}
+	if ((p = findie(skb->data, skb->len, IE_DISPLAY, 0)) != NULL) 
+	  l3dss1_deliver_display(proc, pr, p); /* Display IE included */
 	for (i = 0; i < DATASLLEN; i++)
 		if ((mt == datastatelist[i].primitive) &&
 		    ((1 << proc->state) & datastatelist[i].state))
 			break;
 	if (i == DATASLLEN) {
-		dev_kfree_skb(skb);
 		if (st->l3.debug & L3_DEB_STATE) {
-			l3_debug(st, "dss1up%sstate %d mt %x unhandled",
+			l3_debug(st, "dss1up%sstate %d mt %#x unhandled",
 				(pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
 				proc->state, mt);
 		}
-		return;
+		if ((MT_RELEASE_COMPLETE != mt) && (MT_RELEASE != mt)) {
+			proc->para.cause = 101;
+			l3dss1_status_send(proc, pr, skb);
+		}
 	} else {
 		if (st->l3.debug & L3_DEB_STATE) {
 			l3_debug(st, "dss1up%sstate %d mt %x",
@@ -1893,6 +3147,8 @@
 		}
 		datastatelist[i].rout(proc, pr, skb);
 	}
+	idev_kfree_skb(skb, FREE_READ);
+	return;
 }
 
 static void
@@ -1902,14 +3158,14 @@
 	struct l3_process *proc;
 	struct Channel *chan;
 
-	if (((DL_ESTABLISH | REQUEST) == pr) || ((DL_RELEASE | REQUEST) == pr)) {
+	if ((DL_ESTABLISH | REQUEST) == pr) {
 		l3_msg(st, pr, NULL);
 		return;
 	} else if (((CC_SETUP | REQUEST) == pr) || ((CC_RESUME | REQUEST) == pr)) {
 		chan = arg;
 		cr = newcallref();
 		cr |= 0x80;
-		if ((proc = new_l3_process(st, cr))) {
+		if ((proc = dss1_new_l3_process(st, cr))) {
 			proc->chan = chan;
 			chan->proc = proc;
 			proc->para.setup = chan->setup;
@@ -1922,32 +3178,75 @@
 		printk(KERN_ERR "HiSax dss1down without proc pr=%04x\n", pr);
 		return;
 	}
+
+	if ( pr == (CC_TDSS1_IO | REQUEST)) {
+		l3dss1_io_timer(proc); /* timer expires */ 
+		return;
+	}  
+
 	for (i = 0; i < DOWNSLLEN; i++)
 		if ((pr == downstatelist[i].primitive) &&
 		    ((1 << proc->state) & downstatelist[i].state))
 			break;
 	if (i == DOWNSLLEN) {
 		if (st->l3.debug & L3_DEB_STATE) {
-			l3_debug(st, "dss1down state %d prim %d unhandled",
+			l3_debug(st, "dss1down state %d prim %#x unhandled",
 				proc->state, pr);
 		}
 	} else {
 		if (st->l3.debug & L3_DEB_STATE) {
-			l3_debug(st, "dss1down state %d prim %d",
+			l3_debug(st, "dss1down state %d prim %#x",
 				proc->state, pr);
 		}
 		downstatelist[i].rout(proc, pr, arg);
 	}
 }
 
+static void
+dss1man(struct PStack *st, int pr, void *arg)
+{
+        int i;
+        struct l3_process *proc = arg;
+ 
+        if (!proc) {
+                printk(KERN_ERR "HiSax dss1man without proc pr=%04x\n", pr);
+                return;
+        }
+        for (i = 0; i < MANSLLEN; i++)
+                if ((pr == manstatelist[i].primitive) &&
+                    ((1 << proc->state) & manstatelist[i].state))
+                        break;
+        if (i == MANSLLEN) {
+                if (st->l3.debug & L3_DEB_STATE) {
+                        l3_debug(st, "cr %d dss1man state %d prim %#x unhandled",
+                                proc->callref & 0x7f, proc->state, pr);
+                }
+        } else {
+                if (st->l3.debug & L3_DEB_STATE) {
+                        l3_debug(st, "cr %d dss1man state %d prim %#x",
+                                proc->callref & 0x7f, proc->state, pr);
+                }
+                manstatelist[i].rout(proc, pr, arg);
+        }
+}
+ 
 void
 setstack_dss1(struct PStack *st)
 {
 	char tmp[64];
+	int i;
 
 	st->lli.l4l3 = dss1down;
+	st->lli.l4l3_proto = l3dss1_cmd_global;
 	st->l2.l2l3 = dss1up;
+	st->l3.l3ml3 = dss1man;
 	st->l3.N303 = 1;
+	st->prot.dss1.last_invoke_id = 0;
+	st->prot.dss1.invoke_used[0] = 1; /* Bit 0 must always be set to 1 */
+	i = 1;
+	while (i < 32) 
+		st->prot.dss1.invoke_used[i++] = 0;   
+
 	if (!(st->l3.global = kmalloc(sizeof(struct l3_process), GFP_ATOMIC))) {
 		printk(KERN_ERR "HiSax can't get memory for dss1 global CR\n");
 	} else {
@@ -1957,6 +3256,8 @@
 		st->l3.global->debug = L3_DEB_WARN;
 		st->l3.global->st = st;
 		st->l3.global->N303 = 1;
+		st->l3.global->prot.dss1.invoke_id = 0; 
+
 		L3InitTimer(st->l3.global, &st->l3.global->timer);
 	}
 	strcpy(tmp, dss1_revision);
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/l3dss1.h linux/drivers/isdn/hisax/l3dss1.h
--- v2.3.13/linux/drivers/isdn/hisax/l3dss1.h	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/hisax/l3dss1.h	Thu Aug 12 09:42:33 1999
@@ -1,8 +1,11 @@
-/* $Id: l3dss1.h,v 1.6 1998/03/19 13:18:50 keil Exp $
+/* $Id: l3dss1.h,v 1.7 1999/07/01 08:12:02 keil Exp $
  *
  *  DSS1 (Euro) D-channel protocol defines
  *
  * $Log: l3dss1.h,v $
+ * Revision 1.7  1999/07/01 08:12:02  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 1.6  1998/03/19 13:18:50  keil
  * Start of a CAPI like interface for supplementary Service
  * first service: SUSPEND
@@ -25,10 +28,14 @@
  *
  *
  */
+
+#ifndef l3dss1_process
+
 #define T303	4000
 #define T304	30000
 #define T305	30000
 #define T308	4000
+#define T309	40000
 #define T310	30000
 #define T313	4000
 #define T318	4000
@@ -38,39 +45,99 @@
  * Message-Types
  */
 
-#define MT_ALERTING            0x01
-#define MT_CALL_PROCEEDING     0x02
-#define MT_CONNECT             0x07
-#define MT_CONNECT_ACKNOWLEDGE 0x0f
-#define MT_PROGRESS            0x03
-#define MT_SETUP               0x05
-#define MT_SETUP_ACKNOWLEDGE   0x0d
-#define MT_RESUME              0x26
-#define MT_RESUME_ACKNOWLEDGE  0x2e
-#define MT_RESUME_REJECT       0x22
-#define MT_SUSPEND             0x25
-#define MT_SUSPEND_ACKNOWLEDGE 0x2d
-#define MT_SUSPEND_REJECT      0x21
-#define MT_USER_INFORMATION    0x20
-#define MT_DISCONNECT          0x45
-#define MT_RELEASE             0x4d
-#define MT_RELEASE_COMPLETE    0x5a
-#define MT_RESTART             0x46
-#define MT_RESTART_ACKNOWLEDGE 0x4e
-#define MT_SEGMENT             0x60
-#define MT_CONGESTION_CONTROL  0x79
-#define MT_INFORMATION         0x7b
-#define MT_FACILITY            0x62
-#define MT_NOTIFY              0x6e
-#define MT_STATUS              0x7d
-#define MT_STATUS_ENQUIRY      0x75
-
-#define MT_INVALID             0xff
-
-#define IE_BEARER              0x04
-#define IE_CAUSE               0x08
-#define IE_CALLID              0x10
-#define IE_FACILITY            0x1c
-#define IE_CALL_STATE          0x14
-#define IE_CHANNEL_ID          0x18
-#define IE_RESTART_IND         0x79
+#define MT_ALERTING		0x01
+#define MT_CALL_PROCEEDING	0x02
+#define MT_CONNECT		0x07
+#define MT_CONNECT_ACKNOWLEDGE	0x0f
+#define MT_PROGRESS		0x03
+#define MT_SETUP		0x05
+#define MT_SETUP_ACKNOWLEDGE	0x0d
+#define MT_RESUME		0x26
+#define MT_RESUME_ACKNOWLEDGE	0x2e
+#define MT_RESUME_REJECT	0x22
+#define MT_SUSPEND		0x25
+#define MT_SUSPEND_ACKNOWLEDGE	0x2d
+#define MT_SUSPEND_REJECT	0x21
+#define MT_USER_INFORMATION	0x20
+#define MT_DISCONNECT		0x45
+#define MT_RELEASE		0x4d
+#define MT_RELEASE_COMPLETE	0x5a
+#define MT_RESTART		0x46
+#define MT_RESTART_ACKNOWLEDGE	0x4e
+#define MT_SEGMENT		0x60
+#define MT_CONGESTION_CONTROL	0x79
+#define MT_INFORMATION		0x7b
+#define MT_FACILITY		0x62
+#define MT_NOTIFY		0x6e
+#define MT_STATUS		0x7d
+#define MT_STATUS_ENQUIRY	0x75
+
+#define IE_SEGMENT	0x00
+#define IE_BEARER	0x04
+#define IE_CAUSE	0x08
+#define IE_CALL_ID	0x10
+#define IE_CALL_STATE	0x14
+#define IE_CHANNEL_ID	0x18
+#define IE_FACILITY	0x1c
+#define IE_PROGRESS	0x1e
+#define IE_NET_FAC	0x20
+#define IE_NOTIFY	0x27
+#define IE_DISPLAY	0x28
+#define IE_DATE		0x29
+#define IE_KEYPAD	0x2c
+#define IE_SIGNAL	0x34
+#define IE_INFORATE	0x40
+#define IE_E2E_TDELAY	0x42
+#define IE_TDELAY_SEL	0x43
+#define IE_PACK_BINPARA	0x44
+#define IE_PACK_WINSIZE	0x45
+#define IE_PACK_SIZE	0x46
+#define IE_CUG		0x47
+#define	IE_REV_CHARGE	0x4a
+#define IE_CONNECT_PN	0x4c
+#define IE_CONNECT_SUB	0x4d
+#define IE_CALLING_PN	0x6c
+#define IE_CALLING_SUB	0x6d
+#define IE_CALLED_PN	0x70
+#define IE_CALLED_SUB	0x71
+#define IE_REDIR_NR	0x74
+#define IE_TRANS_SEL	0x78
+#define IE_RESTART_IND	0x79
+#define IE_LLC		0x7c
+#define IE_HLC		0x7d
+#define IE_USER_USER	0x7e
+#define IE_ESCAPE	0x7f
+#define IE_SHIFT	0x90
+#define IE_MORE_DATA	0xa0
+#define IE_COMPLETE	0xa1
+#define IE_CONGESTION	0xb0
+#define IE_REPEAT	0xd0
+
+#define IE_MANDATORY	0x0100
+/* mandatory not in every case */
+#define IE_MANDATORY_1	0x0200
+
+#define ERR_IE_COMPREHENSION	 1
+#define ERR_IE_UNRECOGNIZED	-1
+#define ERR_IE_LENGTH		-2
+#define ERR_IE_SEQUENCE		-3
+
+#else /* only l3dss1_process */
+
+/* l3dss1 specific data in l3 process */
+typedef struct
+  { unsigned char invoke_id; /* used invoke id in remote ops, 0 = not active */
+    ulong ll_id; /* remebered ll id */
+    u_char remote_operation; /* handled remote operation, 0 = not active */ 
+    int proc; /* rememered procedure */  
+    ulong remote_result; /* result of remote operation for statcallb */
+    char uus1_data[35]; /* data send during alerting or disconnect */
+  } dss1_proc_priv;
+
+/* l3dss1 specific data in protocol stack */
+typedef struct
+  { unsigned char last_invoke_id; /* last used value for invoking */
+    unsigned char invoke_used[32]; /* 256 bits for 256 values */
+  } dss1_stk_priv;        
+
+#endif /* only l3dss1_process */
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/lmgr.c linux/drivers/isdn/hisax/lmgr.c
--- v2.3.13/linux/drivers/isdn/hisax/lmgr.c	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/hisax/lmgr.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: lmgr.c,v 1.5 1998/11/15 23:55:12 keil Exp $
+/* $Id: lmgr.c,v 1.6 1999/07/01 08:12:04 keil Exp $
 
  * Author       Karsten Keil (keil@isdn4linux.de)
  *
@@ -6,6 +6,9 @@
  *  Layermanagement module
  *
  * $Log: lmgr.c,v $
+ * Revision 1.6  1999/07/01 08:12:04  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 1.5  1998/11/15 23:55:12  keil
  * changes from 2.0
  *
@@ -50,7 +53,7 @@
 		case (MDL_ERROR | INDICATION):
 			Code = (long) arg;
 			HiSax_putstatus(st->l1.hardware, "manager: MDL_ERROR",
-				"%c %s\n", (char)Code, 
+				" %c %s", (char)Code, 
 				test_bit(FLG_LAPD, &st->l2.flag) ?
 				"D-channel" : "B-channel");
 			if (test_bit(FLG_LAPD, &st->l2.flag))
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/md5sums.asc linux/drivers/isdn/hisax/md5sums.asc
--- v2.3.13/linux/drivers/isdn/hisax/md5sums.asc	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/hisax/md5sums.asc	Thu Aug 12 09:42:33 1999
@@ -2,28 +2,30 @@
 
 # This are valid md5sums for certificated HiSax driver.
 # The certification is valid only if the md5sums of all files match.
-# The certification is valid only for ELSA QuickStep cards in the moment.
+# The certification is valid only for ELSA QuickStep cards and
+# Eicon Technology Diva 2.01 PCI cards in the moment.
 # Read ../../../Documentation/isdn/HiSax.cert for more informations.
 # 
-a273c532aec063574273ee519975cd9a  isac.c
-27c5c5bfa2ceabf02e2e6d686b03abde  isdnl1.c
-8c89ac659d3188ab997fb575da22b566  isdnl2.c
-d0fa912aa284b8fd19fed86b65999f6f  isdnl3.c
-1bce120740b615006286ad9b2d7fcdcb  tei.c
-8845f88dd17917d9b58badeff1605057  callc.c
-f3ec2a634f06074d16167aaba02b6dc1  cert.c
-71840ec8189f42b0db86fb38e5e5984c  l3dss1.c
-1882de8bea921b9ccd98fbe77267aa04  l3_1tr6.c
-3bd7af3a11693d028300278744d0da09  elsa.c
+d93f31e02c1b153ec04d16f69e5688b3  isac.c
+e2a78c07f32c8ca7c88fc9f92a87dfab  isdnl1.c
+54490c4f46a998ff4ef34287bc262185  isdnl2.c
+f4184a50e35e5b568608e6cb7a693319  isdnl3.c
+ef70f4269fdc2ca15100f9b776afaa0d  tei.c
+cf3923304983e9d64cf35bc5a3533f6c  callc.c
+bf9605b36429898f7be6630034e83230  cert.c
+309261e4c36d950db6978440e8bc8342  l3dss1.c
+b674eee9314a7cc413971c84003cf1d2  l3_1tr6.c
+8f86d92f43ecc42f6457773168cfc114  elsa.c
+24cda374da44b57f6a1bb215424267b5  diva.c
 # end of md5sums
 
 -----BEGIN PGP SIGNATURE-----
 Version: 2.6.3i
 Charset: noconv
 
-iQCVAwUBNrl5JDpxHvX/mS9tAQHm8wP+Nk64UJ2abdDG/igXZSrwcYhX/Kp7cxt9
-ccYp+aaur+pALA0lxwY3xcLt9u36fCYuTLHAVmQoiC9Vbemj37yzM2rUpz9nkw/7
-D6gLqZs2jxVpAwVVJgp0JwDONKXaRX6Lt2EPD9PTW6vxRWEu0HqGhM5hrtd/o4rV
-mC1W7Wj13XM=
-=LdhT
+iQCVAwUBN7HnvDpxHvX/mS9tAQFANgP+LGuG98lvCv97vN2dc6T/6hZTxFW+WirJ
+XMhU5NHoZ+8MISMOVKB7ugsGO9cJI0lUA0sOe8jtPCo5070nF1ZkNsxV/x7WK2dS
+RwXfHy6+TAH7qIiBnkP9odB2lib+VFl/nnkkTwsXfVwRCD8bLaagMPv+nAveDoNE
+uff0xxXEnJw=
+=Wu2M
 -----END PGP SIGNATURE-----
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/mic.c linux/drivers/isdn/hisax/mic.c
--- v2.3.13/linux/drivers/isdn/hisax/mic.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/isdn/hisax/mic.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: mic.c,v 1.7 1998/04/15 16:44:32 keil Exp $
+/* $Id: mic.c,v 1.8 1999/07/12 21:05:20 keil Exp $
 
  * mic.c  low level stuff for mic cards
  *
@@ -8,6 +8,10 @@
  *
  *
  * $Log: mic.c,v $
+ * Revision 1.8  1999/07/12 21:05:20  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
  * Revision 1.7  1998/04/15 16:44:32  keil
  * new init code
  *
@@ -40,7 +44,7 @@
 
 extern const char *CardType[];
 
-const char *mic_revision = "$Revision: 1.7 $";
+const char *mic_revision = "$Revision: 1.8 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -158,7 +162,7 @@
 mic_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u_char val, stat = 0;
+	u_char val;
 
 	if (!cs) {
 		printk(KERN_WARNING "mic: Spurious interrupt!\n");
@@ -166,16 +170,12 @@
 	}
 	val = readreg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_ISTA + 0x40);
       Start_HSCX:
-	if (val) {
+	if (val)
 		hscx_int_main(cs, val);
-		stat |= 1;
-	}
 	val = readreg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_ISTA);
       Start_ISAC:
-	if (val) {
+	if (val)
 		isac_interrupt(cs, val);
-		stat |= 2;
-	}
 	val = readreg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_ISTA + 0x40);
 	if (val) {
 		if (cs->debug & L1_DEB_HSCX)
@@ -188,16 +188,12 @@
 			debugl1(cs, "ISAC IntStat after IntRoutine");
 		goto Start_ISAC;
 	}
-	if (stat & 1) {
-		writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK, 0xFF);
-		writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK + 0x40, 0xFF);
-		writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK, 0x0);
-		writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK + 0x40, 0x0);
-	}
-	if (stat & 2) {
-		writereg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_MASK, 0xFF);
-		writereg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_MASK, 0x0);
-	}
+	writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK, 0xFF);
+	writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK + 0x40, 0xFF);
+	writereg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_MASK, 0x0);
+	writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK, 0x0);
+	writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK + 0x40, 0x0);
 }
 
 void
@@ -218,9 +214,6 @@
 		case CARD_RELEASE:
 			release_io_mic(cs);
 			return(0);
-		case CARD_SETIRQ:
-			return(request_irq(cs->irq, &mic_interrupt,
-					I4L_IRQ_FLAG, "HiSax", cs));
 		case CARD_INIT:
 			inithscx(cs); /* /RTSA := ISAC RST */
 			inithscxisac(cs, 3);
@@ -231,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;
@@ -273,6 +266,7 @@
 	cs->BC_Write_Reg = &WriteHSCX;
 	cs->BC_Send_Data = &hscx_fill_fifo;
 	cs->cardmsg = &mic_card_msg;
+	cs->irq_func = &mic_interrupt;
 	ISACVersion(cs, "mic:");
 	if (HscxVersion(cs, "mic:")) {
 		printk(KERN_WARNING
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/netjet.c linux/drivers/isdn/hisax/netjet.c
--- v2.3.13/linux/drivers/isdn/hisax/netjet.c	Mon Aug  9 14:59:20 1999
+++ linux/drivers/isdn/hisax/netjet.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: netjet.c,v 1.8 1998/11/15 23:55:14 keil Exp $
+/* $Id: netjet.c,v 1.13 1999/08/11 21:01:31 keil Exp $
 
  * netjet.c     low level stuff for Traverse Technologie NETJet ISDN cards
  *
@@ -6,8 +6,25 @@
  *
  * Thanks to Traverse Technologie Australia for documents and informations
  *
- *
  * $Log: netjet.c,v $
+ * Revision 1.13  1999/08/11 21:01:31  keil
+ * new PCI codefix
+ *
+ * Revision 1.12  1999/08/10 16:02:00  calle
+ * struct pci_dev changed in 2.3.13. Made the necessary changes.
+ *
+ * Revision 1.11  1999/08/07 17:32:00  keil
+ * Asymetric buffers for improved ping times.  Interframe spacing
+ * fix for NJ<->NJ thoughput.  Matt Henderson - www.traverse.com.au
+ *
+ *
+ * Revision 1.10  1999/07/12 21:05:22  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 1.9  1999/07/01 08:12:05  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 1.8  1998/11/15 23:55:14  keil
  * changes from 2.0
  *
@@ -42,12 +59,23 @@
 #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>
 
+#ifndef bus_to_virt
+#define bus_to_virt (u_int *)
+#endif
+
+#ifndef virt_to_bus
+#define virt_to_bus (u_int)
+#endif
+
 extern const char *CardType[];
 
-const char *NETjet_revision = "$Revision: 1.8 $";
+const char *NETjet_revision = "$Revision: 1.13 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -83,7 +111,8 @@
 #define NETJET_IRQM0_WRITE_1	0x01
 #define NETJET_IRQM0_WRITE_2	0x02
 
-#define NETJET_DMA_SIZE 512
+#define NETJET_DMA_TXSIZE 512
+#define NETJET_DMA_RXSIZE 128
 
 #define HDLC_ZERO_SEARCH 0
 #define HDLC_FLAG_SEARCH 1
@@ -211,7 +240,7 @@
 	switch (mode) {
 		case (L1_MODE_NULL):
 			fill_mem(bcs, bcs->hw.tiger.send,
-				NETJET_DMA_SIZE, bc, 0xff);
+				NETJET_DMA_TXSIZE, bc, 0xff);
 			if (cs->debug & L1_DEB_HSCX)
 				debugl1(cs, "Tiger stat rec %d/%d send %d",
 					bcs->hw.tiger.r_tot, bcs->hw.tiger.r_err,
@@ -228,7 +257,7 @@
 			break;
 		case (L1_MODE_HDLC): 
 			fill_mem(bcs, bcs->hw.tiger.send,
-				NETJET_DMA_SIZE, bc, 0xff);
+				NETJET_DMA_TXSIZE, bc, 0xff);
 			bcs->hw.tiger.r_state = HDLC_ZERO_SEARCH;
 			bcs->hw.tiger.r_tot = 0;
 			bcs->hw.tiger.r_bitcnt = 0;
@@ -237,14 +266,14 @@
 			bcs->hw.tiger.s_tot = 0;
 			if (! cs->hw.njet.dmactrl) {
 				fill_mem(bcs, bcs->hw.tiger.send,
-					NETJET_DMA_SIZE, !bc, 0xff);
+					NETJET_DMA_TXSIZE, !bc, 0xff);
 				cs->hw.njet.dmactrl = 1;
 				byteout(cs->hw.njet.base + NETJET_DMACTRL,
 					cs->hw.njet.dmactrl);
 				byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0x3f);
 			}
 			bcs->hw.tiger.sendp = bcs->hw.tiger.send;
-			bcs->hw.tiger.free = NETJET_DMA_SIZE;
+			bcs->hw.tiger.free = NETJET_DMA_TXSIZE;
 			test_and_set_bit(BC_FLG_EMPTY, &bcs->Flag);
 			break;
 	}
@@ -363,6 +392,7 @@
 			s_val |= 0x80;
 		}
 		bcs->hw.tiger.sendbuf[s_cnt++] = s_val;
+		bcs->hw.tiger.sendbuf[s_cnt++] = 0xff;	// NJ<->NJ thoughput bug fix
 	}
 	bcs->hw.tiger.sendcnt = s_cnt;
 	bcs->tx_cnt -= bcs->tx_skb->len;
@@ -376,6 +406,7 @@
 	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);
 	}
@@ -393,7 +424,7 @@
 	int i;
 	register u_char j;
 	register u_char val;
-	u_int  *pend = bcs->hw.tiger.rec +NETJET_DMA_SIZE -1;
+	u_int  *pend = bcs->hw.tiger.rec +NETJET_DMA_RXSIZE -1;
 	register u_char state = bcs->hw.tiger.r_state;
 	register u_char r_one = bcs->hw.tiger.r_one;
 	register u_char r_val = bcs->hw.tiger.r_val;
@@ -548,7 +579,7 @@
 
 static void read_tiger(struct IsdnCardState *cs) {
 	u_int *p;
-	int cnt = NETJET_DMA_SIZE/2;
+	int cnt = NETJET_DMA_RXSIZE/2;
 	
 	if ((cs->hw.njet.irqstat0 & cs->hw.njet.last_is0) & NETJET_IRQM0_READ) {
 		debugl1(cs,"tiger warn read double dma %x/%x",
@@ -559,7 +590,7 @@
 		cs->hw.njet.last_is0 |= (cs->hw.njet.irqstat0 & NETJET_IRQM0_READ);
 	}	
 	if (cs->hw.njet.irqstat0 & NETJET_IRQM0_READ_1)
-		p = cs->bcs[0].hw.tiger.rec + NETJET_DMA_SIZE - 1;
+		p = cs->bcs[0].hw.tiger.rec + NETJET_DMA_RXSIZE - 1;
 	else
 		p = cs->bcs[0].hw.tiger.rec + cnt - 1;
 	if (cs->bcs[0].mode == L1_MODE_HDLC)
@@ -616,12 +647,12 @@
 		cnt = bcs->hw.tiger.s_end - p;
 		if (cnt < 2) {
 			p = bcs->hw.tiger.send + 1;
-			cnt = NETJET_DMA_SIZE/2 - 2;
+			cnt = NETJET_DMA_TXSIZE/2 - 2;
 		} else {
 			p++;
 			p++;
-			if (cnt <= (NETJET_DMA_SIZE/2))
-				cnt += NETJET_DMA_SIZE/2;
+			if (cnt <= (NETJET_DMA_TXSIZE/2))
+				cnt += NETJET_DMA_TXSIZE/2;
 			cnt--;
 			cnt--;
 		}
@@ -674,12 +705,12 @@
 				if (bcs->st->lli.l1writewakeup &&
 					(PACKET_NOACK != bcs->tx_skb->pkt_type))
 					bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len);
-				dev_kfree_skb(bcs->tx_skb);
+				idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
 				bcs->tx_skb = NULL;
 			}
 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 			bcs->hw.tiger.free = cnt - s_cnt;
-			if (bcs->hw.tiger.free > (NETJET_DMA_SIZE/2))
+			if (bcs->hw.tiger.free > (NETJET_DMA_TXSIZE/2))
 				test_and_set_bit(BC_FLG_HALF, &bcs->Flag);
 			else {
 				test_and_clear_bit(BC_FLG_HALF, &bcs->Flag);
@@ -719,7 +750,7 @@
 }
 
 static void write_tiger(struct IsdnCardState *cs) {
-	u_int *p, cnt = NETJET_DMA_SIZE/2;
+	u_int *p, cnt = NETJET_DMA_TXSIZE/2;
 	
 	if ((cs->hw.njet.irqstat0 & cs->hw.njet.last_is0) & NETJET_IRQM0_WRITE) {
 		debugl1(cs,"tiger warn write double dma %x/%x",
@@ -730,7 +761,7 @@
 		cs->hw.njet.last_is0 |= (cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE);
 	}	
 	if (cs->hw.njet.irqstat0  & NETJET_IRQM0_WRITE_1)
-		p = cs->bcs[0].hw.tiger.send + NETJET_DMA_SIZE - 1;
+		p = cs->bcs[0].hw.tiger.send + NETJET_DMA_TXSIZE - 1;
 	else
 		p = cs->bcs[0].hw.tiger.send + cnt - 1;
 	if (cs->bcs[0].mode == L1_MODE_HDLC)
@@ -811,7 +842,7 @@
 		discard_queue(&bcs->rqueue);
 		discard_queue(&bcs->squeue);
 		if (bcs->tx_skb) {
-			dev_kfree_skb(bcs->tx_skb);
+			idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
 			bcs->tx_skb = NULL;
 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 		}
@@ -858,45 +889,45 @@
 }
 
  
-void __init 
-inittiger(struct IsdnCardState *cs)
+__initfunc(void
+inittiger(struct IsdnCardState *cs))
 {
-	if (!(cs->bcs[0].hw.tiger.send = kmalloc(NETJET_DMA_SIZE * sizeof(unsigned int),
+	if (!(cs->bcs[0].hw.tiger.send = kmalloc(NETJET_DMA_TXSIZE * sizeof(unsigned int),
 		GFP_KERNEL | GFP_DMA))) {
 		printk(KERN_WARNING
 		       "HiSax: No memory for tiger.send\n");
 		return;
 	}
-	cs->bcs[0].hw.tiger.s_irq = cs->bcs[0].hw.tiger.send + NETJET_DMA_SIZE/2 - 1;
-	cs->bcs[0].hw.tiger.s_end = cs->bcs[0].hw.tiger.send + NETJET_DMA_SIZE - 1;
+	cs->bcs[0].hw.tiger.s_irq = cs->bcs[0].hw.tiger.send + NETJET_DMA_TXSIZE/2 - 1;
+	cs->bcs[0].hw.tiger.s_end = cs->bcs[0].hw.tiger.send + NETJET_DMA_TXSIZE - 1;
 	cs->bcs[1].hw.tiger.send = cs->bcs[0].hw.tiger.send;
 	cs->bcs[1].hw.tiger.s_irq = cs->bcs[0].hw.tiger.s_irq;
 	cs->bcs[1].hw.tiger.s_end = cs->bcs[0].hw.tiger.s_end;
 	
-	memset(cs->bcs[0].hw.tiger.send, 0xff, NETJET_DMA_SIZE * sizeof(unsigned int));
+	memset(cs->bcs[0].hw.tiger.send, 0xff, NETJET_DMA_TXSIZE * sizeof(unsigned int));
 	debugl1(cs, "tiger: send buf %x - %x", (u_int)cs->bcs[0].hw.tiger.send,
-		(u_int)(cs->bcs[0].hw.tiger.send + NETJET_DMA_SIZE - 1));
+		(u_int)(cs->bcs[0].hw.tiger.send + NETJET_DMA_TXSIZE - 1));
 	outl(virt_to_bus(cs->bcs[0].hw.tiger.send),
 		cs->hw.njet.base + NETJET_DMA_READ_START);
 	outl(virt_to_bus(cs->bcs[0].hw.tiger.s_irq),
 		cs->hw.njet.base + NETJET_DMA_READ_IRQ);
 	outl(virt_to_bus(cs->bcs[0].hw.tiger.s_end),
 		cs->hw.njet.base + NETJET_DMA_READ_END);
-	if (!(cs->bcs[0].hw.tiger.rec = kmalloc(NETJET_DMA_SIZE * sizeof(unsigned int),
+	if (!(cs->bcs[0].hw.tiger.rec = kmalloc(NETJET_DMA_RXSIZE * sizeof(unsigned int),
 		GFP_KERNEL | GFP_DMA))) {
 		printk(KERN_WARNING
 		       "HiSax: No memory for tiger.rec\n");
 		return;
 	}
 	debugl1(cs, "tiger: rec buf %x - %x", (u_int)cs->bcs[0].hw.tiger.rec,
-		(u_int)(cs->bcs[0].hw.tiger.rec + NETJET_DMA_SIZE - 1));
+		(u_int)(cs->bcs[0].hw.tiger.rec + NETJET_DMA_RXSIZE - 1));
 	cs->bcs[1].hw.tiger.rec = cs->bcs[0].hw.tiger.rec;
-	memset(cs->bcs[0].hw.tiger.rec, 0xff, NETJET_DMA_SIZE * sizeof(unsigned int));
+	memset(cs->bcs[0].hw.tiger.rec, 0xff, NETJET_DMA_RXSIZE * sizeof(unsigned int));
 	outl(virt_to_bus(cs->bcs[0].hw.tiger.rec),
 		cs->hw.njet.base + NETJET_DMA_WRITE_START);
-	outl(virt_to_bus(cs->bcs[0].hw.tiger.rec + NETJET_DMA_SIZE/2 - 1),
+	outl(virt_to_bus(cs->bcs[0].hw.tiger.rec + NETJET_DMA_RXSIZE/2 - 1),
 		cs->hw.njet.base + NETJET_DMA_WRITE_IRQ);
-	outl(virt_to_bus(cs->bcs[0].hw.tiger.rec + NETJET_DMA_SIZE - 1),
+	outl(virt_to_bus(cs->bcs[0].hw.tiger.rec + NETJET_DMA_RXSIZE - 1),
 		cs->hw.njet.base + NETJET_DMA_WRITE_END);
 	debugl1(cs, "tiger: dmacfg  %x/%x  pulse=%d",
 		inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR),
@@ -1030,9 +1061,6 @@
 		case CARD_RELEASE:
 			release_io_netjet(cs);
 			return(0);
-		case CARD_SETIRQ:
-			return(request_irq(cs->irq, &netjet_interrupt,
-					I4L_IRQ_FLAG | SA_SHIRQ, "HiSax", cs));
 		case CARD_INIT:
 			inittiger(cs);
 			clear_pending_isac_ints(cs);
@@ -1046,23 +1074,31 @@
 	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));
 	if (cs->typ != ISDN_CTYPE_NETJET)
 		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);
@@ -1071,22 +1107,57 @@
 		PCI_NETJET_ID,  dev_netjet))) {
 		cs->irq = dev_netjet->irq;
 		if (!cs->irq) {
+			printk(KERN_WARNING "NETjet: No IRQ for PCI card found\n");
+			return(0);
+		}
+		cs->hw.njet.base = get_pcibase(dev_netjet, 0)
+			& PCI_BASE_ADDRESS_IO_MASK; 
+		if (!cs->hw.njet.base) {
+			printk(KERN_WARNING "NETjet: No IO-Adr for PCI card found\n");
+			return(0);
+		}
+	} else {
+		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);
 	}
-		cs->hw.njet.base = dev_netjet->resource[0].start &
-			PCI_BASE_ADDRESS_IO_MASK; 
-		if (!cs->hw.njet.base) {
+	if (!pci_ioaddr) {
 		printk(KERN_WARNING "NETjet: No IO-Adr for PCI card found\n");
 		return(0);
 	}
-		cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
-		cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
+	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;
-	} else {
-		printk(KERN_WARNING "NETjet: No PCI card found\n");
-		return(0);
-	}
 #else
 	printk(KERN_WARNING "NETjet: NO_PCI_BIOS\n");
 	printk(KERN_WARNING "NETjet: unable to config NETJET PCI\n");
@@ -1114,6 +1185,8 @@
 	cs->BC_Write_Reg = &dummywr;
 	cs->BC_Send_Data = &fill_dma;
 	cs->cardmsg = &NETjet_card_msg;
+	cs->irq_func = &netjet_interrupt;
+	cs->irq_flags |= SA_SHIRQ;
 	ISACVersion(cs, "NETjet:");
 	return (1);
 }
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/niccy.c linux/drivers/isdn/hisax/niccy.c
--- v2.3.13/linux/drivers/isdn/hisax/niccy.c	Mon Aug  9 14:59:20 1999
+++ linux/drivers/isdn/hisax/niccy.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: niccy.c,v 1.4 1998/04/16 19:16:48 keil Exp $
+/* $Id: niccy.c,v 1.8 1999/08/11 21:01:33 keil Exp $
 
  * niccy.c  low level stuff for Dr. Neuhaus NICCY PnP and NICCY PCI and
  *          compatible (SAGEM cybermodem)
@@ -8,6 +8,19 @@
  * Thanks to Dr. Neuhaus and SAGEM for informations
  *
  * $Log: niccy.c,v $
+ * Revision 1.8  1999/08/11 21:01:33  keil
+ * new PCI codefix
+ *
+ * Revision 1.7  1999/08/10 16:02:04  calle
+ * struct pci_dev changed in 2.3.13. Made the necessary changes.
+ *
+ * Revision 1.6  1999/07/12 21:05:23  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 1.5  1999/07/01 08:12:07  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 1.4  1998/04/16 19:16:48  keil
  * need config.h
  *
@@ -27,9 +40,12 @@
 #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.4 $";
+const char *niccy_revision = "$Revision: 1.8 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -154,7 +170,7 @@
 niccy_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u_char val, stat = 0;
+	u_char val;
 
 	if (!cs) {
 		printk(KERN_WARNING "Niccy: Spurious interrupt!\n");
@@ -169,16 +185,12 @@
 	}
 	val = readreg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_ISTA + 0x40);
       Start_HSCX:
-	if (val) {
+	if (val)
 		hscx_int_main(cs, val);
-		stat |= 1;
-	}
 	val = readreg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_ISTA);
       Start_ISAC:
-	if (val) {
+	if (val)
 		isac_interrupt(cs, val);
-		stat |= 2;
-	}
 	val = readreg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_ISTA + 0x40);
 	if (val) {
 		if (cs->debug & L1_DEB_HSCX)
@@ -191,16 +203,12 @@
 			debugl1(cs, "ISAC IntStat after IntRoutine");
 		goto Start_ISAC;
 	}
-	if (stat & 1) {
-		writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK, 0xFF);
-		writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK + 0x40, 0xFF);
-		writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK, 0);
-		writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK + 0x40, 0);
-	}
-	if (stat & 2) {
-		writereg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_MASK, 0xFF);
-		writereg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_MASK, 0);
-	}
+	writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK, 0xFF);
+	writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK + 0x40, 0xFF);
+	writereg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_MASK, 0);
+	writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK, 0);
+	writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK + 0x40, 0);
 }
 
 void
@@ -235,8 +243,6 @@
 static int
 niccy_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
-	int imode;
-	
 	switch (mt) {
 		case CARD_RESET:
 			niccy_reset(cs);
@@ -244,14 +250,6 @@
 		case CARD_RELEASE:
 			release_io_niccy(cs);
 			return(0);
-		case CARD_SETIRQ:
-			if (cs->subtyp == NICCY_PCI)
-				imode = I4L_IRQ_FLAG | SA_SHIRQ;
-			else
-				imode = I4L_IRQ_FLAG;
-			return(request_irq(cs->irq, &niccy_interrupt,
-				imode, "HiSax", cs));
-			break;
 		case CARD_INIT:
 			niccy_reset(cs);
 			return(0);
@@ -261,10 +259,14 @@
 	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];
@@ -304,40 +306,85 @@
 	} 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);
 		}
-
 		cs->subtyp = 0;
 		if ((niccy_dev = pci_find_device(PCI_VENDOR_DR_NEUHAUS,
 			   PCI_NICCY_ID, niccy_dev))) {
 			/* get IRQ */
 			if (!niccy_dev->irq) {
 				printk(KERN_WARNING "Niccy: No IRQ for PCI card found\n");
+				return(0);
+			}
+			cs->irq = niccy_dev->irq;
+			if (!get_pcibase(niccy_dev, 0)) {
+				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)) {
+				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;
+			cs->subtyp = NICCY_PCI;
+		} else {
+			printk(KERN_WARNING "Niccy: No PCI card found\n");
 			return(0);
 		}
-			cs->irq = niccy_dev->irq;
-			if (!niccy_dev->resource[0].start) {
+#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);
 		}
-			cs->hw.niccy.cfg_reg = niccy_dev->resource[0].start & PCI_BASE_ADDRESS_IO_MASK;
-			if (!niccy_dev->resource[1].start) {
+		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 = niccy_dev->resource[1].start & PCI_BASE_ADDRESS_IO_MASK;
+		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;
 		cs->hw.niccy.hscx = pci_ioaddr + HSCX_PCI_DATA;
 		cs->hw.niccy.hscx_ale = pci_ioaddr + HSCX_PCI_ADDR;
-			cs->subtyp = NICCY_PCI;
-		} else {
-			printk(KERN_WARNING "Niccy: No PCI card found\n");
-			return(0);
-		}
 		if (check_region((cs->hw.niccy.isac), 4)) {
 			printk(KERN_WARNING
 				"HiSax: %s data port %x-%x already in use\n",
@@ -376,6 +423,7 @@
 	cs->BC_Write_Reg = &WriteHSCX;
 	cs->BC_Send_Data = &hscx_fill_fifo;
 	cs->cardmsg = &niccy_card_msg;
+	cs->irq_func = &niccy_interrupt;
 	ISACVersion(cs, "Niccy:");
 	if (HscxVersion(cs, "Niccy:")) {
 		printk(KERN_WARNING
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/s0box.c linux/drivers/isdn/hisax/s0box.c
--- v2.3.13/linux/drivers/isdn/hisax/s0box.c	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/hisax/s0box.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: s0box.c,v 2.1 1998/04/15 16:38:24 keil Exp $
+/* $Id: s0box.c,v 2.2 1999/07/12 21:05:25 keil Exp $
 
  * s0box.c      low level stuff for Creatix S0BOX
  *
@@ -13,7 +13,7 @@
 #include "isdnl1.h"
 
 extern const char *CardType[];
-const char *s0box_revision = "$Revision: 2.1 $";
+const char *s0box_revision = "$Revision: 2.2 $";
 
 static inline void
 writereg(unsigned int padr, signed int addr, u_char off, u_char val) {
@@ -148,9 +148,9 @@
 static void
 s0box_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
-#define MAXCOUNT 20
+#define MAXCOUNT 5
 	struct IsdnCardState *cs = dev_id;
-	u_char val, stat = 0;
+	u_char val;
 	int count = 0;
 
 	if (!cs) {
@@ -159,16 +159,12 @@
 	}
 	val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_ISTA);
       Start_HSCX:
-	if (val) {
+	if (val)
 		hscx_int_main(cs, val);
-		stat |= 1;
-	}
 	val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_ISTA);
       Start_ISAC:
-	if (val) {
+	if (val)
 		isac_interrupt(cs, val);
-		stat |= 2;
-	}
 	count++;
 	val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_ISTA);
 	if (val && count < MAXCOUNT) {
@@ -184,16 +180,12 @@
 	}
 	if (count >= MAXCOUNT)
 		printk(KERN_WARNING "S0Box: more than %d loops in s0box_interrupt\n", count);
-	if (stat & 1) {
-		writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[0], HSCX_MASK, 0xFF);
-		writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_MASK, 0xFF);
-		writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[0], HSCX_MASK, 0x0);
-		writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_MASK, 0x0);
-	}
-	if (stat & 2) {
-		writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_MASK, 0xFF);
-		writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_MASK, 0x0);
-	}
+	writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[0], HSCX_MASK, 0xFF);
+	writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_MASK, 0xFF);
+	writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_MASK, 0x0);
+	writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[0], HSCX_MASK, 0x0);
+	writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_MASK, 0x0);
 }
 
 void
@@ -211,9 +203,6 @@
 		case CARD_RELEASE:
 			release_io_s0box(cs);
 			break;
-		case CARD_SETIRQ:
-			return(request_irq(cs->irq, &s0box_interrupt,
-					I4L_IRQ_FLAG, "HiSax", cs));
 		case CARD_INIT:
 			inithscxisac(cs, 3);
 			break;
@@ -266,6 +255,7 @@
 	cs->BC_Write_Reg = &WriteHSCX;
 	cs->BC_Send_Data = &hscx_fill_fifo;
 	cs->cardmsg = &S0Box_card_msg;
+	cs->irq_func = &s0box_interrupt;
 	ISACVersion(cs, "S0Box:");
 	if (HscxVersion(cs, "S0Box:")) {
 		printk(KERN_WARNING
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/saphir.c linux/drivers/isdn/hisax/saphir.c
--- v2.3.13/linux/drivers/isdn/hisax/saphir.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/hisax/saphir.c	Thu Aug 12 09:42:33 1999
@@ -0,0 +1,326 @@
+/* $Id: saphir.c,v 1.3 1999/07/12 21:05:26 keil Exp $
+
+ * saphir.c low level stuff for HST Saphir 1
+ *
+ * Author     Karsten Keil (keil@isdn4linux.de)
+ *
+ * Thanks to    HST High Soft Tech GmbH
+ *
+ *
+ * $Log: saphir.c,v $
+ * Revision 1.3  1999/07/12 21:05:26  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 1.2  1999/07/01 08:07:55  keil
+ * Initial version
+ *
+ *
+ */
+
+
+#define __NO_VERSION__
+#include "hisax.h"
+#include "isac.h"
+#include "hscx.h"
+#include "isdnl1.h"
+
+extern const char *CardType[];
+static char *saphir_rev = "$Revision: 1.3 $";
+
+#define byteout(addr,val) outb(val,addr)
+#define bytein(addr) inb(addr)
+
+#define ISAC_DATA	0
+#define HSCX_DATA	1
+#define ADDRESS_REG	2
+#define IRQ_REG		3
+#define SPARE_REG	4
+#define RESET_REG	5
+
+static inline u_char
+readreg(unsigned int ale, unsigned int adr, u_char off)
+{
+	register u_char ret;
+	long flags;
+
+	save_flags(flags);
+	cli();
+	byteout(ale, off);
+	ret = bytein(adr);
+	restore_flags(flags);
+	return (ret);
+}
+
+static inline void
+readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
+{
+	/* fifo read without cli because it's allready done  */
+
+	byteout(ale, off);
+	insb(adr, data, size);
+}
+
+
+static inline void
+writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
+{
+	long flags;
+
+	save_flags(flags);
+	cli();
+	byteout(ale, off);
+	byteout(adr, data);
+	restore_flags(flags);
+}
+
+static inline void
+writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
+{
+	/* fifo write without cli because it's allready done  */
+	byteout(ale, off);
+	outsb(adr, data, size);
+}
+
+/* Interface functions */
+
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
+{
+	return (readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, offset));
+}
+
+static void
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+	writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, offset, value);
+}
+
+static void
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	readfifo(cs->hw.saphir.ale, cs->hw.saphir.isac, 0, data, size);
+}
+
+static void
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	writefifo(cs->hw.saphir.ale, cs->hw.saphir.isac, 0, data, size);
+}
+
+static u_char
+ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
+{
+	return (readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx,
+		offset + (hscx ? 0x40 : 0)));
+}
+
+static void
+WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
+{
+	writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx,
+		offset + (hscx ? 0x40 : 0), value);
+}
+
+#define READHSCX(cs, nr, reg) readreg(cs->hw.saphir.ale, \
+		cs->hw.saphir.hscx, reg + (nr ? 0x40 : 0))
+#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.saphir.ale, \
+		cs->hw.saphir.hscx, reg + (nr ? 0x40 : 0), data)
+
+#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.saphir.ale, \
+		cs->hw.saphir.hscx, (nr ? 0x40 : 0), ptr, cnt)
+
+#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.saphir.ale, \
+		cs->hw.saphir.hscx, (nr ? 0x40 : 0), ptr, cnt)
+
+#include "hscx_irq.c"
+
+static void
+saphir_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char val;
+
+	if (!cs) {
+		printk(KERN_WARNING "saphir: Spurious interrupt!\n");
+		return;
+	}
+	val = readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_ISTA + 0x40);
+      Start_HSCX:
+	if (val)
+		hscx_int_main(cs, val);
+	val = readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_ISTA);
+      Start_ISAC:
+	if (val)
+		isac_interrupt(cs, val);
+	val = readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_ISTA + 0x40);
+	if (val) {
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX IntStat after IntRoutine");
+		goto Start_HSCX;
+	}
+	val = readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_ISTA);
+	if (val) {
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "ISAC IntStat after IntRoutine");
+		goto Start_ISAC;
+	}
+	/* Watchdog */
+	if (cs->hw.saphir.timer.function) {
+		del_timer(&cs->hw.saphir.timer);
+		cs->hw.saphir.timer.expires = jiffies + 1*HZ;
+		add_timer(&cs->hw.saphir.timer);
+	} else
+		printk(KERN_WARNING "saphir: Spurious timer!\n");
+	writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK, 0xFF);
+	writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK + 0x40, 0xFF);
+	writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_MASK, 0);
+	writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK, 0);
+	writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK + 0x40, 0);
+}
+
+static void
+SaphirWatchDog(struct IsdnCardState *cs)
+{
+        /* 5 sec WatchDog, so read at least every 4 sec */
+	cs->readisac(cs, ISAC_RBCH);
+	del_timer(&cs->hw.saphir.timer);
+	cs->hw.saphir.timer.expires = jiffies + 1*HZ;
+	add_timer(&cs->hw.saphir.timer);
+}
+
+void
+release_io_saphir(struct IsdnCardState *cs)
+{
+	long flags;
+	
+	save_flags(flags);
+	cli();
+	byteout(cs->hw.saphir.cfg_reg + IRQ_REG, 0xff);
+	del_timer(&cs->hw.saphir.timer);
+	cs->hw.saphir.timer.function = NULL;
+	restore_flags(flags);
+	if (cs->hw.saphir.cfg_reg)
+		release_region(cs->hw.saphir.cfg_reg, 6);
+}
+
+static int
+saphir_reset(struct IsdnCardState *cs)
+{
+	long flags;
+	u_char irq_val;
+
+	switch(cs->irq) {
+		case 5: irq_val = 0;
+			break;
+		case 3: irq_val = 1;
+			break;
+		case 11:
+			irq_val = 2;
+			break;
+		case 12:
+			irq_val = 3;
+			break;
+		case 15:
+			irq_val = 4;
+			break;
+		default:
+			printk(KERN_WARNING "HiSax: saphir wrong IRQ %d\n",
+				cs->irq);
+			return (1);
+	}
+	byteout(cs->hw.saphir.cfg_reg + IRQ_REG, irq_val);
+	save_flags(flags);
+	sti();
+	byteout(cs->hw.saphir.cfg_reg + RESET_REG, 1);
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout((30*HZ)/1000);	/* Timeout 30ms */
+	byteout(cs->hw.saphir.cfg_reg + RESET_REG, 0);
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout((30*HZ)/1000);	/* Timeout 30ms */
+	restore_flags(flags);
+	byteout(cs->hw.saphir.cfg_reg + IRQ_REG, irq_val);
+	byteout(cs->hw.saphir.cfg_reg + SPARE_REG, 0x02);
+	return (0);
+}
+
+static int
+saphir_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+	switch (mt) {
+		case CARD_RESET:
+			saphir_reset(cs);
+			return(0);
+		case CARD_RELEASE:
+			release_io_saphir(cs);
+			return(0);
+		case CARD_INIT:
+			inithscxisac(cs, 3);
+			return(0);
+		case CARD_TEST:
+			return(0);
+	}
+	return(0);
+}
+
+
+__initfunc(int
+setup_saphir(struct IsdnCard *card))
+{
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+
+	strcpy(tmp, saphir_rev);
+	printk(KERN_INFO "HiSax: HST Saphir driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ != ISDN_CTYPE_HSTSAPHIR)
+		return (0);
+
+	/* IO-Ports */
+	cs->hw.saphir.cfg_reg = card->para[1];
+	cs->hw.saphir.isac = card->para[1] + ISAC_DATA;
+	cs->hw.saphir.hscx = card->para[1] + HSCX_DATA;
+	cs->hw.saphir.ale = card->para[1] + ADDRESS_REG;
+	cs->irq = card->para[0];
+	if (check_region((cs->hw.saphir.cfg_reg), 6)) {
+		printk(KERN_WARNING
+			"HiSax: %s config port %x-%x already in use\n",
+			CardType[card->typ],
+			cs->hw.saphir.cfg_reg,
+			cs->hw.saphir.cfg_reg + 5);
+		return (0);
+	} else
+		request_region(cs->hw.saphir.cfg_reg,6, "saphir");
+
+	printk(KERN_INFO
+	       "HiSax: %s config irq:%d io:0x%X\n",
+	       CardType[cs->typ], cs->irq,
+	       cs->hw.saphir.cfg_reg);
+
+	cs->hw.saphir.timer.function = (void *) SaphirWatchDog;
+	cs->hw.saphir.timer.data = (long) cs;
+	init_timer(&cs->hw.saphir.timer);
+	cs->hw.saphir.timer.expires = jiffies + 4*HZ;
+	add_timer(&cs->hw.saphir.timer);
+	if (saphir_reset(cs)) {
+		release_io_saphir(cs);
+		return (0);
+	}
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->BC_Read_Reg = &ReadHSCX;
+	cs->BC_Write_Reg = &WriteHSCX;
+	cs->BC_Send_Data = &hscx_fill_fifo;
+	cs->cardmsg = &saphir_card_msg;
+	cs->irq_func = &saphir_interrupt;
+	ISACVersion(cs, "saphir:");
+	if (HscxVersion(cs, "saphir:")) {
+		printk(KERN_WARNING
+		    "saphir: wrong HSCX versions check IO address\n");
+		release_io_saphir(cs);
+		return (0);
+	}
+	return (1);
+}
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/sedlbauer.c linux/drivers/isdn/hisax/sedlbauer.c
--- v2.3.13/linux/drivers/isdn/hisax/sedlbauer.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/isdn/hisax/sedlbauer.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: sedlbauer.c,v 1.9 1998/11/15 23:55:20 keil Exp $
+/* $Id: sedlbauer.c,v 1.14 1999/08/11 20:59:22 keil Exp $
 
  * sedlbauer.c  low level stuff for Sedlbauer cards
  *              includes support for the Sedlbauer speed star (speed star II),
@@ -17,6 +17,23 @@
  *            Edgar Toernig
  *
  * $Log: sedlbauer.c,v $
+ * Revision 1.14  1999/08/11 20:59:22  keil
+ * new PCI codefix
+ * fix IRQ problem while unload
+ *
+ * Revision 1.13  1999/08/10 16:02:08  calle
+ * struct pci_dev changed in 2.3.13. Made the necessary changes.
+ *
+ * Revision 1.12  1999/08/05 20:43:22  keil
+ * ISAR analog modem support
+ *
+ * Revision 1.11  1999/07/12 21:05:27  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 1.10  1999/07/01 08:12:09  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 1.9  1998/11/15 23:55:20  keil
  * changes from 2.0
  *
@@ -76,10 +93,13 @@
 #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.9 $";
+const char *Sedlbauer_revision = "$Revision: 1.14 $";
 
 const char *Sedlbauer_Types[] =
 	{"None", "speed card/win", "speed star", "speed fax+", 
@@ -291,7 +311,7 @@
 sedlbauer_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u_char val, stat = 0;
+	u_char val;
 
 	if (!cs) {
 		printk(KERN_WARNING "Sedlbauer: Spurious interrupt!\n");
@@ -307,16 +327,12 @@
 
 	val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_ISTA + 0x40);
       Start_HSCX:
-	if (val) {
+	if (val)
 		hscx_int_main(cs, val);
-		stat |= 1;
-	}
 	val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA);
       Start_ISAC:
-	if (val) {
+	if (val)
 		isac_interrupt(cs, val);
-		stat |= 2;
-	}
 	val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_ISTA + 0x40);
 	if (val) {
 		if (cs->debug & L1_DEB_HSCX)
@@ -329,23 +345,19 @@
 			debugl1(cs, "ISAC IntStat after IntRoutine");
 		goto Start_ISAC;
 	}
-	if (stat & 1) {
-		writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK, 0xFF);
-		writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK + 0x40, 0xFF);
-		writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK, 0x0);
-		writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK + 0x40, 0x0);
-	}
-	if (stat & 2) {
-		writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0xFF);
-		writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0x0);
-	}
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK, 0xFF);
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK + 0x40, 0xFF);
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0x0);
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK, 0x0);
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK + 0x40, 0x0);
 }
 
 static void
 sedlbauer_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u_char ista, val, icnt = 20;
+	u_char ista, val, icnt = 5;
 
 	if (!cs) {
 		printk(KERN_WARNING "Sedlbauer: Spurious interrupt!\n");
@@ -392,7 +404,7 @@
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char val;
-	int cnt = 20;
+	int cnt = 5;
 
 	if (!cs) {
 		printk(KERN_WARNING "Sedlbauer: Spurious interrupt!\n");
@@ -431,9 +443,11 @@
 void
 release_io_sedlbauer(struct IsdnCardState *cs)
 {
-	int bytecnt = (cs->subtyp == SEDL_SPEED_FAX) ? 16 : 8;
+	int bytecnt = 8;
 
-	if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
+	if (cs->subtyp == SEDL_SPEED_FAX) {
+		bytecnt = 16;
+	} else if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
 		bytecnt = 256;
 	}
 	if (cs->hw.sedl.cfg_reg)
@@ -454,10 +468,10 @@
 			save_flags(flags);
 			sti();
 			current->state = TASK_INTERRUPTIBLE;
-			schedule_timeout(1);
+			schedule_timeout((10*HZ)/1000);
 			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x0);
 			current->state = TASK_INTERRUPTIBLE;
-			schedule_timeout(1);
+			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);
 			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_AOE, 0x0);
@@ -469,10 +483,10 @@
 			save_flags(flags);
 			sti();
 			current->state = TASK_INTERRUPTIBLE;
-			schedule_timeout(1);
+			schedule_timeout((10*HZ)/1000);
 			byteout(cs->hw.sedl.reset_off, 0);	/* Reset Off */
 			current->state = TASK_INTERRUPTIBLE;
-			schedule_timeout(1);
+			schedule_timeout((10*HZ)/1000);
 			restore_flags(flags);
 		}
 	}
@@ -486,19 +500,19 @@
 			reset_sedlbauer(cs);
 			return(0);
 		case CARD_RELEASE:
-			release_io_sedlbauer(cs);
-			return(0);
-		case CARD_SETIRQ:
 			if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
-				return(request_irq(cs->irq, &sedlbauer_interrupt_isar,
-					I4L_IRQ_FLAG, "HiSax", cs));
-			} else if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) {
-				return(request_irq(cs->irq, &sedlbauer_interrupt_ipac,
-					I4L_IRQ_FLAG, "HiSax", cs));
-			} else {
-				return(request_irq(cs->irq, &sedlbauer_interrupt,
-					I4L_IRQ_FLAG, "HiSax", cs));
+				writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx,
+					ISAR_IRQBIT, 0);
+				writereg(cs->hw.sedl.adr, cs->hw.sedl.isac,
+					ISAC_MASK, 0xFF);
+				reset_sedlbauer(cs);
+				writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx,
+					ISAR_IRQBIT, 0);
+				writereg(cs->hw.sedl.adr, cs->hw.sedl.isac,
+					ISAC_MASK, 0xFF);
 			}
+			release_io_sedlbauer(cs);
+			return(0);
 		case CARD_INIT:
 			if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
 				clear_pending_isac_ints(cs);
@@ -530,11 +544,15 @@
 
 
 #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;
@@ -569,6 +587,25 @@
 /* Probe for Sedlbauer speed pci */
 #if SEDLBAUER_PCI
 #if CONFIG_PCI
+#ifdef COMPAT_HAS_NEW_PCI
+		if (!pci_present()) {
+			printk(KERN_ERR "FritzPCI: no PCI bus present\n");
+			return(0);
+		}
+		if ((dev_sedl = pci_find_device(PCI_VENDOR_SEDLBAUER,
+				PCI_SPEEDPCI_ID, dev_sedl))) {
+			cs->irq = dev_sedl->irq;
+			if (!cs->irq) {
+				printk(KERN_WARNING "Sedlbauer: No IRQ for PCI card found\n");
+				return(0);
+			}
+			cs->hw.sedl.cfg_reg = get_pcibase(dev_sedl, 0) &
+				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;
@@ -589,14 +626,6 @@
 				printk(KERN_WARNING "Sedlbauer: No IO-Adr for PCI card found\n");
 				return(0);
 			}
-			cs->hw.sedl.bus = SEDL_BUS_PCI;
-			cs->hw.sedl.chip = SEDL_CHIP_IPAC;
-			cs->subtyp = SEDL_SPEED_PCI;
-			bytecnt = 256;
-			byteout(cs->hw.sedl.cfg_reg, 0xff);
-			byteout(cs->hw.sedl.cfg_reg, 0x00);
-			byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd);
-			byteout(cs->hw.sedl.cfg_reg+ 5, 0x02);
 			break;
 		}	
 		if (pci_index == 255) {
@@ -604,6 +633,16 @@
 			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;
+		cs->subtyp = SEDL_SPEED_PCI;
+		bytecnt = 256;
+		byteout(cs->hw.sedl.cfg_reg, 0xff);
+		byteout(cs->hw.sedl.cfg_reg, 0x00);
+		byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd);
+		byteout(cs->hw.sedl.cfg_reg+ 5, 0x02);
 #else
 		printk(KERN_WARNING "Sedlbauer: NO_PCI_BIOS\n");
 		return (0);
@@ -683,6 +722,7 @@
                 cs->writeisac = &WriteISAC_IPAC;
                 cs->readisacfifo = &ReadISACfifo_IPAC;
                 cs->writeisacfifo = &WriteISACfifo_IPAC;
+                cs->irq_func = &sedlbauer_interrupt_ipac;
 
 		val = readreg(cs->hw.sedl.adr,cs->hw.sedl.isac, IPAC_ID);
                 printk(KERN_INFO "Sedlbauer: IPAC version %x\n", val);
@@ -702,6 +742,7 @@
 			cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar;
 			cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar;
 			test_and_set_bit(HW_ISAR, &cs->HW_Flags);
+			cs->irq_func = &sedlbauer_interrupt_isar;
 	
 			ISACVersion(cs, "Sedlbauer:");
 		
@@ -729,6 +770,7 @@
 				cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON;
 				cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF;
 			}
+			cs->irq_func = &sedlbauer_interrupt;
 			ISACVersion(cs, "Sedlbauer:");
 		
 			if (HscxVersion(cs, "Sedlbauer:")) {
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/sportster.c linux/drivers/isdn/hisax/sportster.c
--- v2.3.13/linux/drivers/isdn/hisax/sportster.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/isdn/hisax/sportster.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: sportster.c,v 1.7 1998/11/15 23:55:22 keil Exp $
+/* $Id: sportster.c,v 1.9 1999/07/12 21:05:29 keil Exp $
 
  * sportster.c     low level stuff for USR Sportster internal TA
  *
@@ -7,6 +7,13 @@
  * Thanks to Christian "naddy" Weisgerber (3Com, US Robotics) for documentation
  *
  * $Log: sportster.c,v $
+ * Revision 1.9  1999/07/12 21:05:29  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 1.8  1999/07/01 08:12:10  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 1.7  1998/11/15 23:55:22  keil
  * changes from 2.0
  *
@@ -36,7 +43,7 @@
 #include "isdnl1.h"
 
 extern const char *CardType[];
-const char *sportster_revision = "$Revision: 1.7 $";
+const char *sportster_revision = "$Revision: 1.9 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -171,11 +178,11 @@
 	save_flags(flags);
 	sti();
 	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(1);
+	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;
-	schedule_timeout(1);
+	schedule_timeout((10*HZ)/1000);
 	restore_flags(flags);
 }
 
@@ -189,9 +196,6 @@
 		case CARD_RELEASE:
 			release_io_sportster(cs);
 			return(0);
-		case CARD_SETIRQ:
-			return(request_irq(cs->irq, &sportster_interrupt,
-					I4L_IRQ_FLAG, "HiSax", cs));
 		case CARD_INIT:
 			inithscxisac(cs, 1);
 			cs->hw.spt.res_irq |= SPORTSTER_INTE; /* IRQ On */
@@ -204,8 +208,8 @@
 	return(0);
 }
 
-int __init 
-get_io_range(struct IsdnCardState *cs)
+__initfunc(int
+get_io_range(struct IsdnCardState *cs))
 {
 	int i, j, adr;
 	
@@ -230,8 +234,8 @@
 	}
 }
 
-int __init 
-setup_sportster(struct IsdnCard *card)
+__initfunc(int
+setup_sportster(struct IsdnCard *card))
 {
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
@@ -282,6 +286,7 @@
 	cs->BC_Write_Reg = &WriteHSCX;
 	cs->BC_Send_Data = &hscx_fill_fifo;
 	cs->cardmsg = &Sportster_card_msg;
+	cs->irq_func = &sportster_interrupt;
 	ISACVersion(cs, "Sportster:");
 	if (HscxVersion(cs, "Sportster:")) {
 		printk(KERN_WARNING
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/tei.c linux/drivers/isdn/hisax/tei.c
--- v2.3.13/linux/drivers/isdn/hisax/tei.c	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/hisax/tei.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: tei.c,v 2.11 1998/11/15 23:55:24 keil Exp $
+/* $Id: tei.c,v 2.13 1999/07/21 14:46:28 keil Exp $
 
  * Author       Karsten Keil (keil@isdn4linux.de)
  *              based on the teles driver from Jan den Ouden
@@ -11,6 +11,12 @@
  *              Fritz Elfert
  *
  * $Log: tei.c,v $
+ * Revision 2.13  1999/07/21 14:46:28  keil
+ * changes from EICON certification
+ *
+ * Revision 2.12  1999/07/01 08:12:11  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 2.11  1998/11/15 23:55:24  keil
  * changes from 2.0
  *
@@ -72,7 +78,7 @@
 #include "isdnl2.h"
 #include <linux/random.h>
 
-const char *tei_revision = "$Revision: 2.11 $";
+const char *tei_revision = "$Revision: 2.13 $";
 
 #define ID_REQUEST	1
 #define ID_ASSIGNED	2
@@ -163,6 +169,7 @@
 		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;
@@ -226,6 +233,25 @@
 }
 
 static void
+tei_id_test_dup(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *ost, *st = fi->userdata;
+	struct sk_buff *skb = arg;
+	int tei, ri;
+
+	ri = ((unsigned int) skb->data[1] << 8) + skb->data[2];
+	tei = skb->data[4] >> 1;
+	if (st->ma.debug)
+		st->ma.tei_m.printdebug(&st->ma.tei_m,
+			"foreign identity assign ri %d tei %d", ri, tei);
+	if ((ost = findtei(st, tei))) {		/* same tei is in use */
+		st->ma.tei_m.printdebug(&st->ma.tei_m,
+			"possible duplicate assignment tei %d", tei);
+		FsmEvent(&ost->ma.tei_m, EV_VERIFY, NULL);
+	} 
+}
+
+static void
 tei_id_denied(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
@@ -345,7 +371,7 @@
 	int mt;
 
 	if (test_bit(FLG_FIXED_TEI, &st->l2.flag)) {
-		dev_kfree_skb(skb);
+		idev_kfree_skb(skb, FREE_READ);
 		return;
 	}
 
@@ -353,8 +379,8 @@
 		if (skb->len < 3) {
 			st->ma.tei_m.printdebug(&st->ma.tei_m,
 				"short mgr frame %ld/3", skb->len);
-		} else if (((skb->data[0] >> 2) != TEI_SAPI) ||
-			   ((skb->data[1] >> 1) != GROUP_TEI)) {
+		} else if ((skb->data[0] != ((TEI_SAPI << 2) | 2)) ||
+			   (skb->data[1] != ((GROUP_TEI << 1) | 1))) {
 			st->ma.tei_m.printdebug(&st->ma.tei_m,
 				"wrong mgr sapi/tei %x/%x",
 				skb->data[0], skb->data[1]);
@@ -391,7 +417,7 @@
 		st->ma.tei_m.printdebug(&st->ma.tei_m,
 			"tei handler wrong pr %x\n", pr);
 	}
-	dev_kfree_skb(skb);
+	idev_kfree_skb(skb, FREE_READ);
 }
 
 static void
@@ -468,6 +494,7 @@
 static struct FsmNode TeiFnList[] HISAX_INITDATA =
 {
 	{ST_TEI_NOP, EV_IDREQ, tei_id_request},
+	{ST_TEI_NOP, EV_ASSIGN, tei_id_test_dup},
 	{ST_TEI_NOP, EV_VERIFY, tei_id_verify},
 	{ST_TEI_NOP, EV_REMOVE, tei_id_remove},
 	{ST_TEI_NOP, EV_CHKREQ, tei_id_chk_req},
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/teleint.c linux/drivers/isdn/hisax/teleint.c
--- v2.3.13/linux/drivers/isdn/hisax/teleint.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/isdn/hisax/teleint.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: teleint.c,v 1.7 1998/11/15 23:55:26 keil Exp $
+/* $Id: teleint.c,v 1.9 1999/07/12 21:05:30 keil Exp $
 
  * teleint.c     low level stuff for TeleInt isdn cards
  *
@@ -6,6 +6,13 @@
  *
  *
  * $Log: teleint.c,v $
+ * Revision 1.9  1999/07/12 21:05:30  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 1.8  1999/07/01 08:12:12  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 1.7  1998/11/15 23:55:26  keil
  * changes from 2.0
  *
@@ -38,7 +45,7 @@
 
 extern const char *CardType[];
 
-const char *TeleInt_revision = "$Revision: 1.7 $";
+const char *TeleInt_revision = "$Revision: 1.9 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -191,7 +198,7 @@
 TeleInt_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u_char val, stat = 0;
+	u_char val;
 
 	if (!cs) {
 		printk(KERN_WARNING "TeleInt: Spurious interrupt!\n");
@@ -199,20 +206,16 @@
 	}
 	val = readreg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_ISTA);
       Start_ISAC:
-	if (val) {
+	if (val)
 		isac_interrupt(cs, val);
-		stat |= 2;
-	}
 	val = readreg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_ISTA);
 	if (val) {
 		if (cs->debug & L1_DEB_ISAC)
 			debugl1(cs, "ISAC IntStat after IntRoutine");
 		goto Start_ISAC;
 	}
-	if (stat & 2) {
-		writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0xFF);
-		writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0x0);
-	}
+	writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0xFF);
+	writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0x0);
 }
 
 static void
@@ -252,11 +255,11 @@
 	save_flags(flags);
 	sti();
 	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(3);
+	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;
-	schedule_timeout(1);
+	schedule_timeout((10*HZ)/1000);
 	restore_flags(flags);
 }
 
@@ -270,9 +273,6 @@
 		case CARD_RELEASE:
 			release_io_TeleInt(cs);
 			return(0);
-		case CARD_SETIRQ:
-			return(request_irq(cs->irq, &TeleInt_interrupt,
-					I4L_IRQ_FLAG, "HiSax", cs));
 		case CARD_INIT:
 			inithfc(cs);
 			clear_pending_isac_ints(cs);
@@ -289,8 +289,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];
@@ -365,6 +365,7 @@
 	cs->BC_Read_Reg = &ReadHFC;
 	cs->BC_Write_Reg = &WriteHFC;
 	cs->cardmsg = &TeleInt_card_msg;
+	cs->irq_func = &TeleInt_interrupt;
 	ISACVersion(cs, "TeleInt:");
 	return (1);
 }
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/teles0.c linux/drivers/isdn/hisax/teles0.c
--- v2.3.13/linux/drivers/isdn/hisax/teles0.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/isdn/hisax/teles0.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: teles0.c,v 2.8 1998/04/15 16:44:28 keil Exp $
+/* $Id: teles0.c,v 2.9 1999/07/12 21:05:31 keil Exp $
 
  * teles0.c     low level stuff for Teles Memory IO isdn cards
  *              based on the teles driver from Jan den Ouden
@@ -10,6 +10,10 @@
  *              Beat Doebeli
  *
  * $Log: teles0.c,v $
+ * Revision 2.9  1999/07/12 21:05:31  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
  * Revision 2.8  1998/04/15 16:44:28  keil
  * new init code
  *
@@ -54,7 +58,7 @@
 
 extern const char *CardType[];
 
-const char *teles0_revision = "$Revision: 2.8 $";
+const char *teles0_revision = "$Revision: 2.9 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -177,7 +181,7 @@
 teles0_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u_char val, stat = 0;
+	u_char val;
 	int count = 0;
 
 	if (!cs) {
@@ -186,39 +190,31 @@
 	}
 	val = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA);
       Start_HSCX:
-	if (val) {
+	if (val)
 		hscx_int_main(cs, val);
-		stat |= 1;
-	}
 	val = readisac(cs->hw.teles0.membase, ISAC_ISTA);
       Start_ISAC:
-	if (val) {
+	if (val)
 		isac_interrupt(cs, val);
-		stat |= 2;
-	}
 	count++;
 	val = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA);
-	if (val && count < 20) {
+	if (val && count < 5) {
 		if (cs->debug & L1_DEB_HSCX)
 			debugl1(cs, "HSCX IntStat after IntRoutine");
 		goto Start_HSCX;
 	}
 	val = readisac(cs->hw.teles0.membase, ISAC_ISTA);
-	if (val && count < 20) {
+	if (val && count < 5) {
 		if (cs->debug & L1_DEB_ISAC)
 			debugl1(cs, "ISAC IntStat after IntRoutine");
 		goto Start_ISAC;
 	}
-	if (stat & 1) {
-		writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0xFF);
-		writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0xFF);
-		writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0x0);
-		writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0x0);
-	}
-	if (stat & 2) {
-		writeisac(cs->hw.teles0.membase, ISAC_MASK, 0xFF);
-		writeisac(cs->hw.teles0.membase, ISAC_MASK, 0x0);
-	}
+	writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0xFF);
+	writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0xFF);
+	writeisac(cs->hw.teles0.membase, ISAC_MASK, 0xFF);
+	writeisac(cs->hw.teles0.membase, ISAC_MASK, 0x0);
+	writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0x0);
+	writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0x0);
 }
 
 void
@@ -290,9 +286,6 @@
 		case CARD_RELEASE:
 			release_io_teles0(cs);
 			return(0);
-		case CARD_SETIRQ:
-			return(request_irq(cs->irq, &teles0_interrupt,
-					I4L_IRQ_FLAG, "HiSax", cs));
 		case CARD_INIT:
 			inithscxisac(cs, 3);
 			return(0);
@@ -302,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;
@@ -382,6 +375,7 @@
 	cs->BC_Write_Reg = &WriteHSCX;
 	cs->BC_Send_Data = &hscx_fill_fifo;
 	cs->cardmsg = &Teles_card_msg;
+	cs->irq_func = &teles0_interrupt;
 	ISACVersion(cs, "Teles0:");
 	if (HscxVersion(cs, "Teles0:")) {
 		printk(KERN_WARNING
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/teles3.c linux/drivers/isdn/hisax/teles3.c
--- v2.3.13/linux/drivers/isdn/hisax/teles3.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/isdn/hisax/teles3.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: teles3.c,v 2.10 1999/02/15 14:37:15 cpetig Exp $
+/* $Id: teles3.c,v 2.12 1999/07/12 21:05:32 keil Exp $
 
  * teles3.c     low level stuff for Teles 16.3 & PNP isdn cards
  *
@@ -11,6 +11,13 @@
  *              Beat Doebeli
  *
  * $Log: teles3.c,v $
+ * Revision 2.12  1999/07/12 21:05:32  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 2.11  1999/07/01 08:12:14  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 2.10  1999/02/15 14:37:15  cpetig
  * oops, missed something in last commit
  *
@@ -78,7 +85,7 @@
 #include "isdnl1.h"
 
 extern const char *CardType[];
-const char *teles3_revision = "$Revision: 2.10 $";
+const char *teles3_revision = "$Revision: 2.12 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -160,9 +167,9 @@
 static void
 teles3_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
-#define MAXCOUNT 20
+#define MAXCOUNT 5
 	struct IsdnCardState *cs = dev_id;
-	u_char val, stat = 0;
+	u_char val;
 	int count = 0;
 
 	if (!cs) {
@@ -171,16 +178,12 @@
 	}
 	val = readreg(cs->hw.teles3.hscx[1], HSCX_ISTA);
       Start_HSCX:
-	if (val) {
+	if (val)
 		hscx_int_main(cs, val);
-		stat |= 1;
-	}
 	val = readreg(cs->hw.teles3.isac, ISAC_ISTA);
       Start_ISAC:
-	if (val) {
+	if (val)
 		isac_interrupt(cs, val);
-		stat |= 2;
-	}
 	count++;
 	val = readreg(cs->hw.teles3.hscx[1], HSCX_ISTA);
 	if (val && count < MAXCOUNT) {
@@ -196,16 +199,12 @@
 	}
 	if (count >= MAXCOUNT)
 		printk(KERN_WARNING "Teles3: more than %d loops in teles3_interrupt\n", count);
-	if (stat & 1) {
-		writereg(cs->hw.teles3.hscx[0], HSCX_MASK, 0xFF);
-		writereg(cs->hw.teles3.hscx[1], HSCX_MASK, 0xFF);
-		writereg(cs->hw.teles3.hscx[0], HSCX_MASK, 0x0);
-		writereg(cs->hw.teles3.hscx[1], HSCX_MASK, 0x0);
-	}
-	if (stat & 2) {
-		writereg(cs->hw.teles3.isac, ISAC_MASK, 0xFF);
-		writereg(cs->hw.teles3.isac, ISAC_MASK, 0x0);
-	}
+	writereg(cs->hw.teles3.hscx[0], HSCX_MASK, 0xFF);
+	writereg(cs->hw.teles3.hscx[1], HSCX_MASK, 0xFF);
+	writereg(cs->hw.teles3.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.teles3.isac, ISAC_MASK, 0x0);
+	writereg(cs->hw.teles3.hscx[0], HSCX_MASK, 0x0);
+	writereg(cs->hw.teles3.hscx[1], HSCX_MASK, 0x0);
 }
 
 inline static void
@@ -222,15 +221,16 @@
 void
 release_io_teles3(struct IsdnCardState *cs)
 {
-	if (cs->typ == ISDN_CTYPE_TELESPCMCIA)
+	if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
 		release_region(cs->hw.teles3.hscx[0], 97);
-	else {
-		if (cs->hw.teles3.cfg_reg)
+	} else {
+		if (cs->hw.teles3.cfg_reg) {
 			if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
 				release_region(cs->hw.teles3.cfg_reg, 1);
 			} else {
 				release_region(cs->hw.teles3.cfg_reg, 8);
 			}
+		}
 		release_ioregs(cs, 0x7);
 	}
 }
@@ -309,9 +309,6 @@
 		case CARD_RELEASE:
 			release_io_teles3(cs);
 			return(0);
-		case CARD_SETIRQ:
-			return(request_irq(cs->irq, &teles3_interrupt,
-					I4L_IRQ_FLAG, "HiSax", cs));
 		case CARD_INIT:
 			inithscxisac(cs, 3);
 			return(0);
@@ -321,8 +318,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;
@@ -405,12 +402,13 @@
 			       CardType[cs->typ],
 			       cs->hw.teles3.isac + 32,
 			       cs->hw.teles3.isac + 64);
-			if (cs->hw.teles3.cfg_reg)
+			if (cs->hw.teles3.cfg_reg) {
 				if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
 					release_region(cs->hw.teles3.cfg_reg, 1);
 				} else {
 					release_region(cs->hw.teles3.cfg_reg, 8);
 				}
+			}
 			return (0);
 		} else
 			request_region(cs->hw.teles3.isac + 32, 32, "HiSax isac");
@@ -420,12 +418,13 @@
 			       CardType[cs->typ],
 			       cs->hw.teles3.hscx[0] + 32,
 			       cs->hw.teles3.hscx[0] + 64);
-			if (cs->hw.teles3.cfg_reg)
+			if (cs->hw.teles3.cfg_reg) {
 				if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
 					release_region(cs->hw.teles3.cfg_reg, 1);
 				} else {
 					release_region(cs->hw.teles3.cfg_reg, 8);
 				}
+			}
 			release_ioregs(cs, 1);
 			return (0);
 		} else
@@ -436,12 +435,13 @@
 			       CardType[cs->typ],
 			       cs->hw.teles3.hscx[1] + 32,
 			       cs->hw.teles3.hscx[1] + 64);
-			if (cs->hw.teles3.cfg_reg)
+			if (cs->hw.teles3.cfg_reg) {
 				if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
 					release_region(cs->hw.teles3.cfg_reg, 1);
 				} else {
 					release_region(cs->hw.teles3.cfg_reg, 8);
 				}
+			}
 			release_ioregs(cs, 3);
 			return (0);
 		} else
@@ -494,6 +494,7 @@
 	cs->BC_Write_Reg = &WriteHSCX;
 	cs->BC_Send_Data = &hscx_fill_fifo;
 	cs->cardmsg = &Teles_card_msg;
+	cs->irq_func = &teles3_interrupt;
 	ISACVersion(cs, "Teles3:");
 	if (HscxVersion(cs, "Teles3:")) {
 		printk(KERN_WARNING
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/hisax/telespci.c linux/drivers/isdn/hisax/telespci.c
--- v2.3.13/linux/drivers/isdn/hisax/telespci.c	Tue Jun  1 23:25:48 1999
+++ linux/drivers/isdn/hisax/telespci.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: telespci.c,v 2.5 1998/11/15 23:55:28 keil Exp $
+/* $Id: telespci.c,v 2.9 1999/08/11 21:01:34 keil Exp $
 
  * telespci.c     low level stuff for Teles PCI isdn cards
  *
@@ -7,6 +7,19 @@
  *
  *
  * $Log: telespci.c,v $
+ * Revision 2.9  1999/08/11 21:01:34  keil
+ * new PCI codefix
+ *
+ * Revision 2.8  1999/08/10 16:02:10  calle
+ * struct pci_dev changed in 2.3.13. Made the necessary changes.
+ *
+ * Revision 2.7  1999/07/12 21:05:34  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 2.6  1999/07/01 08:12:15  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
  * Revision 2.5  1998/11/15 23:55:28  keil
  * changes from 2.0
  *
@@ -24,16 +37,17 @@
  */
 #define __NO_VERSION__
 #include <linux/config.h>
-#include <linux/string.h>
 #include "hisax.h"
 #include "isac.h"
 #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.5 $";
+const char *telespci_revision = "$Revision: 2.9 $";
 
 #define ZORAN_PO_RQ_PEN	0x02000000
 #define ZORAN_PO_WR	0x00800000
@@ -243,35 +257,27 @@
 {
 #define MAXCOUNT 20
 	struct IsdnCardState *cs = dev_id;
-	u_char val, stat = 0;
+	u_char val;
 
 	if (!cs) {
 		printk(KERN_WARNING "TelesPCI: Spurious interrupt!\n");
 		return;
 	}
 	val = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA);
-	if (val) {
+	if (val)
 		hscx_int_main(cs, val);
-		stat |= 1;
-	}
 	val = readisac(cs->hw.teles0.membase, ISAC_ISTA);
-	if (val) {
+	if (val)
 		isac_interrupt(cs, val);
-		stat |= 2;
-	}
 	/* Clear interrupt register for Zoran PCI controller */
 	writel(0x70000000, cs->hw.teles0.membase + 0x3C);
 
-	if (stat & 1) {
-		writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0xFF);
-		writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0xFF);
-		writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0x0);
-		writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0x0);
-	}
-	if (stat & 2) {
-		writeisac(cs->hw.teles0.membase, ISAC_MASK, 0xFF);
-		writeisac(cs->hw.teles0.membase, ISAC_MASK, 0x0);
-	}
+	writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0xFF);
+	writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0xFF);
+	writeisac(cs->hw.teles0.membase, ISAC_MASK, 0xFF);
+	writeisac(cs->hw.teles0.membase, ISAC_MASK, 0x0);
+	writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0x0);
+	writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0x0);
 }
 
 void
@@ -289,9 +295,6 @@
 		case CARD_RELEASE:
 			release_io_telespci(cs);
 			return(0);
-		case CARD_SETIRQ:
-			return(request_irq(cs->irq, &telespci_interrupt,
-					I4L_IRQ_FLAG | SA_SHIRQ, "HiSax", cs));
 		case CARD_INIT:
 			inithscxisac(cs, 3);
 			return(0);
@@ -301,20 +304,29 @@
 	return(0);
 }
 
+#ifdef COMPAT_HAS_NEW_PCI
 static 	struct pci_dev *dev_tel __initdata = NULL;
+#else
+static 	int pci_index __initdata = 0;
+#endif
 
 __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);
@@ -325,15 +337,41 @@
 			printk(KERN_WARNING "Teles: No IRQ for PCI card found\n");
 			return(0);
 		}
-		cs->hw.teles0.membase = (u_int) ioremap(dev_tel->base_address[0],
+		cs->hw.teles0.membase = (u_int) ioremap(get_pcibase(dev_tel, 0),
 			PAGE_SIZE);
 		printk(KERN_INFO "Found: Zoran, base-address: 0x%lx, irq: 0x%x\n",
-			dev_tel->base_address[0], dev_tel->irq);
+			get_pcibase(dev_tel, 0), 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");
 	return (0);
@@ -361,6 +399,8 @@
 	cs->BC_Write_Reg = &WriteHSCX;
 	cs->BC_Send_Data = &hscx_fill_fifo;
 	cs->cardmsg = &TelesPCI_card_msg;
+	cs->irq_func = &telespci_interrupt;
+	cs->irq_flags |= SA_SHIRQ;
 	ISACVersion(cs, "TelesPCI:");
 	if (HscxVersion(cs, "TelesPCI:")) {
 		printk(KERN_WARNING
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/icn/icn.c linux/drivers/isdn/icn/icn.c
--- v2.3.13/linux/drivers/isdn/icn/icn.c	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/icn/icn.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: icn.c,v 1.56 1999/04/12 13:15:07 fritz Exp $
+/* $Id: icn.c,v 1.57 1999/07/06 16:15:30 detabc Exp $
 
  * ISDN low-level module for the ICN active ISDN-Card.
  *
@@ -19,6 +19,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: icn.c,v $
+ * Revision 1.57  1999/07/06 16:15:30  detabc
+ * remove unused messages
+ *
  * Revision 1.56  1999/04/12 13:15:07  fritz
  * Fixed a cast.
  *
@@ -39,10 +42,6 @@
  * Revision 1.51  1998/03/07 22:29:55  fritz
  * Adapted Detlef's chenges for 2.1.
  *
- * Revision 1.50  1998/03/07 17:41:54  detabc
- * add d-channel connect and disconnect support statcallback
- * from icn low-level to link->level
- *
  * Revision 1.49  1998/02/13 11:14:15  keil
  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
  *
@@ -233,7 +232,7 @@
 #undef MAP_DEBUG
 
 static char
-*revision = "$Revision: 1.56 $";
+*revision = "$Revision: 1.57 $";
 
 static int icn_addcard(int, char *, char *);
 
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/isdn_audio.c linux/drivers/isdn/isdn_audio.c
--- v2.3.13/linux/drivers/isdn/isdn_audio.c	Sun May 23 10:03:42 1999
+++ linux/drivers/isdn/isdn_audio.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: isdn_audio.c,v 1.13 1999/04/12 12:33:09 fritz Exp $
+/* $Id: isdn_audio.c,v 1.16 1999/08/06 12:47:35 calle Exp $
 
  * Linux ISDN subsystem, audio conversion and compression (linklevel).
  *
@@ -21,6 +21,27 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_audio.c,v $
+ * Revision 1.16  1999/08/06 12:47:35  calle
+ * Using __GNUC__ == 2 && __GNUC_MINOR__ < 95 how to define
+ *   ISDN_AUDIO_OPTIMIZE_ON_X386_WITH_ASM_IF_GCC_ALLOW_IT
+ *
+ * Revision 1.15  1999/08/06 12:02:52  calle
+ * egcs 2.95 complain about invalid asm statement:
+ *    "fixed or forbidden register 2 (cx) was spilled for class CREG."
+ * Using ISDN_AUDIO_OPTIMIZE_ON_X386_WITH_ASM_IF_GCC_ALLOW_IT and not
+ * define it at the moment.
+ *
+ * Revision 1.14  1999/07/11 17:14:06  armin
+ * Added new layer 2 and 3 protocols for Fax and DSP functions.
+ * Moved "Add CPN to RING message" to new register S23,
+ * "Display message" is now correct on register S13 bit 7.
+ * New audio command AT+VDD implemented (deactivate DTMF decoder and
+ * activate possible existing hardware/DSP decoder).
+ * Moved some tty defines to .h file.
+ * Made whitespace possible in AT command line.
+ * Some AT-emulator output bugfixes.
+ * First Fax G3 implementations.
+ *
  * Revision 1.13  1999/04/12 12:33:09  fritz
  * Changes from 2.0 tree.
  *
@@ -71,7 +92,7 @@
 #include "isdn_audio.h"
 #include "isdn_common.h"
 
-char *isdn_audio_revision = "$Revision: 1.13 $";
+char *isdn_audio_revision = "$Revision: 1.16 $";
 
 /*
  * Misc. lookup-tables.
@@ -268,7 +289,18 @@
 	{'*', '0', '#', 'D'}
 };
 
-#if ((CPU == 386) || (CPU == 486) || (CPU == 586))
+
+/*
+ * egcs 2.95 complain about invalid asm statement:
+ * "fixed or forbidden register 2 (cx) was spilled for class CREG."
+ */
+#if ((CPU == 386) || (CPU == 486) || (CPU == 586)) || defined(__GNUC__)
+#if __GNUC__ == 2 && __GNUC_MINOR__ < 95
+#define ISDN_AUDIO_OPTIMIZE_ON_X386_WITH_ASM_IF_GCC_ALLOW_IT
+#endif
+#endif
+
+#ifdef ISDN_AUDIO_OPTIMIZE_ON_X386_WITH_ASM_IF_GCC_ALLOW_IT
 static inline void
 isdn_audio_tlookup(const void *table, void *buff, unsigned long n)
 {
@@ -711,16 +743,51 @@
 }
 
 void
-isdn_audio_eval_silence(modem_info * info)
+isdn_audio_put_dle_code(modem_info * info, u_char code)
 {
-	silence_state *s = info->silence_state;
 	struct sk_buff *skb;
 	unsigned long flags;
 	int di;
 	int ch;
-	char what;
 	char *p;
 
+	skb = dev_alloc_skb(2);
+	if (!skb) {
+		printk(KERN_WARNING
+		  "isdn_audio: Could not alloc skb for ttyI%d\n",
+		       info->line);
+		return;
+	}
+	p = (char *) skb_put(skb, 2);
+	p[0] = 0x10;
+	p[1] = code;
+	if (skb_headroom(skb) < sizeof(isdn_audio_skb)) {
+		printk(KERN_WARNING
+		       "isdn_audio: insufficient skb_headroom, dropping\n");
+		kfree_skb(skb);
+		return;
+	}
+	ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
+	ISDN_AUDIO_SKB_LOCK(skb) = 0;
+	save_flags(flags);
+	cli();
+	di = info->isdn_driver;
+	ch = info->isdn_channel;
+	__skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
+	dev->drv[di]->rcvcount[ch] += 2;
+	restore_flags(flags);
+	/* Schedule dequeuing */
+	if ((dev->modempoll) && (info->rcvsched))
+		isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
+	wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
+}
+
+void
+isdn_audio_eval_silence(modem_info * info)
+{
+	silence_state *s = info->silence_state;
+	char what;
+
 	what = ' ';
 
 	if (s->idx > (info->emu.vpar[2] * 800)) { 
@@ -734,28 +801,6 @@
 		if ((what == 's') || (what == 'q')) {
 			printk(KERN_DEBUG "ttyI%d: %s\n", info->line,
 				(what=='s') ? "silence":"quiet");
-			skb = dev_alloc_skb(2);
-			p = (char *) skb_put(skb, 2);
-			p[0] = 0x10;
-			p[1] = what;
-			if (skb_headroom(skb) < sizeof(isdn_audio_skb)) {
-				printk(KERN_WARNING
-				       "isdn_audio: insufficient skb_headroom, dropping\n");
-				kfree_skb(skb);
-				return;
-			}
-			ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
-			ISDN_AUDIO_SKB_LOCK(skb) = 0;
-			save_flags(flags);
-			cli();
-			di = info->isdn_driver;
-			ch = info->isdn_channel;
-			__skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
-			dev->drv[di]->rcvcount[ch] += 2;
-			restore_flags(flags);
-			/* Schedule dequeuing */
-			if ((dev->modempoll) && (info->rcvsched))
-				isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
-			wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
+			isdn_audio_put_dle_code(info, what);
 		} 
 }
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/isdn_audio.h linux/drivers/isdn/isdn_audio.h
--- v2.3.13/linux/drivers/isdn/isdn_audio.h	Sun May 23 10:03:42 1999
+++ linux/drivers/isdn/isdn_audio.h	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: isdn_audio.h,v 1.7 1999/04/12 12:33:11 fritz Exp $
+/* $Id: isdn_audio.h,v 1.8 1999/07/11 17:14:07 armin Exp $
 
  * Linux ISDN subsystem, audio conversion and compression (linklevel).
  *
@@ -19,6 +19,17 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_audio.h,v $
+ * Revision 1.8  1999/07/11 17:14:07  armin
+ * Added new layer 2 and 3 protocols for Fax and DSP functions.
+ * Moved "Add CPN to RING message" to new register S23,
+ * "Display message" is now correct on register S13 bit 7.
+ * New audio command AT+VDD implemented (deactivate DTMF decoder and
+ * activate possible existing hardware/DSP decoder).
+ * Moved some tty defines to .h file.
+ * Made whitespace possible in AT command line.
+ * Some AT-emulator output bugfixes.
+ * First Fax G3 implementations.
+ *
  * Revision 1.7  1999/04/12 12:33:11  fritz
  * Changes from 2.0 tree.
  *
@@ -74,3 +85,4 @@
 extern void isdn_audio_calc_silence(modem_info *, unsigned char *, int, int);
 extern void isdn_audio_eval_silence(modem_info *);
 silence_state *isdn_audio_silence_init(silence_state *);
+extern void isdn_audio_put_dle_code(modem_info *, u_char);
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/isdn_budget.c linux/drivers/isdn/isdn_budget.c
--- v2.3.13/linux/drivers/isdn/isdn_budget.c	Sun May 23 10:03:42 1999
+++ linux/drivers/isdn/isdn_budget.c	Wed Dec 31 16:00:00 1969
@@ -1,206 +0,0 @@
-/* $Id: isdn_budget.c,v 1.3 1998/10/23 10:18:39 paul Exp $
- *
- * Linux ISDN subsystem, budget-accounting for network interfaces.
- *
- * Copyright 1997       by Christian Lademann <cal@zls.de>
- * 
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
- *
- * $Log: isdn_budget.c,v $
- * Revision 1.3  1998/10/23 10:18:39  paul
- * Implementation of "dialmode" (successor of "status")
- * You also need current isdnctrl for this!
- *
- * Revision 1.2  1998/03/07 23:17:30  fritz
- * Added RCS keywords
- * Bugfix: Did not compile without isdn_dumppkt beeing enabled.
- *
- */
-
-/*
-30.06.97:cal:angelegt
-04.11.97:cal:budget.period: int --> time_t
-*/
-
-#include <linux/config.h>
-#define __NO_VERSION__
-#include <linux/module.h>
-#include <linux/isdn.h>
-#include "isdn_common.h"
-#include "isdn_net.h"
-
-#ifdef CONFIG_ISDN_BUDGET
-
-#define	VERBOSE_PRINTK(v, l, p...)	{ \
-	if(dev->net_verbose >= (v)) { \
-		printk(l ## p); \
-	} else { ; } \
-}
-
-
-int
-isdn_net_budget(int type, struct device *ndev) {
-	isdn_net_local		*lp = (isdn_net_local *)ndev->priv;
-	int			i, ret = 0;
-
-	switch(type) {
-	case ISDN_BUDGET_INIT:
-		for(i = 0; i < ISDN_BUDGET_NUM_BUDGET; i++) {
-			lp->budget [i] .amount = -1;
-			lp->budget [i] .used = 0;
-			lp->budget [i] .period = (time_t)0;
-			lp->budget [i] .period_started = (time_t)0;
-			lp->budget [i] .last_check = CURRENT_TIME;
-			lp->budget [i] .notified = 0;
-		}
-
-		return(0);
-		break;
-
-	case ISDN_BUDGET_CHECK_DIAL:
-	case ISDN_BUDGET_CHECK_CHARGE:
-	case ISDN_BUDGET_CHECK_ONLINE:
-		ret = 0;
-
-		for(i = 0; i < ISDN_BUDGET_NUM_BUDGET; i++) {
-			if(lp->budget [i] .amount < 0)
-				continue;
-
-			if(lp->budget [i] .period_started + lp->budget [i] .period < CURRENT_TIME) {
-				lp->budget [i] .used = 0;
-				lp->budget [i] .period_started = CURRENT_TIME;
-				lp->budget [i] .notified = 0;
-			}
-
-			if(lp->budget [i] .used >= lp->budget [i] .amount)
-				ret |= (1 << i);
-		}
-
-		switch(type) {
-		case ISDN_BUDGET_CHECK_DIAL:
-			if(! ret) {
-				lp->budget [ISDN_BUDGET_DIAL] .used++;
-				lp->budget [ISDN_BUDGET_DIAL] .last_check = CURRENT_TIME;
-			}
-			break;
-
-		case ISDN_BUDGET_CHECK_CHARGE:
-			lp->budget [ISDN_BUDGET_CHARGE] .used++;
-			lp->budget [ISDN_BUDGET_CHARGE] .last_check = CURRENT_TIME;
-			break;
-
-		case ISDN_BUDGET_CHECK_ONLINE:
-			if(lp->budget [ISDN_BUDGET_ONLINE] .last_check) {
-				lp->budget [ISDN_BUDGET_ONLINE] .used += (CURRENT_TIME - lp->budget [ISDN_BUDGET_ONLINE] .last_check);
-			}
-
-			lp->budget [ISDN_BUDGET_ONLINE] .last_check = CURRENT_TIME;
-			break;
-		}
-
-/*
-		if(ret)
-			lp->flags |= ISDN_NET_DM_OFF;
-*/
-		for(i = 0; i < ISDN_BUDGET_NUM_BUDGET; i++) {
-			if(ret & (1 << i) && ! lp->budget [i] .notified) {
-				switch(i) {
-				case ISDN_BUDGET_DIAL:
-					printk(KERN_WARNING "isdn_budget: dial budget used up.\n");
-					break;
-
-				case ISDN_BUDGET_CHARGE:
-					printk(KERN_WARNING "isdn_budget: charge budget used up.\n");
-					break;
-
-				case ISDN_BUDGET_ONLINE:
-					printk(KERN_WARNING "isdn_budget: online budget used up.\n");
-					break;
-
-				default:
-					printk(KERN_WARNING "isdn_budget: budget #%d used up.\n", i);
-					break;
-				}
-
-				lp->budget [i] .notified = 1;
-			}
-		}
-
-		return(ret);
-		break;
-
-	case ISDN_BUDGET_START_ONLINE:
-		lp->budget [ISDN_BUDGET_ONLINE] .last_check = CURRENT_TIME;
-		return(0);
-
-		break;
-	}
-
-	return(-1);
-}
-
-
-int
-isdn_budget_ioctl(isdn_ioctl_budget *iocmd) {
-	isdn_net_dev		*p = isdn_net_findif(iocmd->name);
-
-	if(p) {
-		switch(iocmd->command) {
-		case ISDN_BUDGET_SET_BUDGET:
-			if(! suser())
-				return(-EPERM);
-
-			if(iocmd->budget < 0 || iocmd->budget > ISDN_BUDGET_NUM_BUDGET)
-				return(-EINVAL);
-
-			if(iocmd->amount < 0)
-				iocmd->amount = -1;
-
-			p->local->budget [iocmd->budget] .amount = iocmd->amount;
-			p->local->budget [iocmd->budget] .period = iocmd->period;
-
-			if(iocmd->used <= 0)
-				p->local->budget [iocmd->budget] .used = 0;
-			else
-				p->local->budget [iocmd->budget] .used = iocmd->used;
-
-			if(iocmd->period_started == (time_t)0)
-				p->local->budget [iocmd->budget] .period_started = CURRENT_TIME;
-			else
-				p->local->budget [iocmd->budget] .period_started = iocmd->period_started;
-
-			return(0);
-			break;
-
-		case ISDN_BUDGET_GET_BUDGET:
-			if(iocmd->budget < 0 || iocmd->budget > ISDN_BUDGET_NUM_BUDGET)
-				return(-EINVAL);
-
-			iocmd->amount = p->local->budget [iocmd->budget] .amount;
-			iocmd->used = p->local->budget [iocmd->budget] .used;
-			iocmd->period = p->local->budget [iocmd->budget] .period;
-			iocmd->period_started = p->local->budget [iocmd->budget] .period_started;
-
-			return(0);
-			break;
-
-		default:
-			return(-EINVAL);
-			break;
-		}
-	}
-	return(-ENODEV);
-}
-#endif
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/isdn_cards.c linux/drivers/isdn/isdn_cards.c
--- v2.3.13/linux/drivers/isdn/isdn_cards.c	Sun May 23 10:03:42 1999
+++ linux/drivers/isdn/isdn_cards.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: isdn_cards.c,v 1.9 1999/04/12 12:33:11 fritz Exp $
+/* $Id: isdn_cards.c,v 1.10 1999/07/20 06:41:28 calle Exp $
 
  * Linux ISDN subsystem, initialization for non-modularized drivers.
  *
@@ -19,6 +19,10 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_cards.c,v $
+ * Revision 1.10  1999/07/20 06:41:28  calle
+ * Bugfix: After the redesign of the AVM B1 driver, the driver didn't even
+ *         compile, if not selected as modules.
+ *
  * Revision 1.9  1999/04/12 12:33:11  fritz
  * Changes from 2.0 tree.
  *
@@ -67,12 +71,9 @@
 #endif
 
 #ifdef CONFIG_ISDN_DRV_AVMB1
-extern void avmb1_init(void);
+extern void kcapi_init(void);
 extern void capi_init(void);
 extern void capidrv_init(void);
-#ifdef CONFIG_PCI
-extern int b1pci_init(void);
-#endif
 #endif
 
 void
@@ -88,10 +89,7 @@
 	pcbit_init();
 #endif
 #ifdef CONFIG_ISDN_DRV_AVMB1
-	avmb1_init();
-#ifdef CONFIG_PCI
-	b1pci_init();
-#endif
+	kcapi_init();
 	capi_init();
 	capidrv_init();
 #endif
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c
--- v2.3.13/linux/drivers/isdn/isdn_common.c	Sun May 23 10:03:42 1999
+++ linux/drivers/isdn/isdn_common.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: isdn_common.c,v 1.75 1999/04/18 14:06:47 fritz Exp $
+/* $Id: isdn_common.c,v 1.86 1999/07/31 12:59:42 armin Exp $
 
  * Linux ISDN subsystem, common used functions (linklevel).
  *
@@ -21,6 +21,51 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_common.c,v $
+ * Revision 1.86  1999/07/31 12:59:42  armin
+ * Added tty fax capabilities.
+ *
+ * Revision 1.85  1999/07/29 16:58:35  armin
+ * Bugfix: DLE handling in isdn_readbchan()
+ *
+ * Revision 1.84  1999/07/25 16:21:10  keil
+ * fix number matching
+ *
+ * Revision 1.83  1999/07/13 21:02:05  werner
+ * Added limit possibilty of driver b_channel resources (ISDN_STAT_DISCH)
+ *
+ * Revision 1.82  1999/07/12 21:06:50  werner
+ * Fixed problem when loading more than one driver temporary
+ *
+ * Revision 1.81  1999/07/11 17:14:09  armin
+ * Added new layer 2 and 3 protocols for Fax and DSP functions.
+ * Moved "Add CPN to RING message" to new register S23,
+ * "Display message" is now correct on register S13 bit 7.
+ * New audio command AT+VDD implemented (deactivate DTMF decoder and
+ * activate possible existing hardware/DSP decoder).
+ * Moved some tty defines to .h file.
+ * Made whitespace possible in AT command line.
+ * Some AT-emulator output bugfixes.
+ * First Fax G3 implementations.
+ *
+ * Revision 1.80  1999/07/07 10:14:00  detabc
+ * remove unused messages
+ *
+ * Revision 1.79  1999/07/05 23:51:30  werner
+ * Allow limiting of available HiSax B-chans per card. Controlled by hisaxctrl
+ * hisaxctrl id 10 <nr. of chans 0-2>
+ *
+ * Revision 1.78  1999/07/05 20:21:15  werner
+ * changes to use diversion sources for all kernel versions.
+ * removed static device, only proc filesystem used
+ *
+ * Revision 1.77  1999/07/01 08:29:50  keil
+ * compatibility to 2.3 kernel
+ *
+ * Revision 1.76  1999/06/29 16:16:44  calle
+ * Let ISDN_CMD_UNLOAD work with open isdn devices without crash again.
+ * Also right unlocking (ISDN_CMD_UNLOCK) is done now.
+ * isdnlog should check returncode of read(2) calls.
+ *
  * Revision 1.75  1999/04/18 14:06:47  fritz
  * Removed TIMRU stuff.
  *
@@ -65,16 +110,6 @@
  * brute force fix to avoid Ugh's in isdn_tty_write()
  * cleaned up some dead code
  *
- * Revision 1.65  1998/06/07 00:20:00  fritz
- * abc cleanup.
- *
- * Revision 1.64  1998/06/02 12:10:03  detabc
- * wegen einer einstweiliger verfuegung gegen DW ist zur zeit
- * die abc-extension bis zur klaerung der rechtslage nicht verfuegbar
- *
- * Revision 1.63  1998/05/03 17:40:38  detabc
- * Include abc-extension-support for >= 2.1.x Kernels in
- * isdn_net.c and isdn_common.c. alpha-test OK and running !
  *
  * Revision 1.62  1998/04/14 16:28:43  he
  * Fixed user space access with interrupts off and remaining
@@ -335,6 +370,9 @@
 #ifdef CONFIG_ISDN_AUDIO
 #include "isdn_audio.h"
 #endif
+#ifdef CONFIG_ISDN_DIVERSION
+#include <linux/isdn_divertif.h>
+#endif CONFIG_ISDN_DIVERSION
 #include "isdn_v110.h"
 #include "isdn_cards.h"
 
@@ -343,7 +381,7 @@
 
 isdn_dev *dev = (isdn_dev *) 0;
 
-static char *isdn_revision = "$Revision: 1.75 $";
+static char *isdn_revision = "$Revision: 1.86 $";
 
 extern char *isdn_net_revision;
 extern char *isdn_tty_revision;
@@ -359,6 +397,11 @@
 #endif
 extern char *isdn_v110_revision;
 
+#ifdef CONFIG_ISDN_DIVERSION
+isdn_divert_if *divert_if = NULL; /* interface to diversion module */
+#endif CONFIG_ISDN_DIVERSION
+
+
 static int isdn_writebuf_stub(int, int, const u_char *, int, int);
 
 void
@@ -449,6 +492,8 @@
 	register int reverse;
 	register int nostar = 1;
 
+	if (!(*s) && !(*p))
+		return(1);
 	for (; *p; s++, p++)
 		switch (*p) {
 			case '\\':
@@ -760,7 +805,7 @@
 				return 0;
 			}
 			/* Try to find a network-interface which will accept incoming call */
-			r = isdn_net_find_icall(di, c->arg, i, c->parm.setup);
+			r = ((c->command == ISDN_STAT_ICALLW) ? 0 : isdn_net_find_icall(di, c->arg, i, c->parm.setup));
 			switch (r) {
 				case 0:
 					/* No network-device replies.
@@ -768,7 +813,13 @@
 					 * These return 0 on no match, 1 on match and
 					 * 3 on eventually match, if CID is longer.
 					 */
-					retval = isdn_tty_find_icall(di, c->arg, c->parm.setup);
+                                        if (c->command == ISDN_STAT_ICALL)
+					  if ((retval = isdn_tty_find_icall(di, c->arg, c->parm.setup))) return(retval);
+#ifdef CONFIG_ISDN_DIVERSION 
+                                         if (divert_if)
+                 	                  if ((retval = divert_if->stat_callback(c))) 
+					    return(retval); /* processed */
+#endif CONFIG_ISDN_DIVERSION                        
 					if ((!retval) && (dev->drv[di]->flags & DRV_FLAG_REJBUS)) {
 						/* No tty responding */
 						cmd.driver = di;
@@ -831,6 +882,20 @@
 			printk(KERN_INFO "isdn: %s,ch%ld cause: %s\n",
 			       dev->drvid[di], c->arg, c->parm.num);
 			isdn_tty_stat_callback(i, c);
+#ifdef CONFIG_ISDN_DIVERSION
+                        if (divert_if)
+                         divert_if->stat_callback(c); 
+#endif CONFIG_ISDN_DIVERSION
+			break;
+		case ISDN_STAT_DISPLAY:
+#ifdef ISDN_DEBUG_STATCALLB
+			printk(KERN_DEBUG "DISPLAY: %ld %s\n", c->arg, c->parm.display);
+#endif
+			isdn_tty_stat_callback(i, c);
+#ifdef CONFIG_ISDN_DIVERSION
+                        if (divert_if)
+                         divert_if->stat_callback(c); 
+#endif CONFIG_ISDN_DIVERSION
 			break;
 		case ISDN_STAT_DCONN:
 			if (i < 0)
@@ -869,6 +934,11 @@
 			isdn_v110_stat_callback(i, c);
 			if (isdn_tty_stat_callback(i, c))
 				break;
+#ifdef CONFIG_ISDN_DIVERSION
+                        if (divert_if)
+                         divert_if->stat_callback(c); 
+#endif CONFIG_ISDN_DIVERSION
+			break;
 			break;
 		case ISDN_STAT_BCONN:
 			if (i < 0)
@@ -924,7 +994,34 @@
 				return -1;
 			isdn_info_update();
 			break;
+		case ISDN_STAT_DISCH:
+			save_flags(flags);
+			cli();
+			for (i = 0; i < ISDN_MAX_CHANNELS; i++)
+				if ((dev->drvmap[i] == di) &&
+				    (dev->chanmap[i] == c->arg)) {
+				    if (c->parm.num[0])
+				      dev->usage[i] &= ~ISDN_USAGE_DISABLED;
+				    else
+				      if (USG_NONE(dev->usage[i])) {
+					dev->usage[i] |= ISDN_USAGE_DISABLED;
+				      }
+				      else 
+					retval = -1;
+				    break;
+				}
+			restore_flags(flags);
+			isdn_info_update();
+			break;
 		case ISDN_STAT_UNLOAD:
+			while (dev->drv[di]->locks > 0) {
+				isdn_ctrl cmd;
+				cmd.driver = di;
+				cmd.arg = 0;
+				cmd.command = ISDN_CMD_UNLOCK;
+				isdn_command(&cmd);
+				dev->drv[di]->locks--;
+			}
 			save_flags(flags);
 			cli();
 			isdn_tty_stat_callback(i, c);
@@ -932,6 +1029,7 @@
 				if (dev->drvmap[i] == di) {
 					dev->drvmap[i] = -1;
 					dev->chanmap[i] = -1;
+					dev->usage[i] &= ~ISDN_USAGE_DISABLED;
 				}
 			dev->drivers--;
 			dev->channels -= dev->drv[di]->channels;
@@ -941,7 +1039,7 @@
 				isdn_free_queue(&dev->drv[di]->rpqueue[i]);
 			kfree(dev->drv[di]->rpqueue);
 			kfree(dev->drv[di]->rcv_waitq);
-#if LINUX_VERSION_CODE < 131841
+#ifndef COMPAT_HAS_NEW_WAITQ
 			kfree(dev->drv[di]->snd_waitq);
 #endif
 			kfree(dev->drv[di]);
@@ -954,6 +1052,22 @@
 			break;
 		case CAPI_PUT_MESSAGE:
 			return(isdn_capi_rec_hl_msg(&c->parm.cmsg));
+#ifdef CONFIG_ISDN_TTY_FAX
+		case ISDN_STAT_FAXIND:
+			isdn_tty_stat_callback(i, c);
+			break;
+#endif
+#ifdef CONFIG_ISDN_AUDIO
+		case ISDN_STAT_AUDIO:
+			isdn_tty_stat_callback(i, c);
+			break;
+#endif
+#ifdef CONFIG_ISDN_DIVERSION
+	        case ISDN_STAT_PROT:
+	        case ISDN_STAT_REDIR:
+                        if (divert_if)
+                          return(divert_if->stat_callback(c));
+#endif CONFIG_ISDN_DIVERSION
 		default:
 			return -1;
 	}
@@ -989,10 +1103,10 @@
  * of the mapping (di,ch)<->minor, happen during the sleep? --he 
  */
 int
-#if LINUX_VERSION_CODE < 131841
-isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, struct wait_queue **sleep)
-#else
+#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;
@@ -1021,7 +1135,7 @@
 		if (ISDN_AUDIO_SKB_LOCK(skb))
 			break;
 		ISDN_AUDIO_SKB_LOCK(skb) = 1;
-		if (ISDN_AUDIO_SKB_DLECOUNT(skb)) {
+		if ((ISDN_AUDIO_SKB_DLECOUNT(skb)) || (dev->drv[di]->DLEflag & (1 << channel))) {
 			char *p = skb->data;
 			unsigned long DLEmask = (1 << channel);
 
@@ -1320,11 +1434,11 @@
 		return mask;
 	}
 	if (minor >= ISDN_MINOR_CTRL && minor <= ISDN_MINOR_CTRLMAX) {
-		poll_wait(file, &(dev->drv[drvidx]->st_waitq), wait);
 		if (drvidx < 0) {
-			printk(KERN_ERR "isdn_common: isdn_poll 1 -> what the hell\n");
-			return POLLERR;
+			/* driver deregistered while file open */
+		        return POLLHUP;
 		}
+		poll_wait(file, &(dev->drv[drvidx]->st_waitq), wait);
 		mask = POLLOUT | POLLWRNORM;
 		if (dev->drv[drvidx]->stavail) {
 			mask |= POLLIN | POLLRDNORM;
@@ -1938,6 +2052,8 @@
 			if ((dev->usage[i] & ISDN_USAGE_EXCLUSIVE) &&
 			((pre_dev != d) || (pre_chan != dev->chanmap[i])))
 				continue;
+			if (dev->usage[i] & ISDN_USAGE_DISABLED)
+			        continue; /* usage not allowed */
 			if (dev->drv[d]->flags & DRV_FLAG_RUNNING) {
 				if (((dev->drv[d]->interface->features & features) == features) ||
 				    (((dev->drv[d]->interface->features & vfeatures) == vfeatures) &&
@@ -2132,13 +2248,12 @@
 	int j, k, m;
 	ulong flags;
 
-#if LINUX_VERSION_CODE >= 131841
+#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;
+       	if (n < 1) return 0;
 
 	m = (adding) ? d->channels + n : n;
 
@@ -2185,13 +2300,13 @@
 
 	if ((adding) && (d->rcv_waitq))
 		kfree(d->rcv_waitq);
-#if LINUX_VERSION_CODE < 131841
-	if (!(d->rcv_waitq = (struct wait_queue **)
-	      kmalloc(sizeof(struct wait_queue *) * m, GFP_KERNEL))) {
-#else
+#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) {
@@ -2201,7 +2316,13 @@
 		}
 		return -1;
 	}
-#if LINUX_VERSION_CODE < 131841
+#ifdef COMPAT_HAS_NEW_WAITQ
+	d->snd_waitq = d->rcv_waitq + m;
+	for (j = 0; j < m; j++) {
+		init_waitqueue_head(&d->rcv_waitq[m]);
+		init_waitqueue_head(&d->snd_waitq[m]);
+	}
+#else
 	memset((char *) d->rcv_waitq, 0, sizeof(struct wait_queue *) * m);
 
 	if ((adding) && (d->snd_waitq))
@@ -2218,12 +2339,6 @@
 		return -1;
 	}
 	memset((char *) d->snd_waitq, 0, sizeof(struct wait_queue *) * m);
-#else
-	d->snd_waitq = d->rcv_waitq + m;
-	for (j = 0; j < m; j++) {
-		init_waitqueue_head(&d->rcv_waitq[m]);
-		init_waitqueue_head(&d->snd_waitq[m]);
-	}
 #endif
 
 	dev->channels += n;
@@ -2245,6 +2360,60 @@
  * Low-level-driver registration
  */
 
+
+#ifdef CONFIG_ISDN_DIVERSION
+extern isdn_divert_if *divert_if;
+
+static char *map_drvname(int di)
+{
+  if ((di < 0) || (di >= ISDN_MAX_DRIVERS)) 
+    return(NULL);
+  return(dev->drvid[di]); /* driver name */
+} /* map_drvname */
+
+static int map_namedrv(char *id)
+{  int i;
+
+   for (i = 0; i < ISDN_MAX_DRIVERS; i++)
+    { if (!strcmp(dev->drvid[i],id)) 
+        return(i);
+    }
+   return(-1);
+} /* map_namedrv */
+
+int DIVERT_REG_NAME(isdn_divert_if *i_div)
+{
+  if (i_div->if_magic != DIVERT_IF_MAGIC) 
+    return(DIVERT_VER_ERR);
+  switch (i_div->cmd)
+    {
+      case DIVERT_CMD_REL:
+        if (divert_if != i_div) 
+          return(DIVERT_REL_ERR);
+        divert_if = NULL; /* free interface */
+        MOD_DEC_USE_COUNT;
+        return(DIVERT_NO_ERR);
+
+      case DIVERT_CMD_REG:
+        if (divert_if) 
+          return(DIVERT_REG_ERR);
+        i_div->ll_cmd = isdn_command; /* set command function */
+        i_div->drv_to_name = map_drvname; 
+        i_div->name_to_drv = map_namedrv; 
+        MOD_INC_USE_COUNT;
+        divert_if = i_div; /* remember interface */
+        return(DIVERT_NO_ERR);
+
+      default:
+        return(DIVERT_CMD_ERR);   
+    }
+} /* DIVERT_REG_NAME */
+
+EXPORT_SYMBOL(DIVERT_REG_NAME);
+
+#endif CONFIG_ISDN_DIVERSION
+
+
 EXPORT_SYMBOL(register_isdn);
 EXPORT_SYMBOL(register_isdn_module);
 EXPORT_SYMBOL(unregister_isdn_module);
@@ -2352,18 +2521,18 @@
 	memset((char *) dev, 0, sizeof(isdn_dev));
 	init_timer(&dev->timer);
 	dev->timer.function = isdn_timer_funct;
-#if LINUX_VERSION_CODE < 131841
-	dev->sem = MUTEX;
-#else
+#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], "???");
-#if LINUX_VERSION_CODE >= 131841
+#ifdef COMPAT_HAS_NEW_WAITQ
 		init_waitqueue_head(&dev->mdm.info[i].open_wait);
 		init_waitqueue_head(&dev->mdm.info[i].close_wait);
 #endif
@@ -2452,6 +2621,9 @@
 	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
 		isdn_tty_cleanup_xmit(&dev->mdm.info[i]);
 		kfree(dev->mdm.info[i].xmit_buf - 4);
+#ifdef CONFIG_ISDN_TTY_FAX
+		kfree(dev->mdm.info[i].fax);
+#endif
 	}
 	if (unregister_chrdev(ISDN_MAJOR, "isdn") != 0) {
 		printk(KERN_WARNING "isdn: controldevice busy, remove cancelled\n");
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/isdn_common.h linux/drivers/isdn/isdn_common.h
--- v2.3.13/linux/drivers/isdn/isdn_common.h	Sun May 23 10:03:42 1999
+++ linux/drivers/isdn/isdn_common.h	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: isdn_common.h,v 1.15 1999/04/18 14:06:50 fritz Exp $
+/* $Id: isdn_common.h,v 1.16 1999/07/01 08:29:54 keil Exp $
 
  * header for Linux ISDN subsystem, common used functions and debugging-switches (linklevel).
  *
@@ -21,6 +21,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_common.h,v $
+ * Revision 1.16  1999/07/01 08:29:54  keil
+ * compatibility to 2.3 kernel
+ *
  * Revision 1.15  1999/04/18 14:06:50  fritz
  * Removed TIMRU stuff.
  *
@@ -115,10 +118,10 @@
 extern void isdn_timer_ctrl(int tf, int onoff);
 extern void isdn_unexclusive_channel(int di, int ch);
 extern int isdn_getnum(char **);
-#if LINUX_VERSION_CODE < 131841
-extern int isdn_readbchan(int, int, u_char *, u_char *, int, struct wait_queue**);
-#else
+#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 *);
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/isdn_concap.c linux/drivers/isdn/isdn_concap.c
--- v2.3.13/linux/drivers/isdn/isdn_concap.c	Sun May 23 10:03:42 1999
+++ linux/drivers/isdn/isdn_concap.c	Wed Aug 18 11:38:57 1999
@@ -53,7 +53,7 @@
 int isdn_concap_dl_data_req(struct concap_proto *concap, struct sk_buff *skb)
 {
 	int tmp;
-	struct device *ndev = concap -> net_dev;
+	struct net_device *ndev = concap -> net_dev;
 	isdn_net_local *lp = (isdn_net_local *) ndev->priv;
 
 	IX25DEBUG( "isdn_concap_dl_data_req: %s \n", concap->net_dev->name);
@@ -66,7 +66,7 @@
 
 int isdn_concap_dl_connect_req(struct concap_proto *concap)
 {
-	struct device *ndev = concap -> net_dev;
+	struct net_device *ndev = concap -> net_dev;
 	isdn_net_local *lp = (isdn_net_local *) ndev->priv;
 	int ret;
 	IX25DEBUG( "isdn_concap_dl_connect_req: %s \n", ndev -> name);
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/isdn_net.c linux/drivers/isdn/isdn_net.c
--- v2.3.13/linux/drivers/isdn/isdn_net.c	Sun May 23 10:03:42 1999
+++ linux/drivers/isdn/isdn_net.c	Wed Aug 18 11:38:57 1999
@@ -1,4 +1,4 @@
-/* $Id: isdn_net.c,v 1.84 1999/04/18 14:06:55 fritz Exp $
+/* $Id: isdn_net.c,v 1.88 1999/07/07 10:13:31 detabc Exp $
 
  * Linux ISDN subsystem, network interfaces and related functions (linklevel).
  *
@@ -21,6 +21,19 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_net.c,v $
+ * Revision 1.88  1999/07/07 10:13:31  detabc
+ * remove unused messages
+ *
+ * Revision 1.87  1999/07/06 07:53:53  calle
+ * calls to dev_alloc_skb waste 16 bytes of memory, if we calculate the
+ * right header space for the lowlevel driver. using alloc_skb instead.
+ *
+ * Revision 1.86  1999/06/09 10:12:05  paul
+ * thinko in previous patch
+ *
+ * Revision 1.85  1999/06/07 19:42:39  paul
+ * isdn_net_getpeer() fixed to return correct `outgoing' flag
+ *
  * Revision 1.84  1999/04/18 14:06:55  fritz
  * Removed TIMRU stuff.
  *
@@ -68,7 +81,7 @@
  * Added more locking stuff in tty_write.
  *
  * Revision 1.71  1998/06/18 22:43:08  fritz
- * Bugfix: Setting ndev->do_ioctl had beed accidetly removed at abc-cleanup.
+ * Bugfix: Setting ndev->do_ioctl had beed accidetly removed at cleanup.
  *
  * Revision 1.70  1998/06/17 19:50:49  he
  * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
@@ -80,40 +93,13 @@
  * so autodial is suppressed for that device until it is switched on using
  * 'isdnctrl status dev-name on'.
  *
- * Revision 1.68  1998/06/07 00:20:05  fritz
- * abc cleanup.
  *
- * Revision 1.67  1998/06/02 12:10:08  detabc
- * wegen einer einstweiliger verfuegung gegen DW ist zur zeit
- * die abc-extension bis zur klaerung der rechtslage nicht verfuegbar
  *
  * Revision 1.66  1998/05/26 22:39:24  he
  * sync'ed with 2.1.102 where appropriate (CAPABILITY changes)
  * concap typo
  * cleared dev.tbusy in isdn_net BCONN status callback
  *
- * Revision 1.65  1998/05/22 10:01:11  detabc
- * in case of a icmp-unreach condition the tcp-keepalive-entrys
- * will be dropped from the internal double-link-list (only abc-extension).
- * send icmp unreach only if the skb->protocol == ETH_P_IP
- * speedup abc-no-dchan  redial
- *
- * Revision 1.64  1998/05/07 19:58:39  detabc
- * bugfix in abc_delayed_hangup
- * optimize keepalive-tests for abc_rawip
- *
- * Revision 1.63  1998/05/05 23:23:36  detabc
- * change ICMP_HOST_UNREACH to ICMP_NET_UNREACH (only abc-ext.)
- * set dev->tbusy to zero in isdn_net_unreachable() (only abc-ext.)
- * drop all new packets and send ICMP_NET_UNREACH for
- * min. dialwait to max. dialwait * 6 time. (only abc-ext.)
- * change random-deliver of packets (small first) from all emcapsulation
- * to only rawip with ABC-Router-Flag enabled.
- *
- * Revision 1.62  1998/05/03 17:40:42  detabc
- * Include abc-extension-support for >= 2.1.x Kernels in
- * isdn_net.c and isdn_common.c. alpha-test OK and running !
- *
  * Revision 1.61  1998/04/16 19:19:42  keil
  * Fix from vger (tx max qlength)
  *
@@ -371,17 +357,17 @@
 /* Prototypes */
 
 int isdn_net_force_dial_lp(isdn_net_local *);
-static int isdn_net_start_xmit(struct sk_buff *, struct device *);
-static int isdn_net_xmit(struct device *, isdn_net_local *, struct sk_buff *);
+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.84 $";
+char *isdn_net_revision = "$Revision: 1.88 $";
 
  /*
   * Code for raw-networking over ISDN
   */
 
 static void
-isdn_net_unreachable(struct device *dev, struct sk_buff *skb, char *reason)
+isdn_net_unreachable(struct net_device *dev, struct sk_buff *skb, char *reason)
 {
 
 	if(skb) {
@@ -403,7 +389,7 @@
 }
 
 static void
-isdn_net_reset(struct device *dev)
+isdn_net_reset(struct net_device *dev)
 {
 #ifdef CONFIG_ISDN_X25
 	struct concap_device_ops * dops =
@@ -426,10 +412,10 @@
 
 /* Open/initialize the board. */
 static int
-isdn_net_open(struct device *dev)
+isdn_net_open(struct net_device *dev)
 {
 	int i;
-	struct device *p;
+	struct net_device *p;
 	struct in_device *in_dev;
 
 	isdn_net_reset(dev);
@@ -616,7 +602,7 @@
 					lp->stats.tx_packets++;
 					lp->stats.tx_bytes += c->parm.length;
 					if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP && lp->sav_skb) {
-						struct device *mdev;
+						struct net_device *mdev;
 						if (lp->master)
 							mdev = lp->master;
 						else
@@ -1060,7 +1046,7 @@
  * Perform hangup for a net-interface.
  */
 void
-isdn_net_hangup(struct device *d)
+isdn_net_hangup(struct net_device *d)
 {
 	isdn_net_local *lp = (isdn_net_local *) d->priv;
 	isdn_ctrl cmd;
@@ -1191,7 +1177,7 @@
  * Side-effects: ndev->tbusy is cleared on success.
  */
 int
-isdn_net_send_skb(struct device *ndev, isdn_net_local * lp,
+isdn_net_send_skb(struct net_device *ndev, isdn_net_local * lp,
 		  struct sk_buff *skb)
 {
 	int ret;
@@ -1224,7 +1210,7 @@
  */
 
 static int
-isdn_net_xmit(struct device *ndev, isdn_net_local * lp, struct sk_buff *skb)
+isdn_net_xmit(struct net_device *ndev, isdn_net_local * lp, struct sk_buff *skb)
 {
 	int ret;
 
@@ -1280,7 +1266,7 @@
 }
 
 static void
-isdn_net_adjust_hdr(struct sk_buff *skb, struct device *dev)
+isdn_net_adjust_hdr(struct sk_buff *skb, struct net_device *dev)
 {
 	isdn_net_local *lp = (isdn_net_local *) dev->priv;
 	if (!skb)
@@ -1300,7 +1286,7 @@
  * and start dialing.
  */
 static int
-isdn_net_start_xmit(struct sk_buff *skb, struct device *ndev)
+isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 {
 	isdn_net_local *lp = (isdn_net_local *) ndev->priv;
 #ifdef CONFIG_ISDN_X25
@@ -1452,9 +1438,9 @@
  * Shutdown a net-interface.
  */
 static int
-isdn_net_close(struct device *dev)
+isdn_net_close(struct net_device *dev)
 {
-	struct device *p;
+	struct net_device *p;
 #ifdef CONFIG_ISDN_X25
 	struct concap_proto * cprot =
 		( (isdn_net_local *) dev->priv ) -> netdev -> cprot;
@@ -1490,7 +1476,7 @@
  * Get statistics
  */
 static struct enet_statistics *
-isdn_net_get_stats(struct device *dev)
+isdn_net_get_stats(struct net_device *dev)
 {
 	isdn_net_local *lp = (isdn_net_local *) dev->priv;
 	return &lp->stats;
@@ -1506,7 +1492,7 @@
  */
 
 static unsigned short
-isdn_net_type_trans(struct sk_buff *skb, struct device *dev)
+isdn_net_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ethhdr *eth;
 	unsigned char *rawp;
@@ -1553,7 +1539,7 @@
 isdn_net_slarp_send(isdn_net_local *lp, int is_reply)
 {
 	unsigned short hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen;
-	struct sk_buff *skb = dev_alloc_skb(hl + sizeof(cisco_hdr) + sizeof(cisco_slarp));
+	struct sk_buff *skb = alloc_skb(hl + sizeof(cisco_hdr) + sizeof(cisco_slarp), GFP_ATOMIC);
 	unsigned long t = (jiffies / HZ * 1000000);
 	int len;
 	cisco_hdr *ch;
@@ -1644,7 +1630,7 @@
  * Got a packet from ISDN-Channel.
  */
 static void
-isdn_net_receive(struct device *ndev, struct sk_buff *skb)
+isdn_net_receive(struct net_device *ndev, struct sk_buff *skb)
 {
 	isdn_net_local *lp = (isdn_net_local *) ndev->priv;
 	isdn_net_local *olp = lp;	/* original 'lp' */
@@ -1793,7 +1779,7 @@
 }
 
 static int
-my_eth_header(struct sk_buff *skb, struct device *dev, unsigned short type,
+my_eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
 	      void *daddr, void *saddr, unsigned len)
 {
 	struct ethhdr *eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
@@ -1838,7 +1824,7 @@
  */
 
 static int
-isdn_net_header(struct sk_buff *skb, struct device *dev, unsigned short type,
+isdn_net_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
 		void *daddr, void *saddr, unsigned plen)
 {
 	isdn_net_local *lp = dev->priv;
@@ -1894,7 +1880,7 @@
 static int
 isdn_net_rebuild_header(struct sk_buff *skb)
 {
-	struct device *dev = skb->dev;
+	struct net_device *dev = skb->dev;
 	isdn_net_local *lp = dev->priv;
 	int ret = 0;
 
@@ -1926,7 +1912,7 @@
  * Interface-setup. (called just after registering a new interface)
  */
 static int
-isdn_net_init(struct device *ndev)
+isdn_net_init(struct net_device *ndev)
 {
 	ushort max_hlhdr_len = 0;
 	isdn_net_local *lp = (isdn_net_local *) ndev->priv;
@@ -2437,7 +2423,7 @@
  * Allocate a new network-interface and initialize its data structures.
  */
 char *
-isdn_net_new(char *name, struct device *master)
+isdn_net_new(char *name, struct net_device *master)
 {
 	isdn_net_dev *netdev;
 
@@ -2466,8 +2452,8 @@
 	netdev->local->p_encap = ISDN_NET_ENCAP_RAWIP;
 	if (master) {
 		/* Device shall be a slave */
-		struct device *p = (((isdn_net_local *) master->priv)->slave);
-		struct device *q = master;
+		struct net_device *p = (((isdn_net_local *) master->priv)->slave);
+		struct net_device *q = master;
 
 		netdev->local->master = master;
 		/* Put device at end of slave-chain */
@@ -2928,7 +2914,7 @@
 	/* for pre-bound channels, we need this extra check */
 	if ( strncmp(dev->num[idx],"???",3) == 0 ) return -ENOTCONN;
 	strncpy(phone->phone,dev->num[idx],ISDN_MSNLEN);
-	phone->outgoing=USG_OUTGOING(idx);
+	phone->outgoing=USG_OUTGOING(dev->usage[idx]);
 	if ( copy_to_user(peer,phone,sizeof(*peer)) ) return -EFAULT;
 	return 0;
 }
@@ -3004,7 +2990,7 @@
 isdn_net_force_hangup(char *name)
 {
 	isdn_net_dev *p = isdn_net_findif(name);
-	struct device *q;
+	struct net_device *q;
 
 	if (p) {
 		if (p->local->isdn_device < 0)
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/isdn_net.h linux/drivers/isdn/isdn_net.h
--- v2.3.13/linux/drivers/isdn/isdn_net.h	Sun May 23 10:03:42 1999
+++ linux/drivers/isdn/isdn_net.h	Wed Aug 18 11:38:57 1999
@@ -100,7 +100,7 @@
 #define CISCO_SLARP_REQUEST   1
 #define CISCO_SLARP_KEEPALIVE 2
 
-extern char *isdn_net_new(char *, struct device *);
+extern char *isdn_net_new(char *, struct net_device *);
 extern char *isdn_net_newslave(char *);
 extern int isdn_net_rm(char *);
 extern int isdn_net_rmall(void);
@@ -112,13 +112,13 @@
 extern int isdn_net_getpeer(isdn_net_ioctl_phone *, isdn_net_ioctl_phone *);
 extern int isdn_net_delphone(isdn_net_ioctl_phone *);
 extern int isdn_net_find_icall(int, int, int, setup_parm);
-extern void isdn_net_hangup(struct device *);
+extern void isdn_net_hangup(struct net_device *);
 extern void isdn_net_dial(void);
 extern void isdn_net_autohup(void);
 extern int isdn_net_force_hangup(char *);
 extern int isdn_net_force_dial(char *);
 extern isdn_net_dev *isdn_net_findif(char *);
-extern int isdn_net_send_skb(struct device *, isdn_net_local *,
+extern int isdn_net_send_skb(struct net_device *, isdn_net_local *,
 			     struct sk_buff *);
 extern int isdn_net_rcv_skb(int, struct sk_buff *);
 extern void isdn_net_slarp_out(void);
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/isdn_ppp.c linux/drivers/isdn/isdn_ppp.c
--- v2.3.13/linux/drivers/isdn/isdn_ppp.c	Sun May 23 10:03:42 1999
+++ linux/drivers/isdn/isdn_ppp.c	Wed Aug 18 11:38:57 1999
@@ -1,4 +1,4 @@
-/* $Id: isdn_ppp.c,v 1.47 1999/04/18 14:06:59 fritz Exp $
+/* $Id: isdn_ppp.c,v 1.49 1999/07/06 07:47:11 calle Exp $
  *
  * Linux ISDN subsystem, functions for synchronous PPP (linklevel).
  *
@@ -19,6 +19,14 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_ppp.c,v $
+ * Revision 1.49  1999/07/06 07:47:11  calle
+ * bugfix: dev_alloc_skb only reserve 16 bytes. We need to look at the
+ *  	hdrlen the driver want. So I changed dev_alloc_skb calls
+ *         to alloc_skb and skb_reserve.
+ *
+ * Revision 1.48  1999/07/01 08:29:56  keil
+ * compatibility to 2.3 kernel
+ *
  * Revision 1.47  1999/04/18 14:06:59  fritz
  * Removed TIMRU stuff.
  *
@@ -261,7 +269,7 @@
 static void isdn_ppp_free_mpqueue(isdn_net_dev *);
 #endif
 
-char *isdn_ppp_revision = "$Revision: 1.47 $";
+char *isdn_ppp_revision = "$Revision: 1.49 $";
 
 static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
 static struct isdn_ppp_compressor *ipc_head = NULL;
@@ -430,7 +438,7 @@
 
 	ippp_table[lp->ppp_slot]->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK;
 
-#if LINUX_VERSION_CODE < 131841
+#ifndef COMPAT_HAS_NEW_WAITQ
 	if (ippp_table[lp->ppp_slot]->wq)
 #endif
 		wake_up_interruptible(&ippp_table[lp->ppp_slot]->wq);
@@ -450,10 +458,10 @@
 		return 0;
 	is = ippp_table[slot];
 
-#if LINUX_VERSION_CODE < 131841
-	if (is->state && is->wq)
-#else
+#ifdef COMPAT_HAS_NEW_WAITQ
 	if (is->state)
+#else
+	if (is->state && is->wq)
 #endif
 		wake_up_interruptible(&is->wq);
 
@@ -519,10 +527,10 @@
 	is->mru = 1524;         /* MRU, default 1524 */
 	is->maxcid = 16;        /* VJ: maxcid */
 	is->tk = current;
-#if LINUX_VERSION_CODE < 131841
-	is->wq = NULL;          /* read() wait queue */
-#else
+#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;
@@ -891,7 +899,7 @@
 	is->last = bl->next;
 	restore_flags(flags);
 
-#if LINUX_VERSION_CODE < 131841
+#ifndef COMPAT_HAS_NEW_WAITQ
 	if (is->wq)
 #endif
 		wake_up_interruptible(&is->wq);
@@ -983,13 +991,21 @@
 		if ((dev->drv[lp->isdn_device]->flags & DRV_FLAG_RUNNING) &&
 			lp->dialstate == 0 &&
 		    (lp->flags & ISDN_NET_CONNECTED)) {
+			unsigned short hl;
 			int cnt;
 			struct sk_buff *skb;
-			skb = dev_alloc_skb(count);
+			/*
+			 * we need to reserve enought space in front of
+			 * 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;
+			skb = alloc_skb(hl+count, GFP_ATOMIC);
 			if (!skb) {
 				printk(KERN_WARNING "isdn_ppp_write: out of memory!\n");
 				return count;
 			}
+			skb_reserve(skb, hl);
 			if (copy_from_user(skb_put(skb, count), buf, count))
 				return -EFAULT;
 			if (is->debug & 0x40) {
@@ -1271,7 +1287,7 @@
 static void
 isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff *skb, int proto)
 {
-	struct device *dev = &net_dev->dev;
+	struct net_device *dev = &net_dev->dev;
 	struct ippp_struct *is = ippp_table[lp->ppp_slot];
 
 	if (is->debug & 0x10) {
@@ -1416,9 +1432,9 @@
  */
 
 int
-isdn_ppp_xmit(struct sk_buff *skb, struct device *dev)
+isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
 {
-	struct device *mdev = ((isdn_net_local *) (dev->priv))->master;	/* get master (for redundancy) */
+	struct net_device *mdev = ((isdn_net_local *) (netdev->priv))->master;	/* get master (for redundancy) */
 	isdn_net_local *lp,*mlp;
 	isdn_net_dev *nd;
 	unsigned int proto = PPP_IP;     /* 0x21 */
@@ -1427,8 +1443,8 @@
 	if (mdev)
 		mlp = (isdn_net_local *) (mdev->priv);
 	else {
-		mdev = dev;
-		mlp = (isdn_net_local *) (dev->priv);
+		mdev = netdev;
+		mlp = (isdn_net_local *) (netdev->priv);
 	}
 	nd = mlp->netdev;       /* get master lp */
 	ipts = ippp_table[mlp->ppp_slot];
@@ -1441,7 +1457,7 @@
 			ipts->old_pa_dstaddr = mdev->pa_dstaddr;
 #endif
 		if (ipts->debug & 0x1)
-			printk(KERN_INFO "%s: IP frame delayed.\n", dev->name);
+			printk(KERN_INFO "%s: IP frame delayed.\n", netdev->name);
 		return 1;
 	}
 
@@ -1506,12 +1522,19 @@
 #ifdef CONFIG_ISDN_PPP_VJ
 	if (proto == PPP_IP && ipts->pppcfg & SC_COMP_TCP) {	/* ipts here? probably yes, but check this again */
 		struct sk_buff *new_skb;
-
-		new_skb = dev_alloc_skb(skb->len);
+	        unsigned short hl;
+		/*
+		 * we need to reserve enought space in front of
+		 * 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;
+		new_skb = alloc_skb(hl+skb->len, GFP_ATOMIC);
 		if (new_skb) {
 			u_char *buf;
 			int pktlen;
 
+			skb_reserve(new_skb, hl);
 			new_skb->dev = skb->dev;
 			skb_put(new_skb, skb->len);
 			buf = skb->data;
@@ -1611,9 +1634,9 @@
 		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);
 	}
-	if (isdn_net_send_skb(dev, lp, skb)) {
+	if (isdn_net_send_skb(netdev, lp, skb)) {
 		if (lp->sav_skb) {	/* whole sav_skb processing with disabled IRQs ?? */
-			printk(KERN_ERR "%s: whoops .. there is another stored skb!\n", dev->name);
+			printk(KERN_ERR "%s: whoops .. there is another stored skb!\n", netdev->name);
 			dev_kfree_skb(skb);
 		} else
 			lp->sav_skb = skb;
@@ -1985,7 +2008,7 @@
  */
 
 static int
-isdn_ppp_dev_ioctl_stats(int slot, struct ifreq *ifr, struct device *dev)
+isdn_ppp_dev_ioctl_stats(int slot, struct ifreq *ifr, struct net_device *dev)
 {
 	struct ppp_stats *res,
 	 t;
@@ -2025,7 +2048,7 @@
 }
 
 int
-isdn_ppp_dev_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
+isdn_ppp_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	int error=0;
 	char *r;
@@ -2088,7 +2111,7 @@
 #ifdef CONFIG_ISDN_MPP
 	isdn_net_dev *ndev;
 	isdn_net_local *lp;
-	struct device *sdev;
+	struct net_device *sdev;
 
 	if (!(ndev = isdn_net_findif(name)))
 		return 1;
@@ -2119,7 +2142,7 @@
 #ifdef CONFIG_ISDN_MPP
 	isdn_net_dev *ndev;
 	isdn_net_local *lp;
-	struct device *sdev;
+	struct net_device *sdev;
 
 	if (!(ndev = isdn_net_findif(name)))
 		return 1;
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/isdn_ppp.h linux/drivers/isdn/isdn_ppp.h
--- v2.3.13/linux/drivers/isdn/isdn_ppp.h	Sun May 23 10:03:42 1999
+++ linux/drivers/isdn/isdn_ppp.h	Wed Aug 18 11:38:57 1999
@@ -78,9 +78,9 @@
 extern void isdn_ppp_cleanup(void);
 extern int isdn_ppp_free(isdn_net_local *);
 extern int isdn_ppp_bind(isdn_net_local *);
-extern int isdn_ppp_xmit(struct sk_buff *, struct device *);
+extern int isdn_ppp_xmit(struct sk_buff *, struct net_device *);
 extern void isdn_ppp_receive(isdn_net_dev *, isdn_net_local *, struct sk_buff *);
-extern int isdn_ppp_dev_ioctl(struct device *, struct ifreq *, int);
+extern int isdn_ppp_dev_ioctl(struct net_device *, struct ifreq *, int);
 extern unsigned int isdn_ppp_poll(struct file *, struct poll_table_struct *);
 extern int isdn_ppp_ioctl(int, struct file *, unsigned int, unsigned long);
 extern void isdn_ppp_release(int, struct file *);
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/isdn_tty.c linux/drivers/isdn/isdn_tty.c
--- v2.3.13/linux/drivers/isdn/isdn_tty.c	Sun May 23 10:03:42 1999
+++ linux/drivers/isdn/isdn_tty.c	Thu Aug 12 09:42:33 1999
@@ -1,4 +1,4 @@
-/* $Id: isdn_tty.c,v 1.63 1999/04/12 12:33:39 fritz Exp $
+/* $Id: isdn_tty.c,v 1.72 1999/07/31 12:59:45 armin Exp $
 
  * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel).
  *
@@ -20,6 +20,43 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_tty.c,v $
+ * Revision 1.72  1999/07/31 12:59:45  armin
+ * Added tty fax capabilities.
+ *
+ * Revision 1.71  1999/07/27 10:34:34  armin
+ * Fixed last change. Did not compile with AUDIO support off.
+ *
+ * Revision 1.70  1999/07/25 16:17:58  keil
+ * Fix Suspend/Resume
+ *
+ * Revision 1.69  1999/07/25 12:56:15  armin
+ * isdn_tty_at_cout() now queues the message if online and
+ * data is in queue or flip buffer is full.
+ * needed for fax connections.
+ *
+ * Revision 1.68  1999/07/11 17:51:51  armin
+ * Bugfix, "-" was missing for AT&L settings.
+ *
+ * Revision 1.67  1999/07/11 17:14:12  armin
+ * Added new layer 2 and 3 protocols for Fax and DSP functions.
+ * Moved "Add CPN to RING message" to new register S23,
+ * "Display message" is now correct on register S13 bit 7.
+ * New audio command AT+VDD implemented (deactivate DTMF decoder and
+ * activate possible existing hardware/DSP decoder).
+ * Moved some tty defines to .h file.
+ * Made whitespace possible in AT command line.
+ * Some AT-emulator output bugfixes.
+ * First Fax G3 implementations.
+ *
+ * Revision 1.66  1999/07/07 10:13:46  detabc
+ * remove unused messages
+ *
+ * Revision 1.65  1999/07/04 21:01:59  werner
+ * Added support for keypad and display (ported from 2.0)
+ *
+ * Revision 1.64  1999/07/01 08:30:00  keil
+ * compatibility to 2.3 kernel
+ *
  * Revision 1.63  1999/04/12 12:33:39  fritz
  * Changes from 2.0 tree.
  *
@@ -61,24 +98,12 @@
  * brute force fix to avoid Ugh's in isdn_tty_write()
  * cleaned up some dead code
  *
- * Revision 1.54  1998/06/07 00:20:13  fritz
- * abc cleanup.
  *
- * Revision 1.53  1998/06/02 12:10:16  detabc
- * wegen einer einstweiliger verfuegung gegen DW ist zur zeit
- * die abc-extension bis zur klaerung der rechtslage nicht verfuegbar
  *
  * Revision 1.52  1998/03/19 13:18:21  keil
  * Start of a CAPI like interface for supplementary Service
  * first service: SUSPEND
  *
- * Revision 1.51  1998/03/08 14:26:11  detabc
- * change kfree_skb to dev_kfree_skb
- * remove SET_SKB_FREE
- *
- * Revision 1.50  1998/03/08 13:14:28  detabc
- * abc-extension support for kernels > 2.1.x
- * first try (sorry experimental)
  *
  * Revision 1.49  1998/03/08 00:01:59  fritz
  * Bugfix: Lowlevel module usage and channel usage were not
@@ -303,7 +328,6 @@
 static void isdn_tty_check_esc(const u_char *, u_char, int, int *, int *, int);
 static void isdn_tty_modem_reset_regs(modem_info *, int);
 static void isdn_tty_cmd_ATA(modem_info *);
-static void isdn_tty_at_cout(char *, modem_info *);
 static void isdn_tty_flush_buffer(struct tty_struct *);
 static void isdn_tty_modem_result(int, modem_info *);
 #ifdef CONFIG_ISDN_AUDIO
@@ -321,64 +345,8 @@
 static int si2bit[8] =
 {4, 1, 4, 4, 4, 4, 4, 4};
 
-char *isdn_tty_revision = "$Revision: 1.63 $";
+char *isdn_tty_revision = "$Revision: 1.72 $";
 
-#define DLE 0x10
-#define ETX 0x03
-#define DC4 0x14
-
-/*
- * Definition of some special Registers of AT-Emulator
- */
-#define REG_RINGATA   0
-#define REG_RINGCNT   1
-#define REG_ESC       2
-#define REG_CR        3
-#define REG_LF        4
-#define REG_BS        5
-
-#define REG_WAITC     7
-
-#define REG_RESP     12
-#define BIT_RESP      1
-#define REG_RESPNUM  12
-#define BIT_RESPNUM   2
-#define REG_ECHO     12
-#define BIT_ECHO      4
-#define REG_DCD      12
-#define BIT_DCD       8
-#define REG_CTS      12
-#define BIT_CTS      16
-#define REG_DTRR     12
-#define BIT_DTRR     32
-#define REG_DSR      12
-#define BIT_DSR      64
-#define REG_CPPP     12
-#define BIT_CPPP    128
-
-#define REG_T70      13
-#define BIT_T70       2
-#define BIT_T70_EXT  32
-#define REG_DTRHUP   13
-#define BIT_DTRHUP    4
-#define REG_RESPXT   13
-#define BIT_RESPXT    8
-#define REG_CIDONCE  13
-#define BIT_CIDONCE  16
-#define REG_RUNG     13
-#define BIT_RUNG     64
-#define REG_RESRXT   13
-#define BIT_RESRXT  128
-
-#define REG_L2PROT   14
-#define REG_L3PROT   15
-#define REG_PSIZE    16
-#define REG_WSIZE    17
-#define REG_SI1      18
-#define REG_SI2      19
-#define REG_SI1I     20
-#define REG_PLAN     21
-#define REG_SCREEN   22
 
 /* isdn_tty_try_read() is called from within isdn_tty_rcv_skb()
  * to stuff incoming data directly into a tty's flip-buffer. This
@@ -514,7 +482,7 @@
 #ifdef CONFIG_ISDN_AUDIO
 	ifmt = 1;
 	
-	if (info->vonline)
+	if ((info->vonline) && (!info->emu.vpar[4]))
 		isdn_audio_calc_dtmf(info, skb->data, skb->len, ifmt);
 	if ((info->vonline & 1) && (info->emu.vpar[1]))
 		isdn_audio_calc_silence(info, skb->data, skb->len, ifmt);
@@ -580,6 +548,15 @@
 		ISDN_AUDIO_SKB_DLECOUNT(skb) =
 			isdn_tty_countDLE(skb->data, skb->len);
 	}
+#ifdef CONFIG_ISDN_TTY_FAX
+	else {
+		if (info->faxonline & 2) {
+			isdn_tty_fax_bitorder(info, skb);
+			ISDN_AUDIO_SKB_DLECOUNT(skb) =
+				isdn_tty_countDLE(skb->data, skb->len);
+		}
+	}
+#endif
 #endif
 	/* Try to deliver directly via tty-flip-buf if queue is empty */
 	save_flags(flags);
@@ -909,6 +886,35 @@
 	}
 }
 
+/*
+ * return the usage calculated by si and layer 2 protocol
+ */
+int
+isdn_calc_usage(int si, int l2)
+{
+	int usg = ISDN_USAGE_MODEM;
+
+#ifdef CONFIG_ISDN_AUDIO
+	if (si == 1) {
+		switch(l2) {
+			case ISDN_PROTO_L2_MODEM: 
+				usg = ISDN_USAGE_MODEM;
+				break;
+#ifdef CONFIG_ISDN_TTY_FAX
+			case ISDN_PROTO_L2_FAX: 
+				usg = ISDN_USAGE_FAX;
+				break;
+#endif
+			case ISDN_PROTO_L2_TRANS: 
+			default:
+				usg = ISDN_USAGE_VOICE;
+				break;
+		}
+	}
+#endif
+	return(usg);
+}
+
 /* isdn_tty_dial() performs dialing of a tty an the necessary
  * setup of the lower levels before that.
  */
@@ -928,8 +934,14 @@
 			si = bit2si[j];
 			break;
 		}
+	usg = isdn_calc_usage(si, l2);
 #ifdef CONFIG_ISDN_AUDIO
-	if ((si == 1) && (l2 != ISDN_PROTO_L2_MODEM)) {
+	if ((si == 1) && 
+		(l2 != ISDN_PROTO_L2_MODEM)
+#ifdef CONFIG_ISDN_TTY_FAX
+		&& (l2 != ISDN_PROTO_L2_FAX)
+#endif
+		) {
 		l2 = ISDN_PROTO_L2_TRANS;
 		usg = ISDN_USAGE_VOICE;
 	}
@@ -967,6 +979,12 @@
 		cmd.driver = info->isdn_driver;
 		cmd.command = ISDN_CMD_SETL3;
 		cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
+#ifdef CONFIG_ISDN_TTY_FAX
+		if (l2 == ISDN_PROTO_L2_FAX) {
+			cmd.parm.fax = info->fax;
+			info->fax->direction = ISDN_TTY_FAX_CONN_OUT;
+		}
+#endif
 		isdn_command(&cmd);
 		cmd.driver = info->isdn_driver;
 		cmd.arg = info->isdn_channel;
@@ -989,7 +1007,7 @@
  * ISDN-line (hangup). The usage-status is cleared
  * and some cleanup is done also.
  */
-static void
+void
 isdn_tty_modem_hup(modem_info * info, int local)
 {
 	isdn_ctrl cmd;
@@ -1010,6 +1028,12 @@
 	}
 #ifdef CONFIG_ISDN_AUDIO
 	info->vonline = 0;
+#ifdef CONFIG_ISDN_TTY_FAX
+	info->faxonline = 0;
+	info->fax->phase = ISDN_FAX_PHASE_IDLE;
+#endif
+	info->emu.vpar[4] = 0;
+	info->emu.vpar[5] = 8;
 	if (info->dtmf_state) {
 		kfree(info->dtmf_state);
 		info->dtmf_state = NULL;
@@ -1041,9 +1065,8 @@
 		}
 		isdn_all_eaz(info->isdn_driver, info->isdn_channel);
 		info->emu.mdmreg[REG_RINGCNT] = 0;
-		usage = ((info->emu.mdmreg[REG_SI1I] != 1) || 
-		    (info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM)) ?
-			ISDN_USAGE_MODEM : ISDN_USAGE_VOICE;
+		usage = isdn_calc_usage(info->emu.mdmreg[REG_SI1I],
+					info->emu.mdmreg[REG_L2PROT]);
 		isdn_free_channel(info->isdn_driver, info->isdn_channel,
 				  usage);
 	}
@@ -1130,8 +1153,14 @@
 			si = bit2si[j];
 			break;
 		}
+	usg = isdn_calc_usage(si, l2);
 #ifdef CONFIG_ISDN_AUDIO
-	if ((si == 1) && (l2 != ISDN_PROTO_L2_MODEM)) {
+	if ((si == 1) && 
+		(l2 != ISDN_PROTO_L2_MODEM)
+#ifdef CONFIG_ISDN_TTY_FAX
+		&& (l2 != ISDN_PROTO_L2_FAX)
+#endif
+		) {
 		l2 = ISDN_PROTO_L2_TRANS;
 		usg = ISDN_USAGE_VOICE;
 	}
@@ -1184,11 +1213,11 @@
 		cmd.parm.cmsg.para[5] = l;
 		strncpy(&cmd.parm.cmsg.para[6], id, l);
 		cmd.command =CAPI_PUT_MESSAGE;
-/*		info->dialing = 1;
-		strcpy(dev->num[i], n);
+		info->dialing = 1;
+//		strcpy(dev->num[i], n);
 		isdn_info_update();
-*/
 		isdn_command(&cmd);
+		isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1);
 	}
 }
 
@@ -1218,8 +1247,14 @@
 			si = bit2si[j];
 			break;
 		}
+	usg = isdn_calc_usage(si, l2);
 #ifdef CONFIG_ISDN_AUDIO
-	if ((si == 1) && (l2 != ISDN_PROTO_L2_MODEM)) {
+	if ((si == 1) && 
+		(l2 != ISDN_PROTO_L2_MODEM)
+#ifdef CONFIG_ISDN_TTY_FAX
+		&& (l2 != ISDN_PROTO_L2_FAX)
+#endif
+		) {
 		l2 = ISDN_PROTO_L2_TRANS;
 		usg = ISDN_USAGE_VOICE;
 	}
@@ -1863,11 +1898,11 @@
 static int
 isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * info)
 {
-#if LINUX_VERSION_CODE < 131841
+#ifdef COMPAT_HAS_NEW_WAITQ
+	DECLARE_WAITQUEUE(wait, NULL);
+#else
 	struct wait_queue wait =
 	{current, NULL};
-#else
-	DECLARE_WAITQUEUE(wait, NULL);
 #endif
 	int do_clocal = 0;
 	unsigned long flags;
@@ -2191,6 +2226,7 @@
 	m->profile[18] = 4;
 	m->profile[19] = 0;
 	m->profile[20] = 0;
+	m->profile[23] = 0;
 	m->pmsn[0] = '\0';
 	m->plmsn[0] = '\0';
 }
@@ -2203,6 +2239,42 @@
 	m->vpar[1] = 0;         /* Silence detection level (0 = none      ) */
 	m->vpar[2] = 70;        /* Silence interval        (7 sec.        ) */
 	m->vpar[3] = 2;         /* Compression type        (1 = ADPCM-2   ) */
+	m->vpar[4] = 0;         /* DTMF detection level    (0 = softcode  ) */
+	m->vpar[5] = 8;         /* DTMF interval           (8 * 5 ms.     ) */
+}
+#endif
+
+#ifdef CONFIG_ISDN_TTY_FAX
+static void
+isdn_tty_modem_reset_faxpar(modem_info * info)
+{
+	T30_s *f = info->fax;
+
+	f->code = 0;
+	f->phase = ISDN_FAX_PHASE_IDLE;
+	f->direction = 0;
+	f->resolution = 1;	/* fine */
+	f->rate = 5;		/* 14400 bit/s */
+	f->width = 0;
+	f->length = 0;
+	f->compression = 0;
+	f->ecm = 0;
+	f->binary = 0;
+	f->scantime = 0;
+	memset(&f->id[0], 32, FAXIDLEN - 1);
+	f->id[FAXIDLEN - 1] = 0;
+	f->badlin = 0;
+	f->badmul = 0;
+	f->bor = 0;
+	f->nbc = 0;
+	f->cq = 0;
+	f->cr = 0;
+	f->ctcrty = 0;
+	f->minsp = 0;
+	f->phcto = 30;
+	f->rel = 0;
+	memset(&f->pollid[0], 32, FAXIDLEN - 1);
+	f->pollid[FAXIDLEN - 1] = 0;
 }
 #endif
 
@@ -2219,6 +2291,9 @@
 #ifdef CONFIG_ISDN_AUDIO
 	isdn_tty_modem_reset_vpar(m);
 #endif
+#ifdef CONFIG_ISDN_TTY_FAX
+	isdn_tty_modem_reset_faxpar(info);
+#endif
 	m->mdmcmdl = 0;
 }
 
@@ -2291,10 +2366,16 @@
 	}
 	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
 		info = &m->info[i];
-#if LINUX_VERSION_CODE < 131841
-		info->write_sem = MUTEX;
-#else
+#ifdef CONFIG_ISDN_TTY_FAX
+		if (!(info->fax = kmalloc(sizeof(T30_s), GFP_KERNEL))) {
+			printk(KERN_ERR "Could not allocate fax t30-buffer\n");
+			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");
@@ -2312,14 +2393,14 @@
 		info->blocked_open = 0;
 		info->callout_termios = m->cua_modem.init_termios;
 		info->normal_termios = m->tty_modem.init_termios;
-#if LINUX_VERSION_CODE < 131841
-		info->open_wait = 0;
-		info->close_wait = 0;
-#else
+#ifdef COMPAT_HAS_NEW_WAITQ
 		init_waitqueue_head(&info->open_wait);
 		init_waitqueue_head(&info->close_wait);
-#endif
+#else
+		info->open_wait = 0;
+		info->close_wait = 0;
 		info->isdn_driver = -1;
+#endif
 		info->isdn_channel = -1;
 		info->drv_index = -1;
 		info->xmit_size = ISDN_SERIAL_XMIT_SIZE;
@@ -2371,8 +2452,15 @@
 				break;
 		}
 		return ret;
-	} else
-		return isdn_wildmat(cid, isdn_map_eaz2msn(emu->msn, di));
+	} else {
+		int tmp;
+		tmp = isdn_wildmat(cid, isdn_map_eaz2msn(emu->msn, di));
+#ifdef ISDN_DEBUG_MODEM_ICALL
+			printk(KERN_DEBUG "m_fi: mmsn=%s -> tmp=%d\n",
+			       isdn_map_eaz2msn(emu->msn, di), tmp);
+#endif
+		return tmp;
+	}
 }
 
 /*
@@ -2424,7 +2512,7 @@
 		    (info->emu.mdmreg[REG_SI2] == si2))	{         /* SI2 is matching */
 			idx = isdn_dc2minor(di, ch);
 #ifdef ISDN_DEBUG_MODEM_ICALL
-			printk(KERN_DEBUG "m_fi: match1\n");
+			printk(KERN_DEBUG "m_fi: match1 wret=%d\n", wret);
 			printk(KERN_DEBUG "m_fi: idx=%d flags=%08lx drv=%d ch=%d usg=%d\n", idx,
 			       info->flags, info->isdn_driver, info->isdn_channel,
 			       dev->usage[idx]);
@@ -2446,8 +2534,7 @@
 					info->drv_index = idx;
 					dev->m_idx[idx] = info->line;
 					dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE;
-					dev->usage[idx] |= ((si1 != 1) || (info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM)) ? 
-						ISDN_USAGE_MODEM : ISDN_USAGE_VOICE;
+					dev->usage[idx] |= isdn_calc_usage(si1, info->emu.mdmreg[REG_L2PROT]); 
 					strcpy(dev->num[idx], nr);
 					strcpy(info->emu.cpn, eaz);
 					info->emu.mdmreg[REG_SI1I] = si2bit[si1];
@@ -2514,6 +2601,19 @@
 				/* Signal cause to tty-device */
 				strncpy(info->last_cause, c->parm.num, 5);
 				return 1;
+			case ISDN_STAT_DISPLAY:
+#ifdef ISDN_TTY_STAT_DEBUG
+				printk(KERN_DEBUG "tty_STAT_DISPLAY ttyI%d\n", info->line);
+#endif
+				/* Signal display to tty-device */
+				if ((info->emu.mdmreg[REG_DISPLAY] & BIT_DISPLAY) && 
+					!(info->emu.mdmreg[REG_RESPNUM] & BIT_RESPNUM)) {
+				  isdn_tty_at_cout("\r\n", info);
+				  isdn_tty_at_cout("DISPLAY: ", info);
+				  isdn_tty_at_cout(c->parm.display, info);
+				  isdn_tty_at_cout("\r\n", info);
+				}
+				return 1;
 			case ISDN_STAT_DCONN:
 #ifdef ISDN_TTY_STAT_DEBUG
 				printk(KERN_DEBUG "tty_STAT_DCONN ttyI%d\n", info->line);
@@ -2612,6 +2712,27 @@
 					}
 				}
 				return 1;
+#ifdef CONFIG_ISDN_TTY_FAX
+			case ISDN_STAT_FAXIND:
+				if (TTY_IS_ACTIVE(info)) {
+					isdn_tty_fax_command(info); 
+				}
+				break;
+#endif
+#ifdef CONFIG_ISDN_AUDIO
+			case ISDN_STAT_AUDIO:
+				if (TTY_IS_ACTIVE(info)) {
+					switch(c->parm.num[0]) {
+						case ISDN_AUDIO_DTMF:
+							if (info->vonline) {
+								isdn_audio_put_dle_code(info,
+									c->parm.num[1]);
+							}
+							break;
+					}
+				}
+				break;
+#endif
 		}
 	}
 	return 0;
@@ -2621,13 +2742,13 @@
  Modem-Emulator-Routines
  *********************************************************************/
 
-#define cmdchar(c) ((c>' ')&&(c<=0x7f))
+#define cmdchar(c) ((c>=' ')&&(c<=0x7f))
 
 /*
  * Put a message from the AT-emulator into receive-buffer of tty,
  * convert CR, LF, and BS to values in modem-registers 3, 4 and 5.
  */
-static void
+void
 isdn_tty_at_cout(char *msg, modem_info * info)
 {
 	struct tty_struct *tty;
@@ -2635,6 +2756,8 @@
 	char *p;
 	char c;
 	ulong flags;
+	struct sk_buff *skb = 0;
+	char *sp = 0;
 
 	if (!msg) {
 		printk(KERN_WARNING "isdn_tty: Null-Message in isdn_tty_at_cout\n");
@@ -2643,6 +2766,34 @@
 	save_flags(flags);
 	cli();
 	tty = info->tty;
+	if ((info->flags & ISDN_ASYNC_CLOSING) || (!tty)) {
+		restore_flags(flags);
+		return;
+	}
+
+	/* use queue instead of direct flip, if online and */
+	/* data is in queue or flip buffer is full */
+	if ((info->online) && (((tty->flip.count + strlen(msg)) >= TTY_FLIPBUF_SIZE) ||
+	    (!skb_queue_empty(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel])))) {
+		skb = alloc_skb(strlen(msg)
+#ifdef CONFIG_ISDN_AUDIO
+			+ sizeof(isdn_audio_skb)
+#endif
+			, GFP_ATOMIC);
+		if (!skb) {
+			restore_flags(flags);
+			return;
+		}
+#ifdef CONFIG_ISDN_AUDIO
+		skb_reserve(skb, sizeof(isdn_audio_skb));
+#endif
+		sp = skb_put(skb, strlen(msg));
+#ifdef CONFIG_ISDN_AUDIO
+		ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
+		ISDN_AUDIO_SKB_LOCK(skb) = 0;
+#endif
+	}
+
 	for (p = msg; *p; p++) {
 		switch (*p) {
 			case '\r':
@@ -2657,16 +2808,26 @@
 			default:
 				c = *p;
 		}
-		if ((info->flags & ISDN_ASYNC_CLOSING) || (!tty)) {
-			restore_flags(flags);
-			return;
+		if (skb) {
+			*sp++ = c;
+		} else {
+			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+				break;
+			tty_insert_flip_char(tty, c, 0);
 		}
-		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-			break;
-		tty_insert_flip_char(tty, c, 0);
 	}
-	restore_flags(flags);
-	queue_task(&tty->flip.tqueue, &tq_timer);
+	if (skb) {
+		__skb_queue_tail(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel], skb);
+		dev->drv[info->isdn_driver]->rcvcount[info->isdn_channel] += skb->len;
+		restore_flags(flags);
+		/* Schedule dequeuing */
+		if ((dev->modempoll) && (info->rcvsched))
+			isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
+
+	} else {
+		restore_flags(flags);
+		queue_task(&tty->flip.tqueue, &tq_timer);
+	}
 }
 
 /*
@@ -2847,7 +3008,7 @@
 					break;
 				case 2:
 					/* Append CPN, if enabled */
-					if ((m->mdmreg[REG_RESRXT] & BIT_RESRXT)) {
+					if ((m->mdmreg[REG_CPN] & BIT_CPN)) {
 						sprintf(s, "/%s", m->cpn);
 						isdn_tty_at_cout(s, info);
 					}
@@ -2954,8 +3115,9 @@
 	int limit=39;	/* MUST match the size in isdn_tty_parse to avoid
 				buffer overflow */
 
-	while (strchr("0123456789,#.*WPTS-", *p) && *p && --cnt>0) {
-		if ((*p >= '0' && *p <= '9') || ((*p == 'S') && first))
+	while (strchr(" 0123456789,#.*WPTS-", *p) && *p && --cnt>0) {
+		if ((*p >= '0' && *p <= '9') || ((*p == 'S') && first) ||
+		    (*p == '*') || (*p == '#'))
 			*q++ = *p;
 		p++;
 		if(!--limit)
@@ -3008,6 +3170,9 @@
 		case ISDN_PROTO_L2_MODEM:
 			isdn_tty_at_cout("modem", info);
 			break;
+		case ISDN_PROTO_L2_FAX:
+			isdn_tty_at_cout("fax", info);
+			break;
 		default:
 			isdn_tty_at_cout("unknown", info);
 			break;
@@ -3107,8 +3272,8 @@
 			/* &L -Set Numbers to listen on */
 			p[0]++;
 			i = 0;
-			while ((strchr("0123456789,*[]?;", *p[0])) &&
-			       (i < ISDN_LMSNLEN))
+			while ((strchr("0123456789,-*[]?;", *p[0])) &&
+			       (i < ISDN_LMSNLEN) && *p[0])
 				m->lmsn[i++] = *p[0]++;
 			m->lmsn[i] = '\0';
 			break;
@@ -3264,7 +3429,7 @@
 	int bval;
 
 	mreg = isdn_getnum(p);
-	if (mreg < 0 || mreg > ISDN_MODEM_ANZREG)
+	if (mreg < 0 || mreg >= ISDN_MODEM_ANZREG)
 		PARSE_ERROR1;
 	switch (*p[0]) {
 		case '=':
@@ -3338,7 +3503,7 @@
 		/* If more than one bit set in reg18, autoselect Layer2 */
 		if ((m->mdmreg[REG_SI1] & m->mdmreg[REG_SI1I]) != m->mdmreg[REG_SI1]) {
 			if (m->mdmreg[REG_SI1I] == 1) {
-				if (l2 != ISDN_PROTO_L2_MODEM)
+				if ((l2 != ISDN_PROTO_L2_MODEM) && (l2 != ISDN_PROTO_L2_FAX))
 					l2 = ISDN_PROTO_L2_TRANS;
 			} else
 				l2 = ISDN_PROTO_L2_X75I;
@@ -3352,6 +3517,12 @@
 		cmd.driver = info->isdn_driver;
 		cmd.command = ISDN_CMD_SETL3;
 		cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
+#ifdef CONFIG_ISDN_TTY_FAX
+		if (l2 == ISDN_PROTO_L2_FAX) {
+			cmd.parm.fax = info->fax;
+			info->fax->direction = ISDN_TTY_FAX_CONN_IN;
+		}
+#endif
 		isdn_command(&cmd);
 		cmd.driver = info->isdn_driver;
 		cmd.arg = info->isdn_channel;
@@ -3372,7 +3543,6 @@
 isdn_tty_cmd_PLUSF(char **p, modem_info * info)
 {
 	atemu *m = &info->emu;
-	int par;
 	char rs[20];
 
 	if (!strncmp(p[0], "CLASS", 5)) {
@@ -3382,6 +3552,10 @@
 				p[0]++;
 				sprintf(rs, "\r\n%d",
 					(m->mdmreg[REG_SI1] & 1) ? 8 : 0);
+#ifdef CONFIG_ISDN_TTY_FAX
+				if (m->mdmreg[REG_L2PROT] == ISDN_PROTO_L2_FAX)
+				sprintf(rs, "\r\n2");
+#endif
 				isdn_tty_at_cout(rs, info);
 				break;
 			case '=':
@@ -3389,23 +3563,37 @@
 				switch (*p[0]) {
 					case '0':
 						p[0]++;
+						m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I;
+						m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_TRANS;
 						m->mdmreg[REG_SI1] = 4;
 						info->xmit_size =
 						    m->mdmreg[REG_PSIZE] * 16;
 						break;
+#ifdef CONFIG_ISDN_TTY_FAX
 					case '2':
-						printk(KERN_DEBUG "isdn_tty: FCLASS=2\n");
 						p[0]++;
+						m->mdmreg[REG_SI1] = 1;
+						m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_FAX;
+						m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_FAX;
+						info->xmit_size =
+						    m->mdmreg[REG_PSIZE] * 16;
 						break;
+#endif
 					case '8':
 						p[0]++;
+						/* L2 will change on dialout with si=1 */
+						m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I;
+						m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_TRANS;
 						m->mdmreg[REG_SI1] = 5;
 						info->xmit_size = VBUF;
 						break;
 					case '?':
 						p[0]++;
-						isdn_tty_at_cout("\r\n0,2,8",
-								 info);
+#ifdef CONFIG_ISDN_TTY_FAX
+						isdn_tty_at_cout("\r\n0,2,8", info);
+#else
+						isdn_tty_at_cout("\r\n0,8", info);
+#endif
 						break;
 					default:
 						PARSE_ERROR1;
@@ -3416,115 +3604,11 @@
 		}
 		return 0;
 	}
-	if (!strncmp(p[0], "AA", 2)) {
-		p[0] += 2;
-		switch (*p[0]) {
-			case '?':
-				p[0]++;
-				sprintf(rs, "\r\n%d",
-					m->mdmreg[REG_RINGATA]);
-				isdn_tty_at_cout(rs, info);
-				break;
-			case '=':
-				p[0]++;
-				par = isdn_getnum(p);
-				if ((par < 0) || (par > 255))
-					PARSE_ERROR1;
-				m->mdmreg[REG_RINGATA] = par;
-				break;
-			default:
-				PARSE_ERROR1;
-		}
-		return 0;
-	}
-        if (!strncmp(p[0], "TBC=", 4)) { /* UNKLAR !! */
-                p[0] += 4;
-                printk(KERN_DEBUG "isdn_tty: Fax FTBC=%c\n", *p[0]);
-                switch (*p[0]) {
-                        case '0':
-                                p[0]++;
-                                break;
-                        default:
-                                PARSE_ERROR1;
-                }
-                return 0;
-        }
-        if (!strncmp(p[0], "BOR=", 4)) { /* UNKLAR !! */
-                p[0] += 4;
-                printk(KERN_DEBUG "isdn_tty: Fax FBOR=%c\n", *p[0]);
-                switch (*p[0]) {
-                        case '0':
-                                p[0]++;
-                                break;
-                        default:
-                                PARSE_ERROR1;
-                }
-                return 0;
-        }
-        if (!strncmp(p[0], "DCC=", 4)) { /* SETUP irgendwie !! */
-		int i, val[]={0,0,0,0,0,0,0,0};
-
-                p[0] += 4;
-                if (*p[0] == '?') {
-			isdn_tty_at_cout("\r\n(0,1),(0-5),(0-2),(0-2),(0,1),(0),(0),(0-7)",info);
-			p[0]++;
-                } else {
-			for (i=0; (*p[0]>='0') && (*p[0]<='9'); i++) {
-				val[i] = *p[0] - 48;
-				p[0]++;
-				if (*p[0] == ',')
-					p[0]++;
-			}
-			printk(KERN_DEBUG "isdn_tty: Fax Setup values=%d,%d,%d,%d,%d,%d,%d,%d\n",
-			       val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7]);
-                }
-                return 0;
-        }
-        if (!strncmp(p[0], "LID=", 4)) { /* set sender ID !! */
-		char senderID[80];
-		int i;
-
-                p[0] += 4;
-                if (*p[0] =='"')
-			p[0]++;
-                for(i=0; (*p[0]) && (*p[0] != '"'); i++)
-			senderID[i] = *p[0]++;
-                senderID[i] = 0;
-                if (*p[0] =='"')
-			p[0]++;
-                printk(KERN_DEBUG "isdn_tty: Fax sender=>%s<\n", senderID);
-                return 0;
-        }
-        if (!strncmp(p[0], "MFR?", 4)) {
-                p[0] += 4;
-                printk(KERN_DEBUG "isdn_tty: FMFR?\n");
-                isdn_tty_at_cout("\r\nISDNfax", info);
-                return 0;
-        }
-        if (!strncmp(p[0], "MDL?", 4)) {
-                p[0] += 4;
-                printk(KERN_DEBUG "isdn_tty: FMDL?\n");
-                isdn_tty_at_cout("\r\nAVM-B1", info);
-                return 0;
-        }
-        if (!strncmp(p[0], "AP=?", 4)) {
-                p[0] += 4;
-                printk(KERN_DEBUG "isdn_tty: FAP=?\n");
-                return 0;
-        }
-        if (!strncmp(p[0], "PHCTO=", 6)) {
-		/* beim trace mit dem zyxel folgt der wert 30 ;*/
-                p[0] += 6;
-                printk(KERN_DEBUG "isdn_tty: FPHCTO=%s\n", p[0]);
-                return 0;
-        }
-        if (!strncmp(p[0], "CR=", 3)) {
-                p[0] += 3;
-                printk(KERN_DEBUG "isdn_tty: FCR=%s\n", p[0]);
-                return 0;
-        }
-        printk(KERN_DEBUG "isdn_tty: unknown token=>AT+F%s<\n", p[0]);
+#ifdef CONFIG_ISDN_TTY_FAX
+	return (isdn_tty_cmd_PLUSF_FAX(p, info));
+#else
 	PARSE_ERROR1;
+#endif
 }
 
 /*
@@ -3534,8 +3618,9 @@
 isdn_tty_cmd_PLUSV(char **p, modem_info * info)
 {
 	atemu *m = &info->emu;
+	isdn_ctrl cmd;
 	static char *vcmd[] =
-	{"NH", "IP", "LS", "RX", "SD", "SM", "TX", NULL};
+	{"NH", "IP", "LS", "RX", "SD", "SM", "TX", "DD", NULL};
 	int i;
 	int par1;
 	int par2;
@@ -3711,9 +3796,9 @@
 								   info);
 							isdn_tty_at_cout("4;ADPCM;4;0;(8000)\r\n",
 								   info);
-							isdn_tty_at_cout("5;ALAW;8;0;(8000)",
+							isdn_tty_at_cout("5;ALAW;8;0;(8000)\r\n",
 								   info);
-							isdn_tty_at_cout("6;ULAW;8;0;(8000)",
+							isdn_tty_at_cout("6;ULAW;8;0;(8000)\r\n",
 								   info);
 							break;
 						default:
@@ -3752,6 +3837,52 @@
 			isdn_tty_modem_result(1, info);
 			return 0;
 			break;
+		case 7:
+			/* AT+VDD - DTMF detection */
+			switch (*p[0]) {
+				case '?':
+					p[0]++;
+					sprintf(rs, "\r\n<%d>,<%d>",
+						m->vpar[4],
+						m->vpar[5]);
+					isdn_tty_at_cout(rs, info);
+					break;
+				case '=':
+					p[0]++;
+					if ((*p[0]>='0') && (*p[0]<='9')) {
+						if (info->online != 1)
+							PARSE_ERROR1;
+						par1 = isdn_getnum(p);
+						if ((par1 < 0) || (par1 > 15))
+							PARSE_ERROR1;
+						if (*p[0] != ',')
+							PARSE_ERROR1;
+						p[0]++;
+						par2 = isdn_getnum(p);
+						if ((par2 < 0) || (par2 > 255))
+							PARSE_ERROR1;
+						m->vpar[4] = par1;
+						m->vpar[5] = par2;
+						cmd.driver = info->isdn_driver;
+						cmd.command = ISDN_CMD_AUDIO;
+						cmd.arg = info->isdn_channel + (ISDN_AUDIO_SETDD << 8);
+						cmd.parm.num[0] = par1;
+						cmd.parm.num[1] = par2;
+						isdn_command(&cmd);
+						break;
+					} else
+					if (*p[0] == '?') {
+						p[0]++;
+						isdn_tty_at_cout("\r\n<0-15>,<0-255>",
+							info);
+						break;
+					} else
+					PARSE_ERROR1;
+					break;
+				default:
+					PARSE_ERROR1;
+			}
+			break;
 		default:
 			PARSE_ERROR1;
 	}
@@ -3774,6 +3905,9 @@
 #endif
 	for (p = &m->mdmcmd[2]; *p;) {
 		switch (*p) {
+			case ' ':
+				p++;
+				break;
 			case 'A':
 				/* A - Accept incoming call */
 				p++;
@@ -3919,8 +4053,10 @@
 						isdn_tty_suspend(ds, info, m);
 						break;
 					case 'R':	/* RESUME */
+						p++;
 						isdn_tty_get_msnstr(ds, &p);
 						isdn_tty_resume(ds, info, m);
+						break;
 					case 'M':	/* MESSAGE */
 						p++;
 						isdn_tty_send_msg(info, m, p);
@@ -3981,7 +4117,7 @@
 				eb[1] = 0;
 				isdn_tty_at_cout(eb, info);
 			}
-			if (m->mdmcmdl >= 2)
+			if ((m->mdmcmdl >= 2) && (!(strncmp(m->mdmcmd, "AT", 2))))
 				isdn_tty_parse_at(info);
 			m->mdmcmdl = 0;
 			continue;
@@ -4007,15 +4143,16 @@
 				switch (m->mdmcmdl) {
 					case 0:
 						if (c == 'A')
-							m->mdmcmd[m->mdmcmdl++] = c;
+							m->mdmcmd[m->mdmcmdl] = c;
 						break;
 					case 1:
 						if (c == 'T')
-							m->mdmcmd[m->mdmcmdl++] = c;
+							m->mdmcmd[m->mdmcmdl] = c;
 						break;
 					default:
-						m->mdmcmd[m->mdmcmdl++] = c;
+						m->mdmcmd[m->mdmcmdl] = c;
 				}
+				m->mdmcmd[++m->mdmcmdl] = 0;
 			}
 		}
 	}
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/isdn_tty.h linux/drivers/isdn/isdn_tty.h
--- v2.3.13/linux/drivers/isdn/isdn_tty.h	Sun May 23 10:03:42 1999
+++ linux/drivers/isdn/isdn_tty.h	Sun Aug 15 11:49:08 1999
@@ -1,4 +1,4 @@
-/* $Id: isdn_tty.h,v 1.13 1999/04/12 12:33:46 fritz Exp $
+/* $Id: isdn_tty.h,v 1.15 1999/07/31 12:59:48 armin Exp $
 
  * header for Linux ISDN subsystem, tty related functions (linklevel).
  *
@@ -20,6 +20,20 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_tty.h,v $
+ * Revision 1.15  1999/07/31 12:59:48  armin
+ * Added tty fax capabilities.
+ *
+ * Revision 1.14  1999/07/11 17:14:15  armin
+ * Added new layer 2 and 3 protocols for Fax and DSP functions.
+ * Moved "Add CPN to RING message" to new register S23,
+ * "Display message" is now correct on register S13 bit 7.
+ * New audio command AT+VDD implemented (deactivate DTMF decoder and
+ * activate possible existing hardware/DSP decoder).
+ * Moved some tty defines to .h file.
+ * Made whitespace possible in AT command line.
+ * Some AT-emulator output bugfixes.
+ * First Fax G3 implementations.
+ *
  * Revision 1.13  1999/04/12 12:33:46  fritz
  * Changes from 2.0 tree.
  *
@@ -72,6 +86,69 @@
  *
  */
 
+#include <linux/config.h>
+
+#define DLE 0x10
+#define ETX 0x03
+#define DC4 0x14
+
+
+/*
+ * Definition of some special Registers of AT-Emulator
+ */
+#define REG_RINGATA   0
+#define REG_RINGCNT   1
+#define REG_ESC       2
+#define REG_CR        3
+#define REG_LF        4
+#define REG_BS        5
+
+#define REG_WAITC     7
+
+#define REG_RESP     12
+#define BIT_RESP      1
+#define REG_RESPNUM  12
+#define BIT_RESPNUM   2
+#define REG_ECHO     12
+#define BIT_ECHO      4
+#define REG_DCD      12
+#define BIT_DCD       8
+#define REG_CTS      12
+#define BIT_CTS      16
+#define REG_DTRR     12
+#define BIT_DTRR     32
+#define REG_DSR      12
+#define BIT_DSR      64
+#define REG_CPPP     12
+#define BIT_CPPP    128
+
+#define REG_T70      13
+#define BIT_T70       2
+#define BIT_T70_EXT  32
+#define REG_DTRHUP   13
+#define BIT_DTRHUP    4
+#define REG_RESPXT   13
+#define BIT_RESPXT    8
+#define REG_CIDONCE  13
+#define BIT_CIDONCE  16
+#define REG_RUNG     13
+#define BIT_RUNG     64
+#define REG_DISPLAY  13
+#define BIT_DISPLAY 128
+
+#define REG_L2PROT   14
+#define REG_L3PROT   15
+#define REG_PSIZE    16
+#define REG_WSIZE    17
+#define REG_SI1      18
+#define REG_SI2      19
+#define REG_SI1I     20
+#define REG_PLAN     21
+#define REG_SCREEN   22
+
+#define REG_CPN      23
+#define BIT_CPN       1
+
 extern void isdn_tty_modem_escape(void);
 extern void isdn_tty_modem_ring(void);
 extern void isdn_tty_carrier_timeout(void);
@@ -83,3 +160,10 @@
 extern int isdn_tty_stat_callback(int, isdn_ctrl *);
 extern int isdn_tty_rcv_skb(int, int, int, struct sk_buff *);
 extern int isdn_tty_capi_facility(capi_msg *cm); 
+extern void isdn_tty_at_cout(char *, modem_info *);
+extern void isdn_tty_modem_hup(modem_info *, int);
+#ifdef CONFIG_ISDN_TTY_FAX
+extern int isdn_tty_cmd_PLUSF_FAX(char **, modem_info *);
+extern int isdn_tty_fax_command(modem_info *);
+extern void isdn_tty_fax_bitorder(modem_info *, struct sk_buff *);
+#endif
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/isdn_ttyfax.c linux/drivers/isdn/isdn_ttyfax.c
--- v2.3.13/linux/drivers/isdn/isdn_ttyfax.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/isdn_ttyfax.c	Sun Aug 15 11:49:08 1999
@@ -0,0 +1,1200 @@
+/* $Id: isdn_ttyfax.c,v 1.2 1999/08/05 10:36:10 armin Exp $
+ * Linux ISDN subsystem, tty_fax AT-command emulator (linklevel).
+ *
+ * Copyright 1999    by Armin Schindler (mac@melware.de)
+ * Copyright 1999    by Ralf Spachmann (mel@melware.de)
+ * Copyright 1999    by Cytronics & Melware 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Log: isdn_ttyfax.c,v $
+ * Revision 1.2  1999/08/05 10:36:10  armin
+ * Bugfix: kernel oops on getting revision.
+ *
+ * Revision 1.1  1999/07/31 12:59:50  armin
+ * Added tty fax capabilities.
+ *
+ *
+ */
+
+#undef ISDN_TTY_FAX_STAT_DEBUG
+#undef ISDN_TTY_FAX_CMD_DEBUG
+
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/isdn.h>
+#include "isdn_common.h"
+#include "isdn_tty.h"
+#include "isdn_ttyfax.h"
+
+
+static char *isdn_tty_fax_revision = "$Revision: 1.2 $";
+
+#define PARSE_ERROR1 { isdn_tty_fax_modem_result(1, info); return 1; }
+
+static char *
+isdn_getrev(const char *revision)
+{
+        char *rev;
+        char *p;
+
+        if ((p = strchr(revision, ':'))) {
+                rev = p + 2;
+                p = strchr(rev, '$');
+                *--p = 0;
+        } else
+                rev = "???";
+        return rev;
+}
+
+
+/*
+ * Fax Class 2 Modem results
+ *
+ */
+static void isdn_tty_fax_modem_result(int code, modem_info * info)
+{
+	atemu *m = &info->emu;
+	T30_s *f = info->fax;
+	char rs[50];
+	char rss[50];
+	char *rp;
+	int i;
+	static char *msg[] =
+	{"OK", "ERROR", "+FCON", "+FCSI:", "+FDIS:",
+	 "+FHNG:", "+FDCS:", "CONNECT", "+FTSI:",
+	 "+FCFR", "+FPTS:", "+FET:" };
+
+
+	isdn_tty_at_cout("\r\n", info);
+	isdn_tty_at_cout(msg[code], info);
+
+#ifdef ISDN_TTY_FAX_CMD_DEBUG
+	printk(KERN_DEBUG "isdn_tty: Fax send %s on ttyI%d\n",
+		msg[code], info->line);
+#endif
+	switch (code) {
+		case 0: /* OK */
+			break;
+		case 1: /* ERROR */
+			break;
+		case 2:	/* +FCON */
+			/* Append CPN, if enabled */
+			if ((m->mdmreg[REG_CPN] & BIT_CPN) &&
+				(!(dev->usage[info->isdn_channel] & ISDN_USAGE_OUTGOING))) {
+				sprintf(rs, "/%s", m->cpn);
+				isdn_tty_at_cout(rs, info);
+			}
+			info->online = 1;
+			f->fet = 0;
+			if (f->phase == ISDN_FAX_PHASE_A)
+				f->phase = ISDN_FAX_PHASE_B;
+			break;
+		case 3:	/* +FCSI */
+		case 8:	/* +FTSI */
+			sprintf(rs, "\"%s\"", f->r_id);
+			isdn_tty_at_cout(rs, info); 
+			break;
+		case 4:	/* +FDIS */
+			rs[0] = 0;
+			rp = &f->r_resolution;
+			for(i = 0; i < 8; i++) {
+				sprintf(rss, "%c%s", rp[i] + 48,
+					(i < 7) ? "," : "");
+				strcat(rs, rss);
+			}
+			isdn_tty_at_cout(rs, info);
+#ifdef ISDN_TTY_FAX_CMD_DEBUG
+			printk(KERN_DEBUG "isdn_tty: Fax DIS=%s on ttyI%d\n",
+				rs, info->line);
+#endif
+			break;
+		case 5:	/* +FHNG */
+			sprintf(rs, "%d", f->code);
+			isdn_tty_at_cout(rs, info); 
+			info->faxonline = 0;
+			break;
+		case 6:	/* +FDCS */
+			rs[0] = 0;
+			rp = &f->r_resolution;
+			for(i = 0; i < 8; i++) {
+				sprintf(rss, "%c%s", rp[i] + 48,
+					(i < 7) ? "," : "");
+				strcat(rs, rss);
+			}
+			isdn_tty_at_cout(rs, info);
+#ifdef ISDN_TTY_FAX_CMD_DEBUG
+			printk(KERN_DEBUG "isdn_tty: Fax DCS=%s on ttyI%d\n",
+				rs, info->line);
+#endif
+			break;
+		case 7:	/* CONNECT */
+			info->faxonline |= 2;
+			break;
+		case 9: /* FCFR */
+			break;
+		case 10: /* FPTS */
+			isdn_tty_at_cout("1", info);
+			break;
+		case 11: /* FET */
+			sprintf(rs, "%d", f->fet);
+			isdn_tty_at_cout(rs, info); 
+			break;
+	}
+
+	isdn_tty_at_cout("\r\n", info);
+
+	switch (code) {
+		case 7: /* CONNECT */
+			info->online = 2;
+			if (info->faxonline & 1) {
+				sprintf(rs, "%c", XON);
+				isdn_tty_at_cout(rs, info); 
+			}
+			break;
+	}
+}
+
+int
+isdn_tty_fax_command(modem_info * info)
+{
+	T30_s *f = info->fax;
+	char rs[10];
+
+#ifdef ISDN_TTY_FAX_CMD_DEBUG
+	printk(KERN_DEBUG "isdn_tty: Fax cmd %d on ttyI%d\n",
+		f->r_code, info->line);
+#endif
+	switch(f->r_code) {
+		case ISDN_TTY_FAX_FCON:
+			info->faxonline = 1;
+			isdn_tty_fax_modem_result(2, info); /* +FCON */
+			return(0);
+		case ISDN_TTY_FAX_FCON_I:
+			info->faxonline = 16;
+			isdn_tty_fax_modem_result(2, info); /* +FCON */
+			return(0);
+		case ISDN_TTY_FAX_RID:
+			if (info->faxonline & 1)
+				isdn_tty_fax_modem_result(3, info); /* +FCSI */
+			if (info->faxonline & 16)
+				isdn_tty_fax_modem_result(8, info); /* +FTSI */
+			return(0);
+		case ISDN_TTY_FAX_DIS:
+			isdn_tty_fax_modem_result(4, info); /* +FDIS */
+			return(0);
+		case ISDN_TTY_FAX_HNG:
+			if (f->phase == ISDN_FAX_PHASE_C) {
+				if (f->direction == ISDN_TTY_FAX_CONN_IN) {
+					sprintf(rs, "%c%c", DLE, ETX);
+					isdn_tty_at_cout(rs, info); 
+				} else {
+					sprintf(rs, "%c", 0x18);
+					isdn_tty_at_cout(rs, info); 
+				}
+				info->faxonline &= ~2; /* leave data mode */
+				info->online = 1;
+			}
+			f->phase = ISDN_FAX_PHASE_E;
+			isdn_tty_fax_modem_result(5, info); /* +FHNG */
+			isdn_tty_fax_modem_result(0, info); /* OK */
+			return(0);
+		case ISDN_TTY_FAX_DCS:
+			isdn_tty_fax_modem_result(6, info); /* +FDCS */
+			isdn_tty_fax_modem_result(7, info); /* CONNECT */
+			f->phase = ISDN_FAX_PHASE_C;
+			return(0);
+		case ISDN_TTY_FAX_TRAIN_OK:
+			isdn_tty_fax_modem_result(6, info); /* +FDCS */
+			isdn_tty_fax_modem_result(0, info); /* OK */
+			return(0);
+		case ISDN_TTY_FAX_SENT:
+			isdn_tty_fax_modem_result(0, info); /* OK */
+			return(0);
+		case ISDN_TTY_FAX_CFR:
+			isdn_tty_fax_modem_result(9, info); /* +FCFR */
+			return(0);
+		case ISDN_TTY_FAX_ET:
+			sprintf(rs, "%c%c", DLE, ETX);
+			isdn_tty_at_cout(rs, info); 
+			isdn_tty_fax_modem_result(10, info); /* +FPTS */
+			isdn_tty_fax_modem_result(11, info); /* +FET */
+			isdn_tty_fax_modem_result(0, info); /* OK */
+			info->faxonline &= ~2; /* leave data mode */
+			info->online = 1;
+			f->phase = ISDN_FAX_PHASE_D;
+			return(0);
+		case ISDN_TTY_FAX_PTS:
+			isdn_tty_fax_modem_result(10, info); /* +FPTS */
+			if (f->direction == ISDN_TTY_FAX_CONN_OUT) {
+				if (f->fet == 1)
+					f->phase = ISDN_FAX_PHASE_B;
+				if (f->fet == 0)
+					isdn_tty_fax_modem_result(0, info); /* OK */
+			}
+			return(0);
+		case ISDN_TTY_FAX_EOP:
+			info->faxonline &= ~2; /* leave data mode */
+			info->online = 1;
+			f->phase = ISDN_FAX_PHASE_D;
+			return(0);
+
+	}
+	return(-1);
+}
+
+
+void
+isdn_tty_fax_bitorder(modem_info *info, struct sk_buff *skb)
+{
+	__u8 LeftMask;
+	__u8 RightMask;
+	__u8 fBit;
+	__u8 Data;
+	int i;
+
+	if (!info->fax->bor) {
+		for(i = 0; i < skb->len; i++) {
+			Data = skb->data[i];
+			for (
+				LeftMask = 0x80, RightMask = 0x01;
+				LeftMask > RightMask;
+				LeftMask >>= 1, RightMask <<= 1
+			) {
+				fBit = (Data & LeftMask);
+				if (Data & RightMask)
+					Data |= LeftMask;
+				else
+					Data &= ~LeftMask;
+				if (fBit)
+					Data |= RightMask;
+				else
+					Data &= ~RightMask;
+
+			}
+			skb->data[i] = Data;
+		}
+	}
+}
+
+/*
+ * Parse AT+F.. FAX class 2 commands
+ */
+
+int isdn_tty_cmd_PLUSF_FAX(char **p, modem_info * info)
+{
+	atemu *m = &info->emu;
+	T30_s *f = info->fax;
+	isdn_ctrl cmd;
+	int par;
+	char rs[50];
+	char rss[50];
+	int maxdccval[]={1,5,2,2,3,2,0,7};
+
+	/* FAA still unchanged */
+        if (!strncmp(p[0], "AA", 2)) { /* TODO */
+		p[0] += 2;
+		switch (*p[0]) {
+			case '?':
+				p[0]++;
+				sprintf(rs, "\r\n%d", 0);
+				isdn_tty_at_cout(rs, info);
+				break;
+			case '=':
+				p[0]++;
+				par = isdn_getnum(p);
+				if ((par < 0) || (par > 255))
+					PARSE_ERROR1;
+				break;
+			default:
+				PARSE_ERROR1;
+		}
+		return 0;
+       }
+
+	/* BADLIN=value - dummy 0=disable errorchk disabled, 1-255 nr. of lines for making page bad */
+        if (!strncmp(p[0], "BADLIN", 6)) {
+            p[0] += 6;
+		switch (*p[0]) {
+			case '?':
+				p[0]++;
+                                sprintf(rs, "\r\n%d",f->badlin);
+                                isdn_tty_at_cout(rs, info);
+				break;
+			case '=':
+                                p[0]++;
+                                if (*p[0] == '?')
+                                {
+                                     p[0]++;
+                                     sprintf(rs, "\r\n0-255");
+                       		     isdn_tty_at_cout(rs, info);
+                                    }
+                                    else
+                                    {
+                                        par = isdn_getnum(p);
+                                        if ((par < 0) || (par > 255))
+                                            PARSE_ERROR1;
+                                        f->badlin = par;
+#ifdef ISDN_TTY_FAX_STAT_DEBUG
+                                        printk(KERN_DEBUG "isdn_tty: Fax FBADLIN=%d\n", par);
+#endif
+                                    }
+                                break;
+			default:
+			        PARSE_ERROR1;
+		}
+                return 0;
+        }
+
+	/* BADMUL=value - dummy 0=disable errorchk disabled (treshold multiplier) */
+        if (!strncmp(p[0], "BADMUL", 6)){
+            p[0] +=6;
+		switch (*p[0]) {
+			case '?':
+				p[0]++;
+                                sprintf(rs, "\r\n%d", f->badmul);
+                                isdn_tty_at_cout(rs, info);
+				break;
+			case '=':
+                                p[0]++;
+                                if (*p[0] == '?')
+                                    {
+                                     p[0]++;
+                                     sprintf(rs, "\r\n0-255");
+                       		     isdn_tty_at_cout(rs, info);
+                                    }
+                                    else
+                                    {
+                                        par = isdn_getnum(p);
+                                        if ((par < 0) || (par > 255))
+                                            PARSE_ERROR1;
+                                        f->badmul = par;
+#ifdef ISDN_TTY_FAX_STAT_DEBUG
+                                        printk(KERN_DEBUG "isdn_tty: Fax FBADMUL=%d\n", par);
+#endif
+                                    }
+                                    break;
+			default:
+				PARSE_ERROR1;
+		}
+                return 0;
+        }
+
+	/* BOR=n - Phase C bit order, 0=direct, 1=reverse */
+        if (!strncmp(p[0], "BOR", 3)){
+            p[0] +=3;
+		switch (*p[0]) {
+			case '?':
+				p[0]++;
+                                sprintf(rs, "\r\n%d", f->bor);
+                                isdn_tty_at_cout(rs, info);
+				break;
+			case '=':
+                                p[0]++;
+                                if (*p[0] == '?')
+                                    {
+                                     p[0]++;
+                                     sprintf(rs, "\r\n0,1");
+                       		     isdn_tty_at_cout(rs, info);
+                                    }
+                                    else
+                                    {
+                                        par = isdn_getnum(p);
+                                        if ((par < 0) || (par > 1))
+                                            PARSE_ERROR1;
+                                        f->bor = par;
+#ifdef ISDN_TTY_FAX_STAT_DEBUG
+                                        printk(KERN_DEBUG "isdn_tty: Fax FBOR=%d\n", par);
+#endif
+                                    }
+                                break;
+                        default:
+                                PARSE_ERROR1;
+                                }
+                       return 0;
+        }
+
+	/* NBC=n - No Best Capabilities */
+        if (!strncmp(p[0], "NBC", 3)){
+            p[0] +=3;
+		switch (*p[0]) {
+			case '?':
+				p[0]++;
+                                sprintf(rs, "\r\n%d", f->nbc);
+                                isdn_tty_at_cout(rs, info);
+				break;
+			case '=':
+                                p[0]++;
+                                if (*p[0] == '?')
+                                    {
+                                     p[0]++;
+                                     sprintf(rs, "\r\n0,1");
+                       		     isdn_tty_at_cout(rs, info);
+                                    }
+                                    else
+                                    {
+                                        par = isdn_getnum(p);
+                                        if ((par < 0) || (par > 1))
+                                            PARSE_ERROR1;
+                                        f->nbc = par;
+#ifdef ISDN_TTY_FAX_STAT_DEBUG
+                                        printk(KERN_DEBUG "isdn_tty: Fax FNBC=%d\n", par);
+#endif
+                                    }
+                                break;
+                        default:
+                                PARSE_ERROR1;
+                                }
+                       return 0;
+        }
+
+	/* BUF? - Readonly buffersize readout  */
+        if (!strncmp(p[0], "BUF?", 4)) {
+                p[0] += 4;
+#ifdef ISDN_TTY_FAX_STAT_DEBUG
+                printk(KERN_DEBUG "isdn_tty: Fax FBUF? (%d) \n", (16 * m->mdmreg[REG_PSIZE]));
+#endif
+                                p[0]++;
+                                 sprintf(rs, "\r\n %d ", (16 * m->mdmreg[REG_PSIZE]));
+                                isdn_tty_at_cout(rs, info);
+                return 0;
+        }
+        
+	/* CIG=string - local fax station id string for polling rx */
+        if (!strncmp(p[0], "CIG", 3)) {
+		int i, r;
+                p[0] += 3;
+		switch (*p[0]) {
+			case '?':
+				p[0]++;
+				sprintf(rs, "\r\n\"%s\"", f->pollid);
+                                isdn_tty_at_cout(rs, info);
+                                break;
+			case '=':
+                                p[0]++;
+                                if (*p[0] == '?')
+                                    {
+                                     p[0]++;
+                                     sprintf(rs, "\r\n\"STRING\"");
+                       		     isdn_tty_at_cout(rs, info);
+                                    }
+                                    else
+                                    {
+                                        if (*p[0] =='"')
+                                            p[0]++;
+                                        for(i=0; (*p[0]) && i < (FAXIDLEN-1) && (*p[0] != '"'); i++)
+                                        {
+                                            f->pollid[i] = *p[0]++;
+                                        }
+                                        if (*p[0] =='"')
+                                            p[0]++;
+                                        for(r=i; r < FAXIDLEN; r++)
+                                        {
+                                        	f->pollid[r] = 32;
+                                        }
+                                        f->pollid[FAXIDLEN-1] = 0;
+#ifdef ISDN_TTY_FAX_STAT_DEBUG
+                                       printk(KERN_DEBUG "isdn_tty: Fax local poll ID rx \"%s\"\n", f->pollid);
+#endif
+                                    }
+                                break;
+			default:
+				PARSE_ERROR1;
+		}
+                return 0;
+        }
+
+	/* CQ=n - copy qlty chk, 0= no chk, 1=only 1D chk, 2=1D+2D chk */
+        if (!strncmp(p[0], "CQ", 2)) {
+                p[0] += 2;
+		switch (*p[0]) {
+			case '?':
+				p[0]++;
+                                sprintf(rs, "\r\n%d", f->cq);
+                                isdn_tty_at_cout(rs, info);
+				break;
+			case '=':
+                                p[0]++;
+                                if (*p[0] == '?')
+                                    {
+                                     p[0]++;
+                                     sprintf(rs, "\r\n0,1,2");
+                       		     isdn_tty_at_cout(rs, info);
+                                    }
+                                    else
+                                    {
+                                        par = isdn_getnum(p);
+                                        if ((par < 0) || (par > 2))
+                                            PARSE_ERROR1;
+                                        f->cq = par;
+#ifdef ISDN_TTY_FAX_STAT_DEBUG
+                                        printk(KERN_DEBUG "isdn_tty: Fax FCQ=%d\n", par);
+#endif
+                                    }
+                                    break;
+			default:
+				PARSE_ERROR1;
+		}
+                return 0;
+        }
+
+	/* CR=n - can receive? 0= no data rx or poll remote dev, 1=do receive data or poll remote dev */
+        if (!strncmp(p[0], "CR", 2)) {
+                p[0] += 2;
+		switch (*p[0]) {
+			case '?':
+				p[0]++;
+                                sprintf(rs, "\r\n%d", f->cr); /* read actual value from struct and print */
+                                isdn_tty_at_cout(rs, info);
+				break;
+			case '=':
+                                p[0]++;
+                                if (*p[0] == '?')
+                                    {
+                                     p[0]++;
+                                     sprintf(rs, "\r\n0,1"); /* display online help */
+                       		     isdn_tty_at_cout(rs, info);
+                                    }
+                                    else
+                                    {
+                                        par = isdn_getnum(p);
+                                        if ((par < 0) || (par > 1))
+                                            PARSE_ERROR1;
+                                        f->cr = par;
+#ifdef ISDN_TTY_FAX_STAT_DEBUG
+                                        printk(KERN_DEBUG "isdn_tty: Fax FCR=%d\n", par);
+#endif
+                                    }
+                                    break;
+			default:
+				PARSE_ERROR1;
+		}
+                return 0;
+        }
+
+	/* CTCRTY=value - ECM retry count */
+        if (!strncmp(p[0], "CTCRTY", 6)){
+            p[0] +=6;
+		switch (*p[0]) {
+			case '?':
+				p[0]++;
+                                sprintf(rs, "\r\n%d",f->ctcrty);
+                                isdn_tty_at_cout(rs, info);
+				break;
+			case '=':
+                                p[0]++;
+                                if (*p[0] == '?')
+                                    {
+                                     p[0]++;
+                                     sprintf(rs, "\r\n0-255");
+                       		     isdn_tty_at_cout(rs, info);
+                                    }
+                                    else
+                                    {
+                                        par = isdn_getnum(p);
+                                        if ((par < 0) || (par > 255))
+                                            PARSE_ERROR1;
+                                        f->ctcrty = par;
+#ifdef ISDN_TTY_FAX_STAT_DEBUG
+                                        printk(KERN_DEBUG "isdn_tty: Fax FCTCRTY=%d\n", par);
+#endif
+                                    }
+                                    break;
+			default:
+				PARSE_ERROR1;
+		}
+                return 0;
+        }
+
+	/* DCC=vr,br,wd,ln,df,ec,bf,st - DCE capabilities parms */
+        if (!strncmp(p[0], "DCC", 3)) {
+		char *rp = &f->resolution;
+		int i;
+
+                p[0] += 3;
+		switch(*p[0]) {
+			case '?':
+				p[0]++;
+	                        strcpy(rs, "\r\n");
+	                        for(i = 0; i < 8; i++) {
+        	                        sprintf(rss, "%c%s", rp[i] + 48,
+                	                        (i < 7) ? "," : "");
+                        	        strcat(rs, rss);
+	                        }
+        	                isdn_tty_at_cout(rs, info);
+				break;
+			case '=':
+                                p[0]++;
+		                if (*p[0] == '?') {
+					isdn_tty_at_cout("\r\n(0,1),(0-5),(0-2),(0-2),(0-3),(0-2),(0),(0-7)",info);
+                                	p[0]++;
+		                } else {
+					for (i=0; (((*p[0]>='0')&&(*p[0]<='9'))||(*p[0]==','))&&(i<8); i++) {
+						if (*p[0] != ',') {
+							if ((*p[0] - 48) > maxdccval[i]) {
+								PARSE_ERROR1;
+							}
+							rp[i] = *p[0] - 48;
+							p[0]++;
+							if (*p[0] == ',') 
+								p[0]++;
+						} else p[0]++;
+					}
+#ifdef ISDN_TTY_FAX_STAT_DEBUG
+				printk(KERN_DEBUG "isdn_tty: Fax FDCC capabilities DCE=%d,%d,%d,%d,%d,%d,%d,%d\n",
+				       rp[0], rp[1], rp[2], rp[3], rp[4], rp[5], rp[6], rp[7]);
+#endif
+        		        }
+				break;
+			default:
+				PARSE_ERROR1;
+		}
+                return 0;
+        }
+       
+	/* DIS=vr,br,wd,ln,df,ec,bf,st - current session parms */
+        if (!strncmp(p[0], "DIS", 3)) {
+		char *rp = &f->resolution;
+		int i;
+
+                p[0] += 3;
+		switch(*p[0]) {
+			case '?':
+				p[0]++;
+	                        strcpy(rs, "\r\n");
+	                        for(i = 0; i < 8; i++) {
+        	                        sprintf(rss, "%c%s", rp[i] + 48,
+                	                        (i < 7) ? "," : "");
+                        	        strcat(rs, rss);
+	                        }
+        	                isdn_tty_at_cout(rs, info);
+				break;
+			case '=':
+                                p[0]++;
+		                if (*p[0] == '?') {
+					isdn_tty_at_cout("\r\n(0,1),(0-5),(0-2),(0-2),(0-3),(0-2),(0),(0-7)",info);
+                                	p[0]++;
+		                } else {
+					for (i=0; (((*p[0]>='0')&&(*p[0]<='9'))||(*p[0]==','))&&(i<8); i++) {
+						if (*p[0] != ',') {
+							if ((*p[0] - 48) > maxdccval[i]) {
+								PARSE_ERROR1;
+							}
+							rp[i] = *p[0] - 48;
+							p[0]++;
+							if (*p[0] == ',') 
+								p[0]++;
+						} else p[0]++;
+					}
+#ifdef ISDN_TTY_FAX_STAT_DEBUG
+				printk(KERN_DEBUG "isdn_tty: Fax FDIS session parms=%d,%d,%d,%d,%d,%d,%d,%d\n",
+				       rp[0], rp[1], rp[2], rp[3], rp[4], rp[5], rp[6], rp[7]);
+#endif
+        		        }
+				break;
+			default:
+				PARSE_ERROR1;
+		}
+                return 0;
+        }
+       
+	/* DR - Receive Phase C data command, initiates document reception */ 
+        if (!strncmp(p[0], "DR", 2)) {
+                p[0] += 2;
+		if ((info->faxonline & 16) &&	/* incoming connection */
+   		   ((f->phase == ISDN_FAX_PHASE_B) || (f->phase == ISDN_FAX_PHASE_D))) {
+#ifdef ISDN_TTY_FAX_STAT_DEBUG
+			printk(KERN_DEBUG "isdn_tty: Fax FDR\n");
+#endif
+			f->code = ISDN_TTY_FAX_DR;
+			cmd.driver = info->isdn_driver;
+			cmd.arg = info->isdn_channel;
+			cmd.command = ISDN_CMD_FAXCMD;
+			isdn_command(&cmd);
+			if (f->phase == ISDN_FAX_PHASE_B) {
+				f->phase = ISDN_FAX_PHASE_C;
+			} else if (f->phase == ISDN_FAX_PHASE_D) { 
+				switch(f->fet) {
+					case 0:	/* next page will be received */
+						f->phase = ISDN_FAX_PHASE_C;
+						isdn_tty_fax_modem_result(7, info); /* CONNECT */
+						break;
+					case 1:	/* next doc will be received */
+						f->phase = ISDN_FAX_PHASE_B;
+						break;
+					case 2:	/* fax session is terminating */
+						f->phase = ISDN_FAX_PHASE_E;
+						break;
+					default:	
+						PARSE_ERROR1;
+				}
+			}
+		} else {
+			PARSE_ERROR1;
+		}
+                return 1;
+	}
+ 
+	/* DT=df,vr,wd,ln - TX phase C data command (release DCE to proceed with negotiation) */
+        if (!strncmp(p[0], "DT", 2)) {
+		int i, val[]={4,0,2,3};
+		char *rp = &f->resolution;
+
+                p[0] += 2;
+		if (!info->faxonline & 1) 	/* not outgoing connection */
+			PARSE_ERROR1;
+
+		for (i=0; (((*p[0]>='0')&&(*p[0]<='9'))||(*p[0]==','))&&(i<4); i++) {
+			if (*p[0] != ',') {
+				if ((*p[0] - 48) > maxdccval[val[i]]) {
+					PARSE_ERROR1;
+				}
+				rp[val[i]] = *p[0] - 48;
+				p[0]++;
+				if (*p[0] == ',') 
+					p[0]++;
+			} else p[0]++;
+		}
+#ifdef ISDN_TTY_FAX_STAT_DEBUG
+		printk(KERN_DEBUG "isdn_tty: Fax FDT tx data command parms=%d,%d,%d,%d\n",
+		       rp[4], rp[0], rp[2], rp[3]);
+#endif
+		if ((f->phase == ISDN_FAX_PHASE_B) || (f->phase == ISDN_FAX_PHASE_D)) {
+			f->code = ISDN_TTY_FAX_DT;
+			cmd.driver = info->isdn_driver;
+			cmd.arg = info->isdn_channel;
+			cmd.command = ISDN_CMD_FAXCMD;
+			isdn_command(&cmd);
+			if (f->phase == ISDN_FAX_PHASE_D) {
+				f->phase = ISDN_FAX_PHASE_C;
+				isdn_tty_fax_modem_result(7, info); /* CONNECT */
+			}
+		} else {
+			PARSE_ERROR1;
+		}
+                return 1;
+        }
+
+	/* ECM=n - Error mode control 0=disabled, 2=enabled, handled by DCE alone incl. buff of partial pages */
+        if (!strncmp(p[0], "ECM", 3)) {
+                p[0] += 3;
+		switch (*p[0]) {
+			case '?':
+				p[0]++;
+                                sprintf(rs, "\r\n%d",f->ecm);
+                                isdn_tty_at_cout(rs, info);
+				break;
+			case '=':
+                                p[0]++;
+                                if (*p[0] == '?')
+                                    {
+                                     p[0]++;
+                                     sprintf(rs, "\r\n0,2");
+                       		     isdn_tty_at_cout(rs, info);
+                                    }
+                                    else
+                                    {
+                                        par = isdn_getnum(p);
+                                        if ((par != 0) && (par != 2))
+                                            PARSE_ERROR1;
+                                        f->ecm = par;
+#ifdef ISDN_TTY_FAX_STAT_DEBUG
+                                        printk(KERN_DEBUG "isdn_tty: Fax FECM=%d\n", par);
+#endif
+                                    }
+                                    break;
+			default:
+				PARSE_ERROR1;
+		}
+                return 0;
+        }
+
+	/* ET=n - End of page or document */
+	if (!strncmp(p[0], "ET=", 3)) {
+		p[0] += 3;
+		if (*p[0] == '?') {
+			p[0]++;
+			sprintf(rs, "\r\n0-2");
+			isdn_tty_at_cout(rs, info);
+		} else {
+			if ((f->phase != ISDN_FAX_PHASE_D) || (!info->faxonline & 1))
+				PARSE_ERROR1;
+			par = isdn_getnum(p);
+			if ((par < 0) || (par > 2))
+				PARSE_ERROR1;
+			f->fet = par;
+			f->code = ISDN_TTY_FAX_ET;
+			cmd.driver = info->isdn_driver;
+			cmd.arg = info->isdn_channel;
+			cmd.command = ISDN_CMD_FAXCMD;
+			isdn_command(&cmd);
+#ifdef ISDN_TTY_FAX_STAT_DEBUG
+			printk(KERN_DEBUG "isdn_tty: Fax FET=%d\n", par);
+#endif
+			return 1;
+		}
+		return 0;
+	}
+
+	/* K - terminate */
+	if (!strncmp(p[0], "K", 1)) {
+		p[0] += 1;
+		if ((f->phase == ISDN_FAX_PHASE_IDLE) || (f->phase == ISDN_FAX_PHASE_E))
+			PARSE_ERROR1;
+		isdn_tty_modem_hup(info, 1);
+		return 1;
+	}
+
+	/* LID=string - local fax ID */
+        if (!strncmp(p[0], "LID", 3)) {
+		int i, r;
+                p[0] += 3;
+		switch (*p[0]) {
+			case '?':
+				p[0]++;
+				sprintf(rs, "\r\n\"%s\"", f->id);
+                                isdn_tty_at_cout(rs, info);
+                                break;
+			case '=':
+                                p[0]++;
+                                if (*p[0] == '?')
+                                    {
+                                     p[0]++;
+                                     sprintf(rs, "\r\n\"STRING\"");
+                       		     isdn_tty_at_cout(rs, info);
+                                    }
+                                    else
+                                    {
+                                        if (*p[0] =='"')
+                                            p[0]++;
+                                        for(i=0; (*p[0]) && i < (FAXIDLEN-1) && (*p[0] != '"'); i++)
+                                        {
+                                            f->id[i] = *p[0]++;
+                                        }
+                                        if (*p[0] =='"')
+                                            p[0]++;
+                                        for(r=i; r < FAXIDLEN; r++)
+                                        {
+                                        	f->id[r] = 32;
+                                        }
+                                        f->id[FAXIDLEN-1] = 0;
+#ifdef ISDN_TTY_FAX_STAT_DEBUG
+                                       printk(KERN_DEBUG "isdn_tty: Fax local ID \"%s\"\n", f->id);
+#endif
+                                    }
+                                break;
+			default:
+				PARSE_ERROR1;
+		}
+                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)) {
+                p[0] += 4;
+#ifdef ISDN_TTY_FAX_STAT_DEBUG
+                printk(KERN_DEBUG "isdn_tty: FMDL?\n");
+#endif
+                isdn_tty_at_cout("\r\nisdn4linux", info);
+                return 0;
+        }
+
+	/* MFR? - DCE Manufacturer */
+        if (!strncmp(p[0], "MFR?", 4)) {
+                p[0] += 4;
+#ifdef ISDN_TTY_FAX_STAT_DEBUG
+                printk(KERN_DEBUG "isdn_tty: FMFR?\n");
+#endif
+                isdn_tty_at_cout("\r\nisdn4linux", info);
+                return 0;
+        }
+
+	/* MINSP=n - Minimum Speed for Phase C */
+        if (!strncmp(p[0], "MINSP", 5)) {
+                p[0] += 5;
+		switch (*p[0]) {
+			case '?':
+				p[0]++;
+                                sprintf(rs, "\r\n%d",f->minsp);
+                                isdn_tty_at_cout(rs, info);
+				break;
+			case '=':
+                                p[0]++;
+                                if (*p[0] == '?')
+                                    {
+                                     p[0]++;
+                                     sprintf(rs, "\r\n0-5");
+                       		     isdn_tty_at_cout(rs, info);
+                                    }
+                                    else
+                                    {
+                                        par = isdn_getnum(p);
+                                        if ((par < 0) || (par > 5))
+                                            PARSE_ERROR1;
+                                        f->minsp = par;
+#ifdef ISDN_TTY_FAX_STAT_DEBUG
+                                        printk(KERN_DEBUG "isdn_tty: Fax FMINSP=%d\n", par);
+#endif
+                                    }
+                                    break;
+			default:
+				PARSE_ERROR1;
+		}
+                return 0;
+        }
+
+	/* PHCTO=value - DTE phase C timeout */
+        if (!strncmp(p[0], "PHCTO", 5)){
+            p[0] +=5;
+		switch (*p[0]) {
+			case '?':
+				p[0]++;
+                                sprintf(rs, "\r\n%d",f->phcto);
+                                isdn_tty_at_cout(rs, info);
+				break;
+			case '=':
+                                p[0]++;
+                                if (*p[0] == '?')
+                                    {
+                                     p[0]++;
+                                     sprintf(rs, "\r\n0-255");
+                       		     isdn_tty_at_cout(rs, info);
+                                    }
+                                    else
+                                    {
+                                        par = isdn_getnum(p);
+                                        if ((par < 0) || (par > 255))
+                                            PARSE_ERROR1;
+                                        f->phcto = par;
+#ifdef ISDN_TTY_FAX_STAT_DEBUG
+                                        printk(KERN_DEBUG "isdn_tty: Fax FPHCTO=%d\n", par);
+#endif
+                                    }
+                                    break;
+			default:
+				PARSE_ERROR1;
+		}
+                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)) {
+                p[0] += 3;
+		switch (*p[0]) {
+			case '?':
+				p[0]++;
+                                sprintf(rs, "\r\n%d",f->rel);
+                                isdn_tty_at_cout(rs, info);
+				break;
+			case '=':
+                                p[0]++;
+                                if (*p[0] == '?')
+                                    {
+                                     p[0]++;
+                                     sprintf(rs, "\r\n0,1");
+                       		     isdn_tty_at_cout(rs, info);
+                                    }
+                                    else
+                                    {
+                                        par = isdn_getnum(p);
+                                        if ((par < 0) || (par > 1))
+                                            PARSE_ERROR1;
+                                        f->rel = par;
+#ifdef ISDN_TTY_FAX_STAT_DEBUG
+                                        printk(KERN_DEBUG "isdn_tty: Fax FREL=%d\n", par);
+#endif
+                                    }
+                                    break;
+			default:
+				PARSE_ERROR1;
+		}
+                return 0;
+        }
+
+	/* REV? - DCE Revision */
+        if (!strncmp(p[0], "REV?", 4)) {
+                p[0] += 4;
+#ifdef ISDN_TTY_FAX_STAT_DEBUG
+                printk(KERN_DEBUG "isdn_tty: FREV?\n");
+#endif
+		strcpy(rss, isdn_tty_fax_revision);
+		sprintf(rs, "\r\nRev: %s", isdn_getrev(rss));
+                isdn_tty_at_cout(rs, info);
+                return 0;
+        }
+
+#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 */
+		p[0] += 4;
+#ifdef ISDN_TTY_FAX_STAT_DEBUG
+                printk(KERN_DEBUG "isdn_tty: Fax FTBC=%c\n", *p[0]);
+#endif
+                switch (*p[0]) {
+                        case '0':
+                                p[0]++;
+                                break;
+                        default:
+                                PARSE_ERROR1;
+                }
+                return 0;
+	}
+
+        printk(KERN_DEBUG "isdn_tty: unknown token=>AT+F%s<\n", p[0]);
+	PARSE_ERROR1;
+}
+
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/isdn_ttyfax.h linux/drivers/isdn/isdn_ttyfax.h
--- v2.3.13/linux/drivers/isdn/isdn_ttyfax.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/isdn_ttyfax.h	Thu Aug 12 09:42:33 1999
@@ -0,0 +1,33 @@
+/* $Id: isdn_ttyfax.h,v 1.1 1999/07/31 12:59:51 armin Exp $
+ * header for Linux ISDN subsystem, tty_fax related functions (linklevel).
+ *
+ * Copyright 1999   by Armin Schindler (mac@melware.de)
+ * Copyright 1999   by Ralf Spachmann (mel@melware.de)
+ * Copyright 1999   by Cytronics & Melware
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Log: isdn_ttyfax.h,v $
+ * Revision 1.1  1999/07/31 12:59:51  armin
+ * Added tty fax capabilities.
+ *
+ *
+ */
+
+
+#define XON	0x11
+#define XOFF	0x13
+#define DC2	0x12
+
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/isdn_x25iface.c linux/drivers/isdn/isdn_x25iface.c
--- v2.3.13/linux/drivers/isdn/isdn_x25iface.c	Sun May 23 10:03:42 1999
+++ linux/drivers/isdn/isdn_x25iface.c	Wed Aug 18 11:38:57 1999
@@ -57,7 +57,7 @@
 void isdn_x25iface_proto_del( struct concap_proto * );
 int isdn_x25iface_proto_close( struct concap_proto * );
 int isdn_x25iface_proto_restart( struct concap_proto *,
-				 struct device *,
+				 struct net_device *,
 				 struct concap_device_ops *);
 int isdn_x25iface_xmit( struct concap_proto *, struct sk_buff * );
 int isdn_x25iface_receive( struct concap_proto *, struct sk_buff * );
@@ -175,7 +175,7 @@
 /* (re-)initialize the data structures for x25iface encapsulation
  */
 int isdn_x25iface_proto_restart(struct concap_proto *cprot,
-				struct device *ndev, 
+				struct net_device *ndev, 
 				struct concap_device_ops *dops)
 {
 	ix25_pdata_t * pda = cprot -> proto_data ;
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/pcbit/drv.c linux/drivers/isdn/pcbit/drv.c
--- v2.3.13/linux/drivers/isdn/pcbit/drv.c	Sun May 23 10:03:42 1999
+++ linux/drivers/isdn/pcbit/drv.c	Thu Aug 12 09:42:33 1999
@@ -86,7 +86,7 @@
 
 	dev_pcbit[board] = dev;
 	memset(dev, 0, sizeof(struct pcbit_dev));
-#if LINUX_VERSION_CODE >= 131841
+#ifdef COMPAT_HAS_NEW_WAITQ
 	init_waitqueue_head(&dev->set_running_wq);
 #endif
 
diff -u --recursive --new-file v2.3.13/linux/drivers/isdn/pcbit/pcbit.h linux/drivers/isdn/pcbit/pcbit.h
--- v2.3.13/linux/drivers/isdn/pcbit/pcbit.h	Sun May 23 10:03:42 1999
+++ linux/drivers/isdn/pcbit/pcbit.h	Thu Aug 12 09:42:33 1999
@@ -68,10 +68,10 @@
 	struct frame_buf *write_queue;
 
 	/* Protocol start */
-#if LINUX_VERSION_CODE < 131841
-	struct wait_queue *set_running_wq;
-#else
+#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;
 
diff -u --recursive --new-file v2.3.13/linux/drivers/macintosh/mac_keyb.c linux/drivers/macintosh/mac_keyb.c
--- v2.3.13/linux/drivers/macintosh/mac_keyb.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/macintosh/mac_keyb.c	Thu Aug 12 11:50:14 1999
@@ -44,7 +44,6 @@
 #include <asm/adb.h>
 #include <asm/cuda.h>
 #include <asm/pmu.h>
-#include <linux/init.h>
 
 #include <linux/kbd_kern.h>
 #include <linux/kbd_ll.h>
diff -u --recursive --new-file v2.3.13/linux/drivers/macintosh/macserial.c linux/drivers/macintosh/macserial.c
--- v2.3.13/linux/drivers/macintosh/macserial.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/macintosh/macserial.c	Thu Aug 12 11:50:14 1999
@@ -39,7 +39,6 @@
 #ifdef CONFIG_KGDB
 #include <asm/kgdb.h>
 #endif
-#include <linux/init.h>
 
 #include "macserial.h"
 
diff -u --recursive --new-file v2.3.13/linux/drivers/misc/Config.in linux/drivers/misc/Config.in
--- v2.3.13/linux/drivers/misc/Config.in	Wed Dec 31 16:00:00 1969
+++ linux/drivers/misc/Config.in	Mon Aug  9 15:06:52 1999
@@ -0,0 +1,12 @@
+#
+# Misc strange devices
+#
+mainmenu_option next_comment
+comment 'Misc devices'
+
+# PIIX4 ACPI requires PCI for setup and a hardcoded TSC for timing
+if [ "$CONFIG_PCI" = "y" -a "$CONFIG_X86_TSC" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
+  bool 'PIIX4 ACPI support' CONFIG_PIIX4_ACPI
+fi
+
+endmenu
diff -u --recursive --new-file v2.3.13/linux/drivers/misc/Makefile linux/drivers/misc/Makefile
--- v2.3.13/linux/drivers/misc/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/drivers/misc/Makefile	Mon Aug  9 14:12:48 1999
@@ -0,0 +1,27 @@
+#
+# Makefile for misc devices that really don't fit anywhere else.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now inherited from the
+# parent makes..
+#
+
+SUB_DIRS     := 
+MOD_SUB_DIRS := $(SUB_DIRS)
+ALL_SUB_DIRS := $(SUB_DIRS)
+
+O_TARGET := misc.o
+M_OBJS   :=
+O_OBJS   :=
+OX_OBJS  :=
+
+ifdef CONFIG_PIIX4_ACPI
+O_OBJS += piix4_acpi.o
+endif
+
+include $(TOPDIR)/Rules.make
+
+fastdep:
diff -u --recursive --new-file v2.3.13/linux/drivers/misc/piix4_acpi.c linux/drivers/misc/piix4_acpi.c
--- v2.3.13/linux/drivers/misc/piix4_acpi.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/misc/piix4_acpi.c	Fri Aug 13 13:50:58 1999
@@ -0,0 +1,214 @@
+/*
+ * linux/drivers/misc/piix4_acpi.c
+ *
+ *	(C) Copyright 1999 Linus Torvalds
+ *
+ * A PM driver for the ACPI portion of the Intel PIIX4
+ * chip.
+ *
+ * This has been known to occasionally work on some laptops.
+ *
+ * It probably only works on Intel PII machines that support
+ * the STPCLK protocol.
+ */
+
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+
+extern void (*acpi_idle)(void);
+
+/*
+ * This first part should be common to all ACPI
+ * CPU sleep functionality. Assuming we get the
+ * timing heuristics in a better shape than "none" ;)
+ */
+
+typedef void (*sleep_fn_t)(void);
+
+/*
+ * Our "sleep mode" is a fixed point number
+ * with two binary places, ranging between
+ * [0 .. 3[
+ */
+#define Cx_SHIFT	2
+#define MAXMODE		((3 << Cx_SHIFT)-1)
+
+/*
+ * NOTE!
+ *
+ * Right now this always defaults to C3, which is just broken.
+ * The exit latency is usually too high for much busy IO activity,
+ * and generally it's not always the best thing to do.
+ *
+ * We should just read the cycle counter around all the cases,
+ * and if we pause for a long time we go to a deeper sleep, while
+ * a short wait makes us go into a lighter sleep.
+ */
+static void common_acpi_idle(sleep_fn_t *sleep)
+{
+	int mode = MAXMODE;
+
+	while (1) {
+		while (!current->need_resched) {
+			unsigned int time;
+
+			time = get_cycles();
+			sleep[(mode) >> Cx_SHIFT]();
+			time = get_cycles() - time;
+
+			/*
+			 * Yeah, yeah, yeah.
+			 *  if (time > Large && mode < MAXMODE) mode++;
+			 *  if (time < Small && mode > 0) mode--;
+			 * Yadda-yadda-yadda.
+			 *
+			 * "Large" is on the order of half a timer tick.
+			 * "Small" is on the order of Large >> 2 or so.
+			 *
+			 * Somebody should _really_ look at the exact
+			 * details. The ACPI bios would give some made-up
+			 * numbers, they might be useful (or maybe not:
+			 * they are probably tuned for whatever Windows
+			 * does, so don't take them for granted).
+			 */
+		}
+		schedule();
+		check_pgt_cache();
+	}
+}		
+
+/* Ok, here starts the magic PIIX4 knowledge */
+
+/*
+ * Ehh.. We "know" about the northbridge
+ * bus arbitration stuff. Maybe somebody
+ * should actually verify this some day?
+ */
+#define NORTHBRIDGE_CONTROL	0x22
+#define		NB_ARBITRATE	0x01
+
+/*
+ * PIIX4 ACPI IO offsets and defines
+ */
+#define PMEN		0x02
+#define PMCNTRL		0x04
+#define PMTMR		0x08
+#define GPSTS		0x0c
+#define GPEN		0x0E
+
+#define PCNTRL		0x10
+#define   CC_EN			0x0200
+#define   BST_EN		0x0400
+#define   SLEEP_EN		0x0800
+#define   STPCLK_EN		0x1000
+#define   CLKRUN_EN		0x2000
+
+#define PLVL2		0x14
+#define PLVL3		0x15
+
+/*
+ * PIIX4 ACPI PCI configurations offsets and defines
+ */
+#define DEVACTB		0x58
+#define   BRLD_EN_IRQ0	0x01
+#define   BRLD_EN_IRQ	0x02
+
+#define PMREGMISC	0x80
+#define   PMIOSE		0x01
+
+static unsigned int piix4_base_address = 0;
+
+static void piix4_c1_sleep(void)
+{
+	asm volatile("sti ; hlt" : : : "memory");
+}
+
+static void piix4_c2_sleep(void)
+{
+	outl(CLKRUN_EN | CC_EN, piix4_base_address + PCNTRL);
+	inb(piix4_base_address + PLVL2);
+}
+
+static void piix4_c3_sleep(void)
+{
+	__cli();
+	outl(CLKRUN_EN | CC_EN | STPCLK_EN | SLEEP_EN, piix4_base_address + PCNTRL);
+	outb(NB_ARBITRATE, NORTHBRIDGE_CONTROL);
+	inb(piix4_base_address + PLVL3);
+	outb(0, NORTHBRIDGE_CONTROL);
+	__sti();
+}
+
+static sleep_fn_t piix4_sleep[] = {
+	piix4_c1_sleep,		/* low-latency C1 (ie "sti ; hlt") */
+	piix4_c2_sleep,		/* medium latency C2 (ie LVL2 stopckl) */
+	piix4_c3_sleep		/* high-latency C3 (ie LVL3 sleep) */
+};
+
+static void piix4_acpi_idle(void)
+{
+	common_acpi_idle(piix4_sleep);
+}
+
+static int __init piix4_acpi_init(void)
+{
+	/* This is the PIIX4 ACPI device */
+	struct pci_dev *dev;
+	u32 base, val;
+	u16 cmd;
+	u8 pmregmisc;
+
+#ifdef __SMP__
+	/*
+	 * We can't really do idle things with multiple CPU's, I'm
+	 * afraid.  We'd need a per-CPU ACPI device.
+	 */
+	if (smp_num_cpus > 1)
+		return -1;
+#endif
+	dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
+
+	if (!dev)
+		return -1;
+
+	/*
+	 * Read the IO base value, and verify that it makes sense
+	 *
+	 * We could enable this if it wasn't enabled before, but
+	 * let's walk before we run..
+	 */
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	if (!(cmd & PCI_COMMAND_IO))
+		return -1;
+
+	pci_read_config_byte(dev, PMREGMISC, &pmregmisc);
+	if (!(pmregmisc & PMIOSE))
+		return -1;
+
+	pci_read_config_dword(dev, 0x40, &base);
+	if (!(base & PCI_BASE_ADDRESS_SPACE_IO))
+		return -1;
+
+	base &= PCI_BASE_ADDRESS_IO_MASK;
+	if (!base)
+		return -1;
+
+	printk("Found PIIX4 ACPI device at %04x\n", base);
+	piix4_base_address = base;
+
+	/* Enable stopcklock, sleep and bursts, along with clock control */
+	outl(CLKRUN_EN | CC_EN | STPCLK_EN | SLEEP_EN, piix4_base_address + PCNTRL);
+
+	/* Make all unmasked interrupts be BREAK events */
+	pci_read_config_dword(dev, DEVACTB, &val);
+	pci_write_config_dword(dev, DEVACTB, val | BRLD_EN_IRQ0 | BRLD_EN_IRQ);
+
+	/* Set up the new idle handler.. */
+	acpi_idle = piix4_acpi_idle;
+	return 0;
+}
+
+__initcall(piix4_acpi_init);
diff -u --recursive --new-file v2.3.13/linux/drivers/net/3c501.c linux/drivers/net/3c501.c
--- v2.3.13/linux/drivers/net/3c501.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/3c501.c	Wed Aug 18 11:36:41 1999
@@ -116,16 +116,16 @@
  *	Index to functions.
  */
 
-int el1_probe(struct device *dev);
-static int  el1_probe1(struct device *dev, int ioaddr);
-static int  el_open(struct device *dev);
-static int  el_start_xmit(struct sk_buff *skb, struct device *dev);
+int el1_probe(struct net_device *dev);
+static int  el1_probe1(struct net_device *dev, int ioaddr);
+static int  el_open(struct net_device *dev);
+static int  el_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static void el_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void el_receive(struct device *dev);
-static void el_reset(struct device *dev);
-static int  el1_close(struct device *dev);
-static struct net_device_stats *el1_get_stats(struct device *dev);
-static void set_multicast_list(struct device *dev);
+static void el_receive(struct net_device *dev);
+static void el_reset(struct net_device *dev);
+static int  el1_close(struct net_device *dev);
+static struct net_device_stats *el1_get_stats(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
 
 #define EL1_IO_EXTENT	16
 
@@ -210,7 +210,7 @@
 struct netdev_entry el1_drv = {"3c501", el1_probe1, EL1_IO_EXTENT, netcard_portlist};
 #else
 
-int __init el1_probe(struct device *dev)
+int __init el1_probe(struct net_device *dev)
 {
 	int i;
 	int base_addr = dev ? dev->base_addr : 0;
@@ -237,7 +237,7 @@
  *	The actual probe.
  */
 
-static int __init el1_probe1(struct device *dev, int ioaddr)
+static int __init el1_probe1(struct net_device *dev, int ioaddr)
 {
 	struct net_local *lp;
 	const char *mname;		/* Vendor name */
@@ -355,7 +355,7 @@
  *	Open/initialize the board.
  */
 
-static int el_open(struct device *dev)
+static int el_open(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr;
 
@@ -374,7 +374,7 @@
 	return 0;
 }
 
-static int el_start_xmit(struct sk_buff *skb, struct device *dev)
+static int el_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -480,7 +480,7 @@
 
 static void el_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	struct net_local *lp;
 	int ioaddr;
 	int axsr;			/* Aux. status reg. */
@@ -661,7 +661,7 @@
  *	We must check everything to see if it is good.
  */
 
-static void el_receive(struct device *dev)
+static void el_receive(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -717,7 +717,7 @@
 	return;
 }
 
-static void  el_reset(struct device *dev)
+static void  el_reset(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr;
 
@@ -742,7 +742,7 @@
 	sti();
 }
 
-static int el1_close(struct device *dev)
+static int el1_close(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr;
 
@@ -763,7 +763,7 @@
 	return 0;
 }
 
-static struct net_device_stats *el1_get_stats(struct device *dev)
+static struct net_device_stats *el1_get_stats(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	return &lp->stats;
@@ -774,7 +774,7 @@
  *			best-effort filtering.
  */
 
-static void set_multicast_list(struct device *dev)
+static void set_multicast_list(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr;
 
@@ -799,7 +799,7 @@
 
 static char devicename[9] = { 0, };
 
-static struct device dev_3c501 =
+static struct net_device dev_3c501 =
 {
 	devicename, /* device name is inserted by linux/drivers/net/net_init.c */
 	0, 0, 0, 0,
diff -u --recursive --new-file v2.3.13/linux/drivers/net/3c503.c linux/drivers/net/3c503.c
--- v2.3.13/linux/drivers/net/3c503.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/3c503.c	Wed Aug 18 11:36:41 1999
@@ -52,9 +52,9 @@
 #include "3c503.h"
 #define WRD_COUNT 4
 
-int el2_probe(struct device *dev);
-int el2_pio_probe(struct device *dev);
-int el2_probe1(struct device *dev, int ioaddr);
+int el2_probe(struct net_device *dev);
+int el2_pio_probe(struct net_device *dev);
+int el2_probe1(struct net_device *dev, int ioaddr);
 
 /* A zero-terminated list of I/O addresses to be probed in PIO mode. */
 static unsigned int netcard_portlist[] __initdata =
@@ -71,15 +71,15 @@
 {"3c503pio", el2_pioprobe1, EL1_IO_EXTENT, netcard_portlist};
 #endif
 
-static int el2_open(struct device *dev);
-static int el2_close(struct device *dev);
-static void el2_reset_8390(struct device *dev);
-static void el2_init_card(struct device *dev);
-static void el2_block_output(struct device *dev, int count,
+static int el2_open(struct net_device *dev);
+static int el2_close(struct net_device *dev);
+static void el2_reset_8390(struct net_device *dev);
+static void el2_init_card(struct net_device *dev);
+static void el2_block_output(struct net_device *dev, int count,
 			     const unsigned char *buf, int start_page);
-static void el2_block_input(struct device *dev, int count, struct sk_buff *skb,
+static void el2_block_input(struct net_device *dev, int count, struct sk_buff *skb,
 			   int ring_offset);
-static void el2_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
+static void el2_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
 			 int ring_page);
 
 
@@ -91,7 +91,7 @@
    ethercard jumpered to programmed-I/O mode.
    */
 int __init 
-el2_probe(struct device *dev)
+el2_probe(struct net_device *dev)
 {
     int *addr, addrs[] = { 0xddffe, 0xd9ffe, 0xcdffe, 0xc9ffe, 0};
     int base_addr = dev->base_addr;
@@ -126,7 +126,7 @@
 /*  Try all of the locations that aren't obviously empty.  This touches
     a lot of locations, and is much riskier than the code above. */
 int __init 
-el2_pio_probe(struct device *dev)
+el2_pio_probe(struct net_device *dev)
 {
     int i;
     int base_addr = dev ? dev->base_addr : 0;
@@ -152,7 +152,7 @@
    returning non-zero on success.  If found, set the station
    address and memory parameters in DEVICE. */
 int __init 
-el2_probe1(struct device *dev, int ioaddr)
+el2_probe1(struct net_device *dev, int ioaddr)
 {
     int i, iobase_reg, membase_reg, saved_406, wordlength;
     static unsigned version_printed = 0;
@@ -334,7 +334,7 @@
 }
 
 static int
-el2_open(struct device *dev)
+el2_open(struct net_device *dev)
 {
 
     if (dev->irq < 2) {
@@ -370,7 +370,7 @@
 }
 
 static int
-el2_close(struct device *dev)
+el2_close(struct net_device *dev)
 {
     free_irq(dev->irq, dev);
     dev->irq = ei_status.saved_irq;
@@ -386,7 +386,7 @@
        Bad ring buffer packet header
  */
 static void
-el2_reset_8390(struct device *dev)
+el2_reset_8390(struct net_device *dev)
 {
     if (ei_debug > 1) {
 	printk("%s: Resetting the 3c503 board...", dev->name);
@@ -402,7 +402,7 @@
 
 /* Initialize the 3c503 GA registers after a reset. */
 static void
-el2_init_card(struct device *dev)
+el2_init_card(struct net_device *dev)
 {
     /* Unmap the station PROM and select the DIX or BNC connector. */
     outb_p(ei_status.interface_num==0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
@@ -434,7 +434,7 @@
  * out through the ASIC FIFO.
  */
 static void
-el2_block_output(struct device *dev, int count,
+el2_block_output(struct net_device *dev, int count,
 		 const unsigned char *buf, int start_page)
 {
     unsigned short int *wrd;
@@ -507,7 +507,7 @@
 
 /* Read the 4 byte, page aligned 8390 specific header. */
 static void
-el2_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+el2_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 {
     int boguscount;
     unsigned long hdr_start = dev->mem_start + ((ring_page - EL2_MB1_START_PG)<<8);
@@ -546,7 +546,7 @@
 
 
 static void
-el2_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
+el2_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
 {
     int boguscount = 0;
     unsigned short int *buf;
@@ -625,7 +625,7 @@
 #define NAMELEN 	8	/* #of chars for storing dev->name */
 
 static char namelist[NAMELEN * MAX_EL2_CARDS] = { 0, };
-static struct device dev_el2[MAX_EL2_CARDS] = {
+static struct net_device dev_el2[MAX_EL2_CARDS] = {
 	{
 		NULL,		/* assign a chunk of namelist[] below */
 		0, 0, 0, 0,
@@ -649,7 +649,7 @@
 	int this_dev, found = 0;
 
 	for (this_dev = 0; this_dev < MAX_EL2_CARDS; this_dev++) {
-		struct device *dev = &dev_el2[this_dev];
+		struct net_device *dev = &dev_el2[this_dev];
 		dev->name = namelist+(NAMELEN*this_dev);
 		dev->irq = irq[this_dev];
 		dev->base_addr = io[this_dev];
@@ -679,7 +679,7 @@
 	int this_dev;
 
 	for (this_dev = 0; this_dev < MAX_EL2_CARDS; this_dev++) {
-		struct device *dev = &dev_el2[this_dev];
+		struct net_device *dev = &dev_el2[this_dev];
 		if (dev->priv != NULL) {
 			void *priv = dev->priv;
 			/* NB: el2_close() handles free_irq */
diff -u --recursive --new-file v2.3.13/linux/drivers/net/3c505.c linux/drivers/net/3c505.c
--- v2.3.13/linux/drivers/net/3c505.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/3c505.c	Wed Aug 18 11:36:41 1999
@@ -221,7 +221,7 @@
 	return inb(base_addr + PORT_COMMAND);
 }
 
-static inline void outb_control(unsigned char val, struct device *dev)
+static inline void outb_control(unsigned char val, struct net_device *dev)
 {
 	outb(val, dev->base_addr + PORT_CONTROL);
 	((elp_device *)(dev->priv))->hcr_val = val;
@@ -276,16 +276,16 @@
 	return stat1;
 }
 
-static inline void set_hsf(struct device *dev, int hsf)
+static inline void set_hsf(struct net_device *dev, int hsf)
 {
 	cli();
 	outb_control((HCR_VAL(dev) & ~HSF_PCB_MASK) | hsf, dev);
 	sti();
 }
 
-static int start_receive(struct device *, pcb_struct *);
+static int start_receive(struct net_device *, pcb_struct *);
 
-inline static void adapter_reset(struct device *dev)
+inline static void adapter_reset(struct net_device *dev)
 {
 	int timeout;
 	elp_device *adapter = dev->priv;
@@ -323,7 +323,7 @@
  * never happen in theory, but seems to occur occasionally if the card gets
  * prodded at the wrong time.
  */
-static inline void check_3c505_dma(struct device *dev)
+static inline void check_3c505_dma(struct net_device *dev)
 {
 	elp_device *adapter = dev->priv;
 	if (adapter->dmaing && time_after(jiffies, adapter->current_dma.start_time + 10)) {
@@ -371,7 +371,7 @@
 }
 
 /* Check to see if the receiver needs restarting, and kick it if so */
-static inline void prime_rx(struct device *dev)
+static inline void prime_rx(struct net_device *dev)
 {
 	elp_device *adapter = dev->priv;
 	while (adapter->rx_active < ELP_RX_PCBS && dev->start) {
@@ -404,7 +404,7 @@
  * timeout is reduced to 500us).
  */
 
-static int send_pcb(struct device *dev, pcb_struct * pcb)
+static int send_pcb(struct net_device *dev, pcb_struct * pcb)
 {
 	int i;
 	int timeout;
@@ -487,7 +487,7 @@
  *
  *****************************************************************/
 
-static int receive_pcb(struct device *dev, pcb_struct * pcb)
+static int receive_pcb(struct net_device *dev, pcb_struct * pcb)
 {
 	int i, j;
 	int total_length;
@@ -571,7 +571,7 @@
  *
  ******************************************************/
 
-static int start_receive(struct device *dev, pcb_struct * tx_pcb)
+static int start_receive(struct net_device *dev, pcb_struct * tx_pcb)
 {
 	int status;
 	elp_device *adapter = dev->priv;
@@ -599,7 +599,7 @@
  *
  ******************************************************/
 
-static void receive_packet(struct device *dev, int len)
+static void receive_packet(struct net_device *dev, int len)
 {
 	int rlen;
 	elp_device *adapter = dev->priv;
@@ -668,7 +668,7 @@
 	int len;
 	int dlen;
 	int icount = 0;
-	struct device *dev;
+	struct net_device *dev;
 	elp_device *adapter;
 	int timeout;
 
@@ -885,7 +885,7 @@
  *
  ******************************************************/
 
-static int elp_open(struct device *dev)
+static int elp_open(struct net_device *dev)
 {
 	elp_device *adapter;
 
@@ -1022,7 +1022,7 @@
  *
  ******************************************************/
 
-static int send_packet(struct device *dev, struct sk_buff *skb)
+static int send_packet(struct net_device *dev, struct sk_buff *skb)
 {
 	elp_device *adapter = dev->priv;
 	unsigned long target;
@@ -1092,7 +1092,7 @@
  *
  ******************************************************/
 
-static int elp_start_xmit(struct sk_buff *skb, struct device *dev)
+static int elp_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	if (dev->interrupt) {
 		printk("%s: start_xmit aborted (in irq)\n", dev->name);
@@ -1157,7 +1157,7 @@
  *
  ******************************************************/
 
-static struct net_device_stats *elp_get_stats(struct device *dev)
+static struct net_device_stats *elp_get_stats(struct net_device *dev)
 {
 	elp_device *adapter = (elp_device *) dev->priv;
 
@@ -1194,7 +1194,7 @@
  *
  ******************************************************/
 
-static int elp_close(struct device *dev)
+static int elp_close(struct net_device *dev)
 {
 	elp_device *adapter;
 
@@ -1247,7 +1247,7 @@
  *
  ************************************************************/
 
-static void elp_set_mc_list(struct device *dev)
+static void elp_set_mc_list(struct net_device *dev)
 {
 	elp_device *adapter = (elp_device *) dev->priv;
 	struct dev_mc_list *dmi = dev->mc_list;
@@ -1306,7 +1306,7 @@
  *
  ******************************************************/
 
-static inline void elp_init(struct device *dev)
+static inline void elp_init(struct net_device *dev)
 {
 	elp_device *adapter = dev->priv;
 
@@ -1339,7 +1339,7 @@
  * Called only by elp_autodetect
  ************************************************************/
 
-static int __init elp_sense(struct device *dev)
+static int __init elp_sense(struct net_device *dev)
 {
 	int timeout;
 	int addr = dev->base_addr;
@@ -1406,7 +1406,7 @@
  * Called only by eplus_probe
  *************************************************************/
 
-static int __init elp_autodetect(struct device *dev)
+static int __init elp_autodetect(struct net_device *dev)
 {
 	int idx = 0;
 
@@ -1450,7 +1450,7 @@
  * work at all if it was in a weird state).
  */
 
-int __init elplus_probe(struct device *dev)
+int __init elplus_probe(struct net_device *dev)
 {
 	elp_device *adapter;
 	int i, tries, tries1, timeout, okay;
@@ -1654,7 +1654,7 @@
 #ifdef MODULE
 #define NAMELEN 9
 static char devicename[ELP_MAX_CARDS][NAMELEN] = {{0,}};
-static struct device dev_3c505[ELP_MAX_CARDS] =
+static struct net_device dev_3c505[ELP_MAX_CARDS] =
 {
 	{ NULL,		/* device name is inserted by net_init.c */
 	0, 0, 0, 0,
@@ -1674,7 +1674,7 @@
 	int this_dev, found = 0;
 
 	for (this_dev = 0; this_dev < ELP_MAX_CARDS; this_dev++) {
-		struct device *dev = &dev_3c505[this_dev];
+		struct net_device *dev = &dev_3c505[this_dev];
 		dev->name = devicename[this_dev];
 		dev->irq = irq[this_dev];
 		dev->base_addr = io[this_dev];
@@ -1703,7 +1703,7 @@
 	int this_dev;
 
 	for (this_dev = 0; this_dev < ELP_MAX_CARDS; this_dev++) {
-		struct device *dev = &dev_3c505[this_dev];
+		struct net_device *dev = &dev_3c505[this_dev];
 		if (dev->priv != NULL) {
 			unregister_netdev(dev);
 			kfree(dev->priv);
diff -u --recursive --new-file v2.3.13/linux/drivers/net/3c507.c linux/drivers/net/3c507.c
--- v2.3.13/linux/drivers/net/3c507.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/3c507.c	Wed Aug 18 11:36:41 1999
@@ -279,18 +279,18 @@
 
 /* Index to functions, as function prototypes. */
 
-extern int el16_probe(struct device *dev);	/* Called from Space.c */
+extern int el16_probe(struct net_device *dev);	/* Called from Space.c */
 
-static int	el16_probe1(struct device *dev, int ioaddr);
-static int	el16_open(struct device *dev);
-static int	el16_send_packet(struct sk_buff *skb, struct device *dev);
+static int	el16_probe1(struct net_device *dev, int ioaddr);
+static int	el16_open(struct net_device *dev);
+static int	el16_send_packet(struct sk_buff *skb, struct net_device *dev);
 static void	el16_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void el16_rx(struct device *dev);
-static int	el16_close(struct device *dev);
-static struct net_device_stats *el16_get_stats(struct device *dev);
+static void el16_rx(struct net_device *dev);
+static int	el16_close(struct net_device *dev);
+static struct net_device_stats *el16_get_stats(struct net_device *dev);
 
-static void hardware_send_packet(struct device *dev, void *buf, short length);
-static void init_82586_mem(struct device *dev);
+static void hardware_send_packet(struct net_device *dev, void *buf, short length);
+static void init_82586_mem(struct net_device *dev);
 
 
 #ifdef HAVE_DEVLIST
@@ -305,7 +305,7 @@
 	device and return success.
 	*/
 
-int __init el16_probe(struct device *dev)
+int __init el16_probe(struct net_device *dev)
 {
 	int base_addr = dev ? dev->base_addr : 0;
 	int i;
@@ -326,7 +326,7 @@
 	return ENODEV;
 }
 
-int __init el16_probe1(struct device *dev, int ioaddr)
+int __init el16_probe1(struct net_device *dev, int ioaddr)
 {
 	static unsigned char init_ID_done = 0, version_printed = 0;
 	int i, irq, irqval;
@@ -432,7 +432,7 @@
 	return 0;
 }
 
-static int el16_open(struct device *dev)
+static int el16_open(struct net_device *dev)
 {
 	/* Initialize the 82586 memory and start it. */
 	init_82586_mem(dev);
@@ -446,7 +446,7 @@
 	return 0;
 }
 
-static int el16_send_packet(struct sk_buff *skb, struct device *dev)
+static int el16_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -514,7 +514,7 @@
 	Handle the network interface interrupts. */
 static void el16_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	struct net_local *lp;
 	int ioaddr, status, boguscount = 0;
 	ushort ack_cmd = 0;
@@ -592,7 +592,7 @@
 
 	if ((status & 0x0070) != 0x0040  &&  dev->start) 
 	{
-		static void init_rx_bufs(struct device *);
+		static void init_rx_bufs(struct net_device *);
 		/* The Rx unit is not ready, it must be hung.  Restart the receiver by
 		   initializing the rx buffers, and issuing an Rx start command. */
 		if (net_debug)
@@ -616,7 +616,7 @@
 	return;
 }
 
-static int el16_close(struct device *dev)
+static int el16_close(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr;
 	unsigned long shmem = dev->mem_start;
@@ -642,7 +642,7 @@
 
 /* Get the current statistics.	This may be called with the card open or
    closed. */
-static struct net_device_stats *el16_get_stats(struct device *dev)
+static struct net_device_stats *el16_get_stats(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 
@@ -652,7 +652,7 @@
 }
 
 /* Initialize the Rx-block list. */
-static void init_rx_bufs(struct device *dev)
+static void init_rx_bufs(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	unsigned long write_ptr;
@@ -695,7 +695,7 @@
 	writew(lp->rx_head,write_ptr+2);			/* Link */
 }
 
-static void init_82586_mem(struct device *dev)
+static void init_82586_mem(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	short ioaddr = dev->base_addr;
@@ -753,7 +753,7 @@
 	return;
 }
 
-static void hardware_send_packet(struct device *dev, void *buf, short length)
+static void hardware_send_packet(struct net_device *dev, void *buf, short length)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	short ioaddr = dev->base_addr;
@@ -798,7 +798,7 @@
 		dev->tbusy = 0;
 }
 
-static void el16_rx(struct device *dev)
+static void el16_rx(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	unsigned long shmem = dev->mem_start;
@@ -869,7 +869,7 @@
 }
 #ifdef MODULE
 static char devicename[9] = { 0, };
-static struct device dev_3c507 = {
+static struct net_device dev_3c507 = {
 	devicename, /* device name is inserted by linux/drivers/net/net_init.c */
 	0, 0, 0, 0,
 	0, 0,
diff -u --recursive --new-file v2.3.13/linux/drivers/net/3c509.c linux/drivers/net/3c509.c
--- v2.3.13/linux/drivers/net/3c509.c	Thu May  6 14:02:34 1999
+++ linux/drivers/net/3c509.c	Wed Aug 18 11:36:41 1999
@@ -129,7 +129,7 @@
 
 struct el3_private {
 	struct enet_statistics stats;
-	struct device *next_dev;
+	struct net_device *next_dev;
 	spinlock_t lock;
 	/* skb send-queue */
 	int head, size;
@@ -137,18 +137,18 @@
 	char mca_slot;
 };
 static int id_port = 0x110;		/* Start with 0x110 to avoid new sound cards.*/
-static struct device *el3_root_dev = NULL;
+static struct net_device *el3_root_dev = NULL;
 
 static ushort id_read_eeprom(int index);
 static ushort read_eeprom(int ioaddr, int index);
-static int el3_open(struct device *dev);
-static int el3_start_xmit(struct sk_buff *skb, struct device *dev);
+static int el3_open(struct net_device *dev);
+static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void update_stats(struct device *dev);
-static struct enet_statistics *el3_get_stats(struct device *dev);
-static int el3_rx(struct device *dev);
-static int el3_close(struct device *dev);
-static void set_multicast_list(struct device *dev);
+static void update_stats(struct net_device *dev);
+static struct enet_statistics *el3_get_stats(struct net_device *dev);
+static int el3_rx(struct net_device *dev);
+static int el3_close(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
 
 #ifdef CONFIG_MCA
 struct el3_mca_adapters_struct {
@@ -166,7 +166,7 @@
 };
 #endif
 
-int el3_probe(struct device *dev)
+int el3_probe(struct net_device *dev)
 {
 	short lrs_state = 0xff, i;
 	int ioaddr, irq, if_port;
@@ -425,7 +425,7 @@
 
 
 static int
-el3_open(struct device *dev)
+el3_open(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr;
 	int i;
@@ -505,7 +505,7 @@
 }
 
 static int
-el3_start_xmit(struct sk_buff *skb, struct device *dev)
+el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct el3_private *lp = (struct el3_private *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -615,7 +615,7 @@
 static void
 el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev = (struct device *)dev_id;
+	struct net_device *dev = (struct net_device *)dev_id;
 	struct el3_private *lp;
 	int ioaddr, status;
 	int i = max_interrupt_work;
@@ -708,7 +708,7 @@
 
 
 static struct enet_statistics *
-el3_get_stats(struct device *dev)
+el3_get_stats(struct net_device *dev)
 {
 	struct el3_private *lp = (struct el3_private *)dev->priv;
 	unsigned long flags;
@@ -729,7 +729,7 @@
 	operation, and it's simpler for the rest of the driver to assume that
 	window 1 is always valid rather than use a special window-state variable.
 	*/
-static void update_stats(struct device *dev)
+static void update_stats(struct net_device *dev)
 {
 	struct el3_private *lp = (struct el3_private *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -759,7 +759,7 @@
 }
 
 static int
-el3_rx(struct device *dev)
+el3_rx(struct net_device *dev)
 {
 	struct el3_private *lp = (struct el3_private *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -829,7 +829,7 @@
  *     Set or clear the multicast filter for this adaptor.
  */
 static void
-set_multicast_list(struct device *dev)
+set_multicast_list(struct net_device *dev)
 {
 	unsigned long flags;
 	struct el3_private *lp = (struct el3_private *)dev->priv;
@@ -856,7 +856,7 @@
 }
 
 static int
-el3_close(struct device *dev)
+el3_close(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr;
 
@@ -926,7 +926,7 @@
 void
 cleanup_module(void)
 {
-	struct device *next_dev;
+	struct net_device *next_dev;
 
 	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
 	while (el3_root_dev) {
diff -u --recursive --new-file v2.3.13/linux/drivers/net/3c515.c linux/drivers/net/3c515.c
--- v2.3.13/linux/drivers/net/3c515.c	Mon Jun  7 16:18:58 1999
+++ linux/drivers/net/3c515.c	Wed Aug 18 11:36:41 1999
@@ -293,7 +293,7 @@
 struct vortex_private {
 	char devname[8];			/* "ethN" string, also for kernel debug. */
 	const char *product_name;
-	struct device *next_module;
+	struct net_device *next_module;
 	/* The Rx and Tx rings are here to keep them quad-word-aligned. */
 	struct boom_rx_desc rx_ring[RX_RING_SIZE];
 	struct boom_tx_desc tx_ring[TX_RING_SIZE];
@@ -343,21 +343,21 @@
   { "Default",	 0,			0xFF, XCVR_10baseT, 10000},
 };
 
-static int vortex_scan(struct device *dev);
-static struct device *vortex_found_device(struct device *dev, int ioaddr,
+static int vortex_scan(struct net_device *dev);
+static struct net_device *vortex_found_device(struct net_device *dev, int ioaddr,
 										  int irq, int product_index,
 										  int options);
-static int vortex_probe1(struct device *dev);
-static int vortex_open(struct device *dev);
+static int vortex_probe1(struct net_device *dev);
+static int vortex_open(struct net_device *dev);
 static void vortex_timer(unsigned long arg);
-static int vortex_start_xmit(struct sk_buff *skb, struct device *dev);
-static int vortex_rx(struct device *dev);
-static int boomerang_rx(struct device *dev);
+static int vortex_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 IRQ(int irq, void *dev_id, struct pt_regs *regs);
-static int vortex_close(struct device *dev);
-static void update_stats(int addr, struct device *dev);
-static struct enet_statistics *vortex_get_stats(struct device *dev);
-static void set_rx_mode(struct device *dev);
+static int vortex_close(struct net_device *dev);
+static void update_stats(int addr, struct net_device *dev);
+static struct enet_statistics *vortex_get_stats(struct net_device *dev);
+static void set_rx_mode(struct net_device *dev);
 
 
 /* Unlike the other PCI cards the 59x cards don't need a large contiguous
@@ -381,7 +381,7 @@
 #ifdef MODULE
 static int debug = -1;
 /* A list of all installed Vortex devices, for removing the driver module. */
-static struct device *root_vortex_dev = NULL;
+static struct net_device *root_vortex_dev = NULL;
 
 int
 init_module(void)
@@ -399,7 +399,7 @@
 }
 
 #else
-int tc515_probe(struct device *dev)
+int tc515_probe(struct net_device *dev)
 {
 	int cards_found = 0;
 
@@ -412,7 +412,7 @@
 }
 #endif  /* not MODULE */
 
-static int vortex_scan(struct device *dev)
+static int vortex_scan(struct net_device *dev)
 {
 	int cards_found = 0;
 	static int ioaddr = 0x100;
@@ -452,7 +452,7 @@
 	return cards_found;
 }
 
-static struct device *vortex_found_device(struct device *dev, int ioaddr,
+static struct net_device *vortex_found_device(struct net_device *dev, int ioaddr,
 										  int irq, int product_index,
 										  int options)
 {
@@ -460,13 +460,13 @@
 
 #ifdef MODULE
 	/* Allocate and fill new device structure. */
-	int dev_size = sizeof(struct device) +
+	int dev_size = sizeof(struct net_device) +
 		sizeof(struct vortex_private) + 15;		/* Pad for alignment */
 	
-	dev = (struct device *) kmalloc(dev_size, GFP_KERNEL);
+	dev = (struct net_device *) kmalloc(dev_size, GFP_KERNEL);
 	memset(dev, 0, dev_size);
 	/* Align the Rx and Tx ring entries.  */
-	dev->priv = (void *)(((long)dev + sizeof(struct device) + 15) & ~15);
+	dev->priv = (void *)(((long)dev + sizeof(struct net_device) + 15) & ~15);
 	vp = (struct vortex_private *)dev->priv;
 	dev->name = vp->devname; /* An empty string. */
 	dev->base_addr = ioaddr;
@@ -517,7 +517,7 @@
 	return dev;
 }
 
-static int vortex_probe1(struct device *dev)
+static int vortex_probe1(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr;
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
@@ -607,7 +607,7 @@
 
 
 static int
-vortex_open(struct device *dev)
+vortex_open(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr;
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
@@ -778,7 +778,7 @@
 static void vortex_timer(unsigned long data)
 {
 #ifdef AUTOMEDIA
-	struct device *dev = (struct device *)data;
+	struct net_device *dev = (struct net_device *)data;
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
 	int ioaddr = dev->base_addr;
 	unsigned long flags;
@@ -850,7 +850,7 @@
 }
 
 static int
-vortex_start_xmit(struct sk_buff *skb, struct device *dev)
+vortex_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -1018,7 +1018,7 @@
 static void vortex_interrupt IRQ(int irq, void *dev_id, struct pt_regs *regs)
 {
 	/* Use the now-standard shared IRQ implementation. */
-	struct device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	struct vortex_private *lp;
 	int ioaddr, status;
 	int latency;
@@ -1162,7 +1162,7 @@
 }
 
 static int
-vortex_rx(struct device *dev)
+vortex_rx(struct net_device *dev)
 {
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -1232,7 +1232,7 @@
 }
 
 static int
-boomerang_rx(struct device *dev)
+boomerang_rx(struct net_device *dev)
 {
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
 	int entry = vp->cur_rx % RX_RING_SIZE;
@@ -1322,7 +1322,7 @@
 }
 
 static int
-vortex_close(struct device *dev)
+vortex_close(struct net_device *dev)
 {
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -1388,7 +1388,7 @@
 }
 
 static struct enet_statistics *
-vortex_get_stats(struct device *dev)
+vortex_get_stats(struct net_device *dev)
 {
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
 	unsigned long flags;
@@ -1409,7 +1409,7 @@
 	table.  This is done by checking that the ASM (!) code generated uses
 	atomic updates with '+='.
 	*/
-static void update_stats(int ioaddr, struct device *dev)
+static void update_stats(int ioaddr, struct net_device *dev)
 {
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
 
@@ -1445,7 +1445,7 @@
    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 device *dev)
+set_rx_mode(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr;
 	short new_mode;
@@ -1466,7 +1466,7 @@
 void
 cleanup_module(void)
 {
-	struct device *next_dev;
+	struct net_device *next_dev;
 
 	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
 	while (root_vortex_dev) {
diff -u --recursive --new-file v2.3.13/linux/drivers/net/3c523.c linux/drivers/net/3c523.c
--- v2.3.13/linux/drivers/net/3c523.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/3c523.c	Wed Aug 18 11:36:41 1999
@@ -182,23 +182,23 @@
       elmc_id_reset586(); } } }
 
 static void elmc_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr);
-static int elmc_open(struct device *dev);
-static int elmc_close(struct device *dev);
-static int elmc_send_packet(struct sk_buff *, struct device *);
-static struct net_device_stats *elmc_get_stats(struct device *dev);
+static int elmc_open(struct net_device *dev);
+static int elmc_close(struct net_device *dev);
+static int elmc_send_packet(struct sk_buff *, struct net_device *);
+static struct net_device_stats *elmc_get_stats(struct net_device *dev);
 #ifdef ELMC_MULTICAST
-static void set_multicast_list(struct device *dev);
+static void set_multicast_list(struct net_device *dev);
 #endif
 
 /* helper-functions */
-static int init586(struct device *dev);
-static int check586(struct device *dev, unsigned long where, unsigned size);
-static void alloc586(struct device *dev);
-static void startrecv586(struct device *dev);
-static void *alloc_rfa(struct device *dev, void *ptr);
-static void elmc_rcv_int(struct device *dev);
-static void elmc_xmt_int(struct device *dev);
-static void elmc_rnr_int(struct device *dev);
+static int init586(struct net_device *dev);
+static int check586(struct net_device *dev, unsigned long where, unsigned size);
+static void alloc586(struct net_device *dev);
+static void startrecv586(struct net_device *dev);
+static void *alloc_rfa(struct net_device *dev, void *ptr);
+static void elmc_rcv_int(struct net_device *dev);
+static void elmc_xmt_int(struct net_device *dev);
+static void elmc_rnr_int(struct net_device *dev);
 
 struct priv {
 	struct net_device_stats stats;
@@ -268,7 +268,7 @@
  * close device
  */
 
-static int elmc_close(struct device *dev)
+static int elmc_close(struct net_device *dev)
 {
 	elmc_id_reset586();	/* the hard way to stop the receiver */
 
@@ -288,7 +288,7 @@
  * open device
  */
 
-static int elmc_open(struct device *dev)
+static int elmc_open(struct net_device *dev)
 {
 
 	elmc_id_attn586();	/* disable interrupts */
@@ -319,7 +319,7 @@
  * Check to see if there's an 82586 out there.
  */
 
-static int __init check586(struct device *dev, unsigned long where, unsigned size)
+static int __init check586(struct net_device *dev, unsigned long where, unsigned size)
 {
 	struct priv *p = (struct priv *) dev->priv;
 	char *iscp_addrs[2];
@@ -359,7 +359,7 @@
  * set iscp at the right place, called by elmc_probe and open586.
  */
 
-void alloc586(struct device *dev)
+void alloc586(struct net_device *dev)
 {
 	struct priv *p = (struct priv *) dev->priv;
 
@@ -394,7 +394,7 @@
 static int elmc_getinfo(char *buf, int slot, void *d)
 {
 	int len = 0;
-	struct device *dev = (struct device *) d;
+	struct net_device *dev = (struct net_device *) d;
 	int i;
 
 	if (dev == NULL)
@@ -422,7 +422,7 @@
 
 /*****************************************************************/
 
-int __init elmc_probe(struct device *dev)
+int __init elmc_probe(struct net_device *dev)
 {
 	static int slot = 0;
 	int base_addr = dev ? dev->base_addr : 0;
@@ -593,7 +593,7 @@
  * needs a correct 'allocated' memory
  */
 
-static int init586(struct device *dev)
+static int init586(struct net_device *dev)
 {
 	void *ptr;
 	unsigned long s;
@@ -831,7 +831,7 @@
  * It sets up the Receive Frame Area (RFA).
  */
 
-static void *alloc_rfa(struct device *dev, void *ptr)
+static void *alloc_rfa(struct net_device *dev, void *ptr)
 {
 	volatile struct rfd_struct *rfd = (struct rfd_struct *) ptr;
 	volatile struct rbd_struct *rbd;
@@ -877,7 +877,7 @@
 
 static void elmc_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
 {
-	struct device *dev = (struct device *) dev_id;
+	struct net_device *dev = (struct net_device *) dev_id;
 	unsigned short stat;
 	struct priv *p;
 
@@ -952,7 +952,7 @@
  * receive-interrupt
  */
 
-static void elmc_rcv_int(struct device *dev)
+static void elmc_rcv_int(struct net_device *dev)
 {
 	int status;
 	unsigned short totlen;
@@ -999,7 +999,7 @@
  * handle 'Receiver went not ready'.
  */
 
-static void elmc_rnr_int(struct device *dev)
+static void elmc_rnr_int(struct net_device *dev)
 {
 	struct priv *p = (struct priv *) dev->priv;
 
@@ -1021,7 +1021,7 @@
  * handle xmit - interrupt
  */
 
-static void elmc_xmt_int(struct device *dev)
+static void elmc_xmt_int(struct net_device *dev)
 {
 	int status;
 	struct priv *p = (struct priv *) dev->priv;
@@ -1066,7 +1066,7 @@
  * (re)start the receiver
  */
 
-static void startrecv586(struct device *dev)
+static void startrecv586(struct net_device *dev)
 {
 	struct priv *p = (struct priv *) dev->priv;
 
@@ -1080,7 +1080,7 @@
  * send frame
  */
 
-static int elmc_send_packet(struct sk_buff *skb, struct device *dev)
+static int elmc_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
 	int len;
 #ifndef NO_NOPCOMMANDS
@@ -1192,7 +1192,7 @@
  * Someone wanna have the statistics
  */
 
-static struct net_device_stats *elmc_get_stats(struct device *dev)
+static struct net_device_stats *elmc_get_stats(struct net_device *dev)
 {
 	struct priv *p = (struct priv *) dev->priv;
 	unsigned short crc, aln, rsc, ovrn;
@@ -1219,7 +1219,7 @@
  */
 
 #ifdef ELMC_MULTICAST
-static void set_multicast_list(struct device *dev)
+static void set_multicast_list(struct net_device *dev)
 {
 	if (!dev->start) {
 		/* without a running interface, promiscuous doesn't work */
@@ -1244,7 +1244,7 @@
 
 static char devicenames[NAMELEN * MAX_3C523_CARDS] = {0,};
 
-static struct device dev_elmc[MAX_3C523_CARDS] =
+static struct net_device dev_elmc[MAX_3C523_CARDS] =
 {	
 	{
 	NULL /*"3c523" */ , 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL
@@ -1263,7 +1263,7 @@
 	/* Loop until we either can't find any more cards, or we have MAX_3C523_CARDS */	
 	for(this_dev=0; this_dev<MAX_3C523_CARDS; this_dev++) 
 		{
-		struct device *dev = &dev_elmc[this_dev];
+		struct net_device *dev = &dev_elmc[this_dev];
 		dev->name=devicenames+(NAMELEN*this_dev);
 		dev->irq=irq[this_dev];
 		dev->base_addr=io[this_dev];
@@ -1285,7 +1285,7 @@
 	int this_dev;
 	for(this_dev=0; this_dev<MAX_3C523_CARDS; this_dev++) {
 
-		struct device *dev = &dev_elmc[this_dev];
+		struct net_device *dev = &dev_elmc[this_dev];
 		if(dev->priv) {
 			/* shutdown interrupts on the card */
 			elmc_id_reset586();
diff -u --recursive --new-file v2.3.13/linux/drivers/net/3c527.c linux/drivers/net/3c527.c
--- v2.3.13/linux/drivers/net/3c527.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/3c527.c	Wed Aug 18 11:36:41 1999
@@ -129,15 +129,15 @@
 
 /* Index to functions, as function prototypes. */
 
-extern int mc32_probe(struct device *dev);
+extern int mc32_probe(struct net_device *dev);
 
-static int	mc32_probe1(struct device *dev, int ioaddr);
-static int	mc32_open(struct device *dev);
-static int	mc32_send_packet(struct sk_buff *skb, struct device *dev);
+static int	mc32_probe1(struct net_device *dev, int ioaddr);
+static int	mc32_open(struct net_device *dev);
+static int	mc32_send_packet(struct sk_buff *skb, struct net_device *dev);
 static void	mc32_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static int	mc32_close(struct device *dev);
-static struct	net_device_stats *mc32_get_stats(struct device *dev);
-static void	mc32_set_multicast_list(struct device *dev);
+static int	mc32_close(struct net_device *dev);
+static struct	net_device_stats *mc32_get_stats(struct net_device *dev);
+static void	mc32_set_multicast_list(struct net_device *dev);
 
 /*
  * Check for a network adaptor of this type, and return '0' iff one exists.
@@ -147,7 +147,7 @@
  * (detachable devices only).
  */
 
-int __init mc32_probe(struct device *dev)
+int __init mc32_probe(struct net_device *dev)
 {
 	static int current_mca_slot = -1;
 	int i;
@@ -183,7 +183,7 @@
  * probes on the ISA bus. A good device probes avoids doing writes, and
  * verifies that the correct device exists and functions.
  */
-static int __init mc32_probe1(struct device *dev, int slot)
+static int __init mc32_probe1(struct net_device *dev, int slot)
 {
 	static unsigned version_printed = 0;
 	int i;
@@ -435,7 +435,7 @@
  *	Polled command stuff 
  */
  
-static void mc32_ring_poll(struct device *dev)
+static void mc32_ring_poll(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr;
 	while(!(inb(ioaddr+HOST_STATUS)&HOST_STATUS_CRR));
@@ -446,7 +446,7 @@
  *	Send exec commands
  */
  
-static int mc32_command(struct device *dev, u16 cmd, void *data, int len)
+static int mc32_command(struct net_device *dev, u16 cmd, void *data, int len)
 {
 	struct mc32_local *lp = (struct mc32_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -488,7 +488,7 @@
  *	RX abort
  */
  
-static void mc32_rx_abort(struct device *dev)
+static void mc32_rx_abort(struct net_device *dev)
 {
 	struct mc32_local *lp = (struct mc32_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -504,7 +504,7 @@
  *	RX enable
  */
  
-static void mc32_rx_begin(struct device *dev)
+static void mc32_rx_begin(struct net_device *dev)
 {
 	struct mc32_local *lp = (struct mc32_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -518,7 +518,7 @@
 	lp->rx_halted=0;
 }
 
-static void mc32_tx_abort(struct device *dev)
+static void mc32_tx_abort(struct net_device *dev)
 {
 	struct mc32_local *lp = (struct mc32_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -565,7 +565,7 @@
  *	TX enable
  */
  
-static void mc32_tx_begin(struct device *dev)
+static void mc32_tx_begin(struct net_device *dev)
 {
 	struct mc32_local *lp = (struct mc32_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -588,7 +588,7 @@
  *	Load the rx ring
  */
  
-static int mc32_load_rx_ring(struct device *dev)
+static int mc32_load_rx_ring(struct net_device *dev)
 {
 	struct mc32_local *lp = (struct mc32_local *)dev->priv;
 	int i;
@@ -652,7 +652,7 @@
  * sometime after booting when the 'ifconfig' program is run.
  */
 
-static int mc32_open(struct device *dev)
+static int mc32_open(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr;
 	u16 zero_word=0;
@@ -717,7 +717,7 @@
 	return 0;
 }
 
-static int mc32_send_packet(struct sk_buff *skb, struct device *dev)
+static int mc32_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
 	struct mc32_local *lp = (struct mc32_local *)dev->priv;
 
@@ -796,12 +796,12 @@
 	return 0;
 }
 
-static void mc32_update_stats(struct device *dev)
+static void mc32_update_stats(struct net_device *dev)
 {
 }
 
 
-static void mc32_rx_ring(struct device *dev)
+static void mc32_rx_ring(struct net_device *dev)
 {
 	struct mc32_local *lp=dev->priv;
 	int ioaddr = dev->base_addr;
@@ -879,7 +879,7 @@
  */
 static void mc32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
-	struct device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	struct mc32_local *lp;
 	int ioaddr, status, boguscount = 0;
 	int rx_event = 0;
@@ -1002,7 +1002,7 @@
 
 /* The inverse routine to mc32_open(). */
 
-static int mc32_close(struct device *dev)
+static int mc32_close(struct net_device *dev)
 {
 	struct mc32_local *lp = (struct mc32_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -1050,7 +1050,7 @@
  * This may be called with the card open or closed.
  */
 
-static struct net_device_stats *mc32_get_stats(struct device *dev)
+static struct net_device_stats *mc32_get_stats(struct net_device *dev)
 {
 	struct mc32_local *lp = (struct mc32_local *)dev->priv;
 	return &lp->net_stats;
@@ -1063,7 +1063,7 @@
  * num_addrs > 0	Multicast mode, receive normal and MC packets,
  *			and do best-effort filtering.
  */
-static void mc32_set_multicast_list(struct device *dev)
+static void mc32_set_multicast_list(struct net_device *dev)
 {
 	u16 filt;
 	if (dev->flags&IFF_PROMISC)
@@ -1110,7 +1110,7 @@
 #ifdef MODULE
 
 static char devicename[9] = { 0, };
-static struct device this_device = {
+static struct net_device this_device = {
 	devicename, /* will be inserted by linux/drivers/net/mc32_init.c */
 	0, 0, 0, 0,
 	0, 0,  /* I/O address, IRQ */
diff -u --recursive --new-file v2.3.13/linux/drivers/net/3c59x.c linux/drivers/net/3c59x.c
--- v2.3.13/linux/drivers/net/3c59x.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/3c59x.c	Wed Aug 18 11:36:41 1999
@@ -229,14 +229,14 @@
 	const char *name;
 	u16	vendor_id, device_id, device_id_mask, flags;
 	int drv_flags, io_size;
-	struct device *(*probe1)(int pci_bus, int pci_devfn, struct device *dev,
+	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 device *vortex_probe1(int pci_bus, int pci_devfn,
-									struct device *dev, long ioaddr,
+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,
@@ -422,7 +422,7 @@
 	/* 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 device *next_module;
+	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. */
@@ -482,23 +482,23 @@
 };
 
 #ifndef CARDBUS
-static int vortex_scan(struct device *dev, struct pci_id_info pci_tbl[]);
+static int vortex_scan(struct net_device *dev, struct pci_id_info pci_tbl[]);
 #endif
-static int vortex_open(struct 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 device *dev);
-static int boomerang_start_xmit(struct sk_buff *skb, struct device *dev);
-static int vortex_rx(struct device *dev);
-static int boomerang_rx(struct device *dev);
+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 device *dev);
-static void update_stats(long ioaddr, struct device *dev);
-static struct net_device_stats *vortex_get_stats(struct device *dev);
-static void set_rx_mode(struct device *dev);
-static int vortex_ioctl(struct device *dev, struct ifreq *rq, int cmd);
+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);
 
 
 /* This driver uses 'options' to pass the media type, full-duplex flag, etc. */
@@ -507,7 +507,7 @@
 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 device *root_vortex_dev = NULL;
+static struct net_device *root_vortex_dev = NULL;
 
 #ifdef MODULE
 #ifndef CARDBUS
@@ -524,7 +524,7 @@
 	u16 dev_id, vendor_id;
 	u32 io;
 	u8 bus, devfn, irq;
-	struct device *dev;
+	struct net_device *dev;
 	int chip_idx;
 
 	if (loc->bus != LOC_PCI) return NULL;
@@ -566,14 +566,14 @@
 
 static void vortex_detach(dev_node_t *node)
 {
-	struct device **devp, **next;
+	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 device *dev = *devp;
+		struct net_device *dev = *devp;
 		struct vortex_private *vp = dev->priv;
 		if (dev->flags & IFF_UP)
 			vortex_close(dev);
@@ -608,7 +608,7 @@
 }
 
 #else
-int tc59x_probe(struct device *dev)
+int tc59x_probe(struct net_device *dev)
 {
 	static int scanned=0;
 	if(scanned++)
@@ -619,7 +619,7 @@
 #endif  /* not MODULE */
 
 #ifndef CARDBUS
-static int vortex_scan(struct device *dev, struct pci_id_info pci_tbl[])
+static int vortex_scan(struct net_device *dev, struct pci_id_info pci_tbl[])
 {
 	int cards_found = 0;
 
@@ -762,8 +762,8 @@
 }
 #endif  /* ! Cardbus */
 
-static struct device *vortex_probe1(int pci_bus, int pci_devfn,
-									struct device *dev, long ioaddr,
+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;
@@ -964,7 +964,7 @@
 
 
 static int
-vortex_open(struct device *dev)
+vortex_open(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
@@ -1159,7 +1159,7 @@
 
 static void vortex_timer(unsigned long data)
 {
-	struct device *dev = (struct device *)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 = 0;
@@ -1261,7 +1261,7 @@
 	return;
 }
 
-static void vortex_tx_timeout(struct device *dev)
+static void vortex_tx_timeout(struct net_device *dev)
 {
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -1332,7 +1332,7 @@
  * the cache impact.
  */
 static void
-vortex_error(struct device *dev, int status)
+vortex_error(struct net_device *dev, int status)
 {
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -1421,7 +1421,7 @@
 
 
 static int
-vortex_start_xmit(struct sk_buff *skb, struct device *dev)
+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;
@@ -1483,7 +1483,7 @@
 }
 
 static int
-boomerang_start_xmit(struct sk_buff *skb, struct device *dev)
+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;
@@ -1547,7 +1547,7 @@
    after the Tx thread. */
 static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
 	long ioaddr;
 	int latency, status;
@@ -1672,7 +1672,7 @@
 	return;
 }
 
-static int vortex_rx(struct device *dev)
+static int vortex_rx(struct net_device *dev)
 {
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -1745,7 +1745,7 @@
 }
 
 static int
-boomerang_rx(struct device *dev)
+boomerang_rx(struct net_device *dev)
 {
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
 	int entry = vp->cur_rx % RX_RING_SIZE;
@@ -1841,7 +1841,7 @@
 }
 
 static int
-vortex_close(struct device *dev)
+vortex_close(struct net_device *dev)
 {
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -1901,7 +1901,7 @@
 	return 0;
 }
 
-static struct net_device_stats *vortex_get_stats(struct device *dev)
+static struct net_device_stats *vortex_get_stats(struct net_device *dev)
 {
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
 	unsigned long flags;
@@ -1922,7 +1922,7 @@
 	table.  This is done by checking that the ASM (!) code generated uses
 	atomic updates with '+='.
 	*/
-static void update_stats(long ioaddr, struct device *dev)
+static void update_stats(long ioaddr, struct net_device *dev)
 {
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
 
@@ -1953,7 +1953,7 @@
 	return;
 }
 
-static int vortex_ioctl(struct device *dev, struct ifreq *rq, int cmd)
+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;
@@ -1981,7 +1981,7 @@
 /* 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 device *dev)
+static void set_rx_mode(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
 	int new_mode;
@@ -2096,7 +2096,7 @@
 #ifdef MODULE
 void cleanup_module(void)
 {
-	struct device *next_dev;
+	struct net_device *next_dev;
 
 #ifdef CARDBUS
 	unregister_driver(&vortex_ops);
diff -u --recursive --new-file v2.3.13/linux/drivers/net/7990.c linux/drivers/net/7990.c
--- v2.3.13/linux/drivers/net/7990.c	Thu Jun 25 11:03:42 1998
+++ linux/drivers/net/7990.c	Wed Aug 18 11:36:41 1999
@@ -101,7 +101,7 @@
 #define DEBUG_IRING 0
 /* Set up the Lance Rx and Tx rings and the init block */
 /* Sets dev->tbusy */
-static void lance_init_ring (struct device *dev)
+static void lance_init_ring (struct net_device *dev)
 {
         struct lance_private *lp = (struct lance_private *) dev->priv;
         volatile struct lance_init_block *ib = lp->init_block;
@@ -219,7 +219,7 @@
         return 0;
 }
 
-static int lance_reset (struct device *dev)
+static int lance_reset (struct net_device *dev)
 {
         struct lance_private *lp = (struct lance_private *)dev->priv;
         int status;
@@ -242,7 +242,7 @@
         return status;
 }
 
-static int lance_rx (struct device *dev)
+static int lance_rx (struct net_device *dev)
 {
         struct lance_private *lp = (struct lance_private *) dev->priv;
         volatile struct lance_init_block *ib = lp->init_block;
@@ -320,7 +320,7 @@
         return 0;
 }
 
-static int lance_tx (struct device *dev)
+static int lance_tx (struct net_device *dev)
 {
         struct lance_private *lp = (struct lance_private *) dev->priv;
         volatile struct lance_init_block *ib = lp->init_block;
@@ -405,7 +405,7 @@
 
 static void lance_interrupt (int irq, void *dev_id, struct pt_regs *regs)
 {
-        struct device *dev = (struct device *)dev_id;
+        struct net_device *dev = (struct net_device *)dev_id;
         struct lance_private *lp = (struct lance_private *)dev->priv;
         int csr0;
         DECLARE_LL;
@@ -460,7 +460,7 @@
         dev->interrupt = 0;
 }
 
-int lance_open (struct device *dev)
+int lance_open (struct net_device *dev)
 {
         struct lance_private *lp = (struct lance_private *)dev->priv;
         DECLARE_LL;
@@ -472,7 +472,7 @@
         return lance_reset(dev);
 }
 
-int lance_close (struct device *dev)
+int lance_close (struct net_device *dev)
 {
         struct lance_private *lp = (struct lance_private *) dev->priv;
         DECLARE_LL;
@@ -489,7 +489,7 @@
         return 0;
 }
 
-int lance_start_xmit (struct sk_buff *skb, struct device *dev)
+int lance_start_xmit (struct sk_buff *skb, struct net_device *dev)
 {
         struct lance_private *lp = (struct lance_private *)dev->priv;
         volatile struct lance_init_block *ib = lp->init_block;
@@ -560,7 +560,7 @@
         return status;
 }
 
-struct net_device_stats *lance_get_stats (struct device *dev)
+struct net_device_stats *lance_get_stats (struct net_device *dev)
 {
         struct lance_private *lp = (struct lance_private *) dev->priv;
 
@@ -568,7 +568,7 @@
 }
 
 /* taken from the depca driver via a2065.c */
-static void lance_load_multicast (struct device *dev)
+static void lance_load_multicast (struct net_device *dev)
 {
         struct lance_private *lp = (struct lance_private *) dev->priv;
         volatile struct lance_init_block *ib = lp->init_block;
@@ -619,7 +619,7 @@
 }
 
 
-void lance_set_multicast (struct device *dev)
+void lance_set_multicast (struct net_device *dev)
 {
         struct lance_private *lp = (struct lance_private *) dev->priv;
         volatile struct lance_init_block *ib = lp->init_block;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/7990.h linux/drivers/net/7990.h
--- v2.3.13/linux/drivers/net/7990.h	Sat Jun 13 13:28:34 1998
+++ linux/drivers/net/7990.h	Wed Aug 18 11:36:45 1999
@@ -247,10 +247,10 @@
 #define LANCE_ADDR(x) ((int)(x) & ~0xff000000)
 
 /* Now the prototypes we export */
-extern int lance_open(struct device *dev);
-extern int lance_close (struct device *dev);
-extern int lance_start_xmit (struct sk_buff *skb, struct device *dev);
-extern struct net_device_stats *lance_get_stats (struct device *dev);
-extern void lance_set_multicast (struct device *dev);
+extern int lance_open(struct net_device *dev);
+extern int lance_close (struct net_device *dev);
+extern int lance_start_xmit (struct sk_buff *skb, struct net_device *dev);
+extern struct net_device_stats *lance_get_stats (struct net_device *dev);
+extern void lance_set_multicast (struct net_device *dev);
 
 #endif /* ndef _7990_H */
diff -u --recursive --new-file v2.3.13/linux/drivers/net/82596.c linux/drivers/net/82596.c
--- v2.3.13/linux/drivers/net/82596.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/82596.c	Wed Aug 18 11:36:41 1999
@@ -258,20 +258,20 @@
 	0x00,
 	0x7f /*  *multi IA */ };
 
-static int i596_open(struct device *dev);
-static int i596_start_xmit(struct sk_buff *skb, struct device *dev);
+static int i596_open(struct net_device *dev);
+static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static int i596_close(struct device *dev);
-static struct net_device_stats *i596_get_stats(struct device *dev);
-static void i596_add_cmd(struct device *dev, struct i596_cmd *cmd);
+static int i596_close(struct net_device *dev);
+static struct net_device_stats *i596_get_stats(struct net_device *dev);
+static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd);
 static void print_eth(char *);
-static void set_multicast_list(struct device *dev);
+static void set_multicast_list(struct net_device *dev);
 
 static int ticks_limit = 25;
 static int max_cmd_backlog = 16;
 
 
-static inline void CA(struct device *dev)
+static inline void CA(struct net_device *dev)
 {
 #ifdef CONFIG_MVME16x_NET
 	if (MACH_IS_MVME16x) {
@@ -291,7 +291,7 @@
 }
 
 
-static inline void MPU_PORT(struct device *dev, int c, volatile void *x)
+static inline void MPU_PORT(struct net_device *dev, int c, volatile void *x)
 {
 #ifdef CONFIG_MVME16x_NET
 	if (MACH_IS_MVME16x) {
@@ -315,7 +315,7 @@
 #if defined(CONFIG_MVME16x_NET) || defined(CONFIG_BVME6000_NET)
 static void i596_error(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	struct i596_cmd *cmd;
 
 	struct i596_private *lp = (struct i596_private *) dev->priv;
@@ -338,7 +338,7 @@
 }
 #endif
 
-static inline int init_rx_bufs(struct device *dev, int num)
+static inline int init_rx_bufs(struct net_device *dev, int num)
 {
 	struct i596_private *lp = (struct i596_private *) dev->priv;
 	int i;
@@ -373,7 +373,7 @@
 	return (i);
 }
 
-static inline void remove_rx_bufs(struct device *dev)
+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);
@@ -388,7 +388,7 @@
 	while (rfd != lp->rx_tail);
 }
 
-static inline void init_i596_mem(struct device *dev)
+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)
@@ -528,7 +528,7 @@
 	return;
 }
 
-static inline int i596_rx(struct device *dev)
+static inline int i596_rx(struct net_device *dev)
 {
 	struct i596_private *lp = (struct i596_private *) dev->priv;
 	struct i596_rfd *rfd;
@@ -645,7 +645,7 @@
 	lp->scb.cmd = WSWAPcmd(lp->cmd_head);
 }
 
-static inline void i596_reset(struct device *dev, struct i596_private *lp, int ioaddr)
+static inline void i596_reset(struct net_device *dev, struct i596_private *lp, int ioaddr)
 {
 	int boguscnt = 1000;
 	unsigned long flags;
@@ -688,7 +688,7 @@
 	init_i596_mem(dev);
 }
 
-static void i596_add_cmd(struct device *dev, struct i596_cmd *cmd)
+static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd)
 {
 	struct i596_private *lp = (struct i596_private *) dev->priv;
 	int ioaddr = dev->base_addr;
@@ -746,7 +746,7 @@
 	}
 }
 
-static int i596_open(struct device *dev)
+static int i596_open(struct net_device *dev)
 {
 	int i;
 
@@ -779,7 +779,7 @@
 	return 0;		/* Always succeed */
 }
 
-static int i596_start_xmit(struct sk_buff *skb, struct device *dev)
+static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct i596_private *lp = (struct i596_private *) dev->priv;
 	int ioaddr = dev->base_addr;
@@ -878,7 +878,7 @@
 	printk("type %2.2X%2.2X\n", (unsigned char) add[12], (unsigned char) add[13]);
 }
 
-int __init i82596_probe(struct device *dev)
+int __init i82596_probe(struct net_device *dev)
 {
 	int i;
 	struct i596_private *lp;
@@ -983,7 +983,7 @@
 
 static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	struct i596_private *lp;
 	short ioaddr;
 	int boguscnt = 2000;
@@ -1176,7 +1176,7 @@
 	return;
 }
 
-static int i596_close(struct device *dev)
+static int i596_close(struct net_device *dev)
 {
 	struct i596_private *lp = (struct i596_private *) dev->priv;
 	int boguscnt = 2000;
@@ -1239,7 +1239,7 @@
 }
 
 static struct net_device_stats *
- i596_get_stats(struct device *dev)
+ i596_get_stats(struct net_device *dev)
 {
 	struct i596_private *lp = (struct i596_private *) dev->priv;
 
@@ -1250,7 +1250,7 @@
  *    Set or clear the multicast filter for this adaptor.
  */
 
-static void set_multicast_list(struct device *dev)
+static void set_multicast_list(struct net_device *dev)
 {
 	struct i596_private *lp = (struct i596_private *) dev->priv;
 	struct i596_cmd *cmd;
@@ -1317,7 +1317,7 @@
 #ifdef MODULE
 static char devicename[9] =
 {0,};
-static struct device dev_apricot =
+static struct net_device dev_apricot =
 {
 	devicename,		/* device name inserted by /linux/drivers/net/net_init.c */
 	0, 0, 0, 0,
diff -u --recursive --new-file v2.3.13/linux/drivers/net/8390.c linux/drivers/net/8390.c
--- v2.3.13/linux/drivers/net/8390.c	Thu May  6 14:02:34 1999
+++ linux/drivers/net/8390.c	Wed Aug 18 11:36:41 1999
@@ -76,18 +76,18 @@
 
 /* These are the operational function interfaces to board-specific
    routines.
-	void reset_8390(struct device *dev)
+	void reset_8390(struct net_device *dev)
 		Resets the board associated with DEV, including a hardware reset of
 		the 8390.  This is only called when there is a transmit timeout, and
 		it is always followed by 8390_init().
-	void block_output(struct device *dev, int count, const unsigned char *buf,
+	void block_output(struct net_device *dev, int count, const unsigned char *buf,
 					  int start_page)
 		Write the COUNT bytes of BUF to the packet buffer at START_PAGE.  The
 		"page" value uses the 8390's 256-byte pages.
-	void get_8390_hdr(struct device *dev, struct e8390_hdr *hdr, int ring_page)
+	void get_8390_hdr(struct net_device *dev, struct e8390_hdr *hdr, int ring_page)
 		Read the 4 byte, page aligned 8390 header. *If* there is a
 		subsequent read, it will be of the rest of the packet.
-	void block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
+	void block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
 		Read COUNT bytes from the packet buffer into the skb data area. Start 
 		reading from RING_OFFSET, the address as the 8390 sees it.  This will always
 		follow the read of the 8390 header. 
@@ -103,16 +103,16 @@
 #endif
 
 /* Index to functions. */
-static void ei_tx_intr(struct device *dev);
-static void ei_tx_err(struct device *dev);
-static void ei_receive(struct device *dev);
-static void ei_rx_overrun(struct device *dev);
+static void ei_tx_intr(struct net_device *dev);
+static void ei_tx_err(struct net_device *dev);
+static void ei_receive(struct net_device *dev);
+static void ei_rx_overrun(struct net_device *dev);
 
 /* Routines generic to NS8390-based boards. */
-static void NS8390_trigger_send(struct device *dev, unsigned int length,
+static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
 								int start_page);
-static void set_multicast_list(struct device *dev);
-static void do_set_multicast_list(struct device *dev);
+static void set_multicast_list(struct net_device *dev);
+static void do_set_multicast_list(struct net_device *dev);
 
 /*
  *	SMP and the 8390 setup.
@@ -146,7 +146,7 @@
    up anew at each open, even though many of these registers should only
    need to be set once at boot.
    */
-int ei_open(struct device *dev)
+int ei_open(struct net_device *dev)
 {
 	unsigned long flags;
 	struct ei_device *ei_local = (struct ei_device *) dev->priv;
@@ -174,7 +174,7 @@
 }
 
 /* Opposite of above. Only used when "ifconfig <devname> down" is done. */
-int ei_close(struct device *dev)
+int ei_close(struct net_device *dev)
 {
 	struct ei_device *ei_local = (struct ei_device *) dev->priv;
 	unsigned long flags;
@@ -190,7 +190,7 @@
 	return 0;
 }
 
-static int ei_start_xmit(struct sk_buff *skb, struct device *dev)
+static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	int e8390_base = dev->base_addr;
 	struct ei_device *ei_local = (struct ei_device *) dev->priv;
@@ -404,7 +404,7 @@
 
 void ei_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
-	struct device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	int e8390_base;
 	int interrupts, nr_serviced = 0;
 	struct ei_device *ei_local;
@@ -516,7 +516,7 @@
  * Called with lock held
  */
 
-static void ei_tx_err(struct device *dev)
+static void ei_tx_err(struct net_device *dev)
 {
 	int e8390_base = dev->base_addr;
 	struct ei_device *ei_local = (struct ei_device *) dev->priv;
@@ -554,7 +554,7 @@
 /* We have finished a transmit: check for errors and then trigger the next
    packet to be sent. Called with lock held */
 
-static void ei_tx_intr(struct device *dev)
+static void ei_tx_intr(struct net_device *dev)
 {
 	int e8390_base = dev->base_addr;
 	struct ei_device *ei_local = (struct ei_device *) dev->priv;
@@ -644,7 +644,7 @@
 /* We have a good packet(s), get it/them out of the buffers. 
    Called with lock held */
 
-static void ei_receive(struct device *dev)
+static void ei_receive(struct net_device *dev)
 {
 	int e8390_base = dev->base_addr;
 	struct ei_device *ei_local = (struct ei_device *) dev->priv;
@@ -773,7 +773,7 @@
  * computer will hate you - it takes 10mS or so. 
  */
 
-static void ei_rx_overrun(struct device *dev)
+static void ei_rx_overrun(struct net_device *dev)
 {
 	int e8390_base = dev->base_addr;
 	unsigned char was_txing, must_resend = 0;
@@ -842,7 +842,7 @@
  *	Collect the stats. This is called unlocked and from several contexts.
  */
  
-static struct net_device_stats *get_stats(struct device *dev)
+static struct net_device_stats *get_stats(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr;
 	struct ei_device *ei_local = (struct ei_device *) dev->priv;
@@ -888,7 +888,7 @@
  * associated with this dev structure.
  */
  
-static inline void make_mc_bits(u8 *bits, struct device *dev)
+static inline void make_mc_bits(u8 *bits, struct net_device *dev)
 {
 	struct dev_mc_list *dmi;
 
@@ -917,7 +917,7 @@
  *	from a BH in 2.1.x. Must be called with lock held. 
  */
  
-static void do_set_multicast_list(struct device *dev)
+static void do_set_multicast_list(struct net_device *dev)
 {
 	int e8390_base = dev->base_addr;
 	int i;
@@ -972,7 +972,7 @@
  *	not called too often. Must protect against both bh and irq users
  */
  
-static void set_multicast_list(struct device *dev)
+static void set_multicast_list(struct net_device *dev)
 {
 	unsigned long flags;
 	struct ei_device *ei_local = (struct ei_device*)dev->priv;
@@ -987,7 +987,7 @@
  * this, as it is used by 8390 based modular drivers too.
  */
 
-int ethdev_init(struct device *dev)
+int ethdev_init(struct net_device *dev)
 {
 	if (ei_debug > 1)
 		printk(version);
@@ -1022,7 +1022,7 @@
  *	Must be called with lock held.
  */
 
-void NS8390_init(struct device *dev, int startp)
+void NS8390_init(struct net_device *dev, int startp)
 {
 	int e8390_base = dev->base_addr;
 	struct ei_device *ei_local = (struct ei_device *) dev->priv;
@@ -1085,7 +1085,7 @@
 /* Trigger a transmit start, assuming the length is valid. 
    Always called with the page lock held */
    
-static void NS8390_trigger_send(struct device *dev, unsigned int length,
+static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
 								int start_page)
 {
 	int e8390_base = dev->base_addr;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/8390.h linux/drivers/net/8390.h
--- v2.3.13/linux/drivers/net/8390.h	Mon Dec 28 11:04:21 1998
+++ linux/drivers/net/8390.h	Wed Aug 18 11:36:45 1999
@@ -53,10 +53,10 @@
 #if defined(LOAD_8390_BY_KMOD) && defined(MODULE) && !defined(NS8390_CORE)
 
 /* Function pointers to be mapped onto the 8390 core support */
-static int (*S_ethdev_init)(struct device *dev);
-static void (*S_NS8390_init)(struct device *dev, int startp);
-static int (*S_ei_open)(struct device *dev);
-static int (*S_ei_close)(struct device *dev);
+static int (*S_ethdev_init)(struct net_device *dev);
+static void (*S_NS8390_init)(struct net_device *dev, int startp);
+static int (*S_ei_open)(struct net_device *dev);
+static int (*S_ei_close)(struct net_device *dev);
 static void (*S_ei_interrupt)(int irq, void *dev_id, struct pt_regs *regs);
 
 
@@ -143,23 +143,23 @@
 #define load_8390_module(driver)	0
 #define lock_8390_module()		do { } while (0)
 #define unlock_8390_module()		do { } while (0)
-extern int ethdev_init(struct device *dev);
-extern void NS8390_init(struct device *dev, int startp);
-extern int ei_open(struct device *dev);
-extern int ei_close(struct device *dev);
+extern int ethdev_init(struct net_device *dev);
+extern void NS8390_init(struct net_device *dev, int startp);
+extern int ei_open(struct net_device *dev);
+extern int ei_close(struct net_device *dev);
 extern void ei_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 
 #endif
 
-/* Most of these entries should be in 'struct device' (or most of the
+/* Most of these entries should be in 'struct net_device' (or most of the
    things in there should be here!) */
 /* You have one of these per-board */
 struct ei_device {
 	const char *name;
-	void (*reset_8390)(struct device *);
-	void (*get_8390_hdr)(struct device *, struct e8390_pkt_hdr *, int);
-	void (*block_output)(struct device *, int, const unsigned char *, int);
-	void (*block_input)(struct device *, int, struct sk_buff *, int);
+	void (*reset_8390)(struct net_device *);
+	void (*get_8390_hdr)(struct net_device *, struct e8390_pkt_hdr *, int);
+	void (*block_output)(struct net_device *, int, const unsigned char *, int);
+	void (*block_input)(struct net_device *, int, struct sk_buff *, int);
 	unsigned char mcfilter[8];
 	unsigned open:1;
 	unsigned word16:1;  		/* We have the 16-bit (vs 8-bit) version of the card. */
diff -u --recursive --new-file v2.3.13/linux/drivers/net/Makefile linux/drivers/net/Makefile
--- v2.3.13/linux/drivers/net/Makefile	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/Makefile	Thu Aug 12 09:46:13 1999
@@ -1136,6 +1136,15 @@
   endif
 endif
 
+ifeq ($(CONFIG_CYCLADES_SYNC),m)
+  MX_OBJS += cycx_drv.o
+  M_OBJS += cyclomx.o
+  CYCLOMX_OBJS = cycx_main.o
+  ifeq ($(CONFIG_CYCLOMX_X25),y)
+    CYCLOMX_OBJS += cycx_x25.o
+  endif
+endif
+
 ifeq ($(CONFIG_X25_ASY),y)
 L_OBJS += x25_asy.o
 else
diff -u --recursive --new-file v2.3.13/linux/drivers/net/Space.c linux/drivers/net/Space.c
--- v2.3.13/linux/drivers/net/Space.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/Space.c	Wed Aug 18 11:36:41 1999
@@ -39,107 +39,107 @@
    ethernet adaptor have the name "eth[0123...]".
    */
 
-extern int ne2_probe(struct device *dev);
-extern int tulip_probe(struct device *dev);
-extern int hp100_probe(struct device *dev);
-extern int ultra_probe(struct device *dev);
-extern int ultra32_probe(struct device *dev);
-extern int ultramca_probe(struct device *dev);
-extern int wd_probe(struct device *dev);
-extern int el2_probe(struct device *dev);
-extern int ne2k_pci_probe(struct device *dev);
-extern int ne_probe(struct device *dev);
-extern int hp_probe(struct device *dev);
-extern int hp_plus_probe(struct device *dev);
-extern int znet_probe(struct device *);
-extern int express_probe(struct device *);
-extern int eepro_probe(struct device *);
-extern int eepro100_probe(struct device *);
-extern int el3_probe(struct device *);
-extern int at1500_probe(struct device *);
-extern int pcnet32_probe(struct device *);
-extern int at1700_probe(struct device *);
-extern int fmv18x_probe(struct device *);
-extern int eth16i_probe(struct device *);
-extern int depca_probe(struct device *);
-extern int i82596_probe(struct device *);
-extern int ewrk3_probe(struct device *);
-extern int de4x5_probe(struct device *);
-extern int el1_probe(struct device *);
-extern int wavelan_probe(struct device *);
-extern int arlan_probe(struct device *);
-extern int el16_probe(struct device *);
-extern int elmc_probe(struct device *);
-extern int skmca_probe(struct device *);
-extern int elplus_probe(struct device *);
-extern int ac3200_probe(struct device *);
-extern int es_probe(struct device *);
-extern int lne390_probe(struct device *);
-extern int ne3210_probe(struct device *);
-extern int e2100_probe(struct device *);
-extern int ni5010_probe(struct device *);
-extern int ni52_probe(struct device *);
-extern int ni65_probe(struct device *);
-extern int sonic_probe(struct device *);
-extern int SK_init(struct device *);
-extern int seeq8005_probe(struct device *);
-extern int tc59x_probe(struct device *);
-extern int dgrs_probe(struct device *);
-extern int smc_init( struct device * );
-extern int sparc_lance_probe(struct device *);
-extern int happy_meal_probe(struct device *);
-extern int qec_probe(struct device *);
-extern int bigmac_probe(struct device *);
-extern int myri_sbus_probe(struct device *);
-extern int sgiseeq_probe(struct device *);
-extern int atarilance_probe(struct device *);
-extern int a2065_probe(struct device *);
-extern int ariadne_probe(struct device *);
-extern int ariadne2_probe(struct device *);
-extern int hydra_probe(struct device *);
-extern int apne_probe(struct device *);
-extern int bionet_probe(struct device *);
-extern int pamsnet_probe(struct device *);
-extern int tlan_probe(struct device *);
-extern int mace_probe(struct device *);
-extern int bmac_probe(struct device *);
-extern int cs89x0_probe(struct device *dev);
-extern int ethertap_probe(struct device *dev);
-extern int ether1_probe (struct device *dev);
-extern int ether3_probe (struct device *dev);
-extern int etherh_probe (struct device *dev);
-extern int am79c961_probe(struct device *dev);
-extern int epic100_probe(struct device *dev);
-extern int rtl8139_probe(struct device *dev);
-extern int hplance_probe(struct device *dev);
-extern int bagetlance_probe(struct device *);
-extern int dec_lance_probe(struct device *);
-extern int mvme147lance_probe(struct device *dev);
-extern int via_rhine_probe(struct device *dev);
-extern int tc515_probe(struct device *dev);
-extern int lance_probe(struct device *dev);
-extern int rcpci_probe(struct device *);
-extern int mac_onboard_sonic_probe(struct device *dev);
+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 *);
+extern int depca_probe(struct net_device *);
+extern int i82596_probe(struct net_device *);
+extern int ewrk3_probe(struct net_device *);
+extern int de4x5_probe(struct net_device *);
+extern int el1_probe(struct net_device *);
+extern int wavelan_probe(struct net_device *);
+extern int arlan_probe(struct net_device *);
+extern int el16_probe(struct net_device *);
+extern int elmc_probe(struct net_device *);
+extern int skmca_probe(struct net_device *);
+extern int elplus_probe(struct net_device *);
+extern int ac3200_probe(struct net_device *);
+extern int es_probe(struct net_device *);
+extern int lne390_probe(struct net_device *);
+extern int ne3210_probe(struct net_device *);
+extern int e2100_probe(struct net_device *);
+extern int ni5010_probe(struct net_device *);
+extern int ni52_probe(struct net_device *);
+extern int ni65_probe(struct net_device *);
+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 a2065_probe(struct net_device *);
+extern int ariadne_probe(struct net_device *);
+extern int ariadne2_probe(struct net_device *);
+extern int hydra_probe(struct net_device *);
+extern int apne_probe(struct net_device *);
+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 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 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 rcpci_probe(struct net_device *);
+extern int mac_onboard_sonic_probe(struct net_device *dev);
 
 /* Gigabit Ethernet adapters */
-extern int yellowfin_probe(struct device *dev);
-extern int acenic_probe(struct device *dev);
+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 device *);
-extern int de600_probe(struct device *);
-extern int de620_probe(struct device *);
+extern int atp_init(struct net_device *);
+extern int de600_probe(struct net_device *);
+extern int de620_probe(struct net_device *);
 
 /* FDDI adapters */
-extern int dfx_probe(struct device *dev);
-extern int apfddi_init(struct device *dev);
+extern int dfx_probe(struct net_device *dev);
+extern int apfddi_init(struct net_device *dev);
 
 /* HIPPI boards */
-extern int rr_hippi_probe(struct device *);
+extern int rr_hippi_probe(struct net_device *);
 
 struct devprobe
 {
-	int (*probe)(struct device *dev);
+	int (*probe)(struct net_device *dev);
 	int status;	/* non-zero if autoprobe has failed */
 };
 
@@ -150,7 +150,7 @@
  * autoprobe (i.e. a probe that fails to find a card when autoprobing
  * will not be asked to autoprobe again).  It exits when a card is found.
  */
-static int __init probe_list(struct device *dev, struct devprobe *plist)
+static int __init probe_list(struct net_device *dev, struct devprobe *plist)
 {
 	struct devprobe *p = plist;
 	unsigned long base_addr = dev->base_addr;
@@ -486,7 +486,7 @@
  * Unified ethernet device probe, segmented per architecture and
  * per bus interface.
  */
-static int __init ethif_probe(struct device *dev)
+static int __init ethif_probe(struct net_device *dev)
 {
 	unsigned long base_addr = dev->base_addr;
 
@@ -534,7 +534,7 @@
 }
 
 #ifdef CONFIG_FDDI
-static int __init fddiif_probe(struct device *dev)
+static int __init fddiif_probe(struct net_device *dev)
 {
     unsigned long base_addr = dev->base_addr;
 
@@ -556,7 +556,7 @@
 #endif
 
 #ifdef CONFIG_HIPPI
-static int hippi_probe(struct device *dev)
+static int hippi_probe(struct net_device *dev)
 {
 	/*
 	 * Damn this is ugly.
@@ -579,22 +579,22 @@
 #endif
 
 #ifdef CONFIG_ETHERTAP
-    static struct device tap0_dev = { "tap0", 0, 0, 0, 0, NETLINK_TAPBASE, 0, 0, 0, 0, NEXT_DEV, ethertap_probe, };
+    static struct net_device tap0_dev = { "tap0", 0, 0, 0, 0, NETLINK_TAPBASE, 0, 0, 0, 0, NEXT_DEV, ethertap_probe, };
 #   undef NEXT_DEV
 #   define NEXT_DEV	(&tap0_dev)
 #endif
 
 #ifdef CONFIG_SDLA
-    extern int sdla_init(struct device *);
-    static struct device sdla0_dev = { "sdla0", 0, 0, 0, 0, 0, 0, 0, 0, 0, NEXT_DEV, sdla_init, };
+    extern int sdla_init(struct net_device *);
+    static struct net_device sdla0_dev = { "sdla0", 0, 0, 0, 0, 0, 0, 0, 0, 0, NEXT_DEV, sdla_init, };
 
 #   undef NEXT_DEV
 #   define NEXT_DEV	(&sdla0_dev)
 #endif
 
 #if defined(CONFIG_LTPC)
-    extern int ltpc_probe(struct device *);
-    static struct device dev_ltpc = {
+    extern int ltpc_probe(struct net_device *);
+    static struct net_device dev_ltpc = {
         "lt0\0   ",
                 0, 0, 0, 0,
                 0x0, 0,
@@ -604,17 +604,17 @@
 #endif  /* LTPC */
 
 #if defined(CONFIG_COPS)
-    extern int cops_probe(struct device *);
-    static struct device cops2_dev = { "lt2", 0, 0, 0, 0, 0x0, 0, 0, 0, 0, NEXT_DEV, cops_probe };
-    static struct device cops1_dev = { "lt1", 0, 0, 0, 0, 0x0, 0, 0, 0, 0, &cops2_dev, cops_probe };
-    static struct device cops0_dev = { "lt0", 0, 0, 0, 0, 0x0, 0, 0, 0, 0, &cops1_dev, cops_probe };
+    extern int cops_probe(struct net_device *);
+    static struct net_device cops2_dev = { "lt2", 0, 0, 0, 0, 0x0, 0, 0, 0, 0, NEXT_DEV, cops_probe };
+    static struct net_device cops1_dev = { "lt1", 0, 0, 0, 0, 0x0, 0, 0, 0, 0, &cops2_dev, cops_probe };
+    static struct net_device cops0_dev = { "lt0", 0, 0, 0, 0, 0x0, 0, 0, 0, 0, &cops1_dev, cops_probe };
 #   undef NEXT_DEV
 #   define NEXT_DEV     (&cops0_dev)
 #endif  /* COPS */
 
 #if defined(CONFIG_IPDDP)
-    extern int ipddp_init(struct device *dev);
-    static struct device dev_ipddp = {
+    extern int ipddp_init(struct net_device *dev);
+    static struct net_device dev_ipddp = {
         "ipddp0\0   ",
                 0, 0, 0, 0,
                 0x0, 0,
@@ -637,22 +637,22 @@
 
 #define ETH_NOPROBE_ADDR 0xffe0
 
-static struct device eth7_dev = {
+static struct net_device eth7_dev = {
     "eth7", 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, NEXT_DEV, ethif_probe };
-static struct device eth6_dev = {
+static struct net_device eth6_dev = {
     "eth6", 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, &eth7_dev, ethif_probe };
-static struct device eth5_dev = {
+static struct net_device eth5_dev = {
     "eth5", 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, &eth6_dev, ethif_probe };
-static struct device eth4_dev = {
+static struct net_device eth4_dev = {
     "eth4", 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, &eth5_dev, ethif_probe };
-static struct device eth3_dev = {
+static struct net_device eth3_dev = {
     "eth3", 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, &eth4_dev, ethif_probe };
-static struct device eth2_dev = {
+static struct net_device eth2_dev = {
     "eth2", 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, &eth3_dev, ethif_probe };
-static struct device eth1_dev = {
+static struct net_device eth1_dev = {
     "eth1", 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, &eth2_dev, ethif_probe };
 
-static struct device eth0_dev = {
+static struct net_device eth0_dev = {
     "eth0", 0, 0, 0, 0, ETH0_ADDR, ETH0_IRQ, 0, 0, 0, &eth1_dev, ethif_probe };
 
 #   undef NEXT_DEV
@@ -661,8 +661,8 @@
 #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 device *);
-static struct device slip_bootstrap = {
+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)
@@ -671,8 +671,8 @@
 #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 device *);
-static struct device x25_asy_bootstrap = {
+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)
@@ -681,48 +681,48 @@
 #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 device *);
-static struct device mkiss_bootstrap = {
+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 device *);
-static struct device yam_bootstrap = {
+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 device *);
-static struct device strip_bootstrap = {
+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 device *);
-static struct device ppp_bootstrap = {
+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 device *dev);
-    static struct device dummy_dev = {
+    extern int dummy_init(struct net_device *dev);
+    static struct net_device dummy_dev = {
 	"dummy", 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 device *dev);
-struct device eql_dev = {
+extern int eql_init(struct net_device *dev);
+struct net_device eql_dev = {
   "eql",			/* Master device for IP traffic load 
 				   balancing */
   0x0, 0x0, 0x0, 0x0,		/* recv end/start; mem end/start */
@@ -738,11 +738,11 @@
 
 #ifdef CONFIG_TR
 /* Token-ring device probe */
-extern int ibmtr_probe(struct device *);
-extern int olympic_probe(struct device *);
+extern int ibmtr_probe(struct net_device *);
+extern int olympic_probe(struct net_device *);
 
 static int
-trif_probe(struct device *dev)
+trif_probe(struct net_device *dev)
 {
     if (1
 #ifdef CONFIG_IBMTR
@@ -762,21 +762,21 @@
     }
     return 0;
 }
-static struct device tr7_dev = {
+static struct net_device tr7_dev = {
     "tr7",0,0,0,0,0,0,0,0,0, NEXT_DEV, trif_probe };
-static struct device tr6_dev = {
+static struct net_device tr6_dev = {
     "tr6",0,0,0,0,0,0,0,0,0, &tr7_dev, trif_probe };
-static struct device tr5_dev = {
+static struct net_device tr5_dev = {
     "tr5",0,0,0,0,0,0,0,0,0, &tr6_dev, trif_probe };
-static struct device tr4_dev = {
+static struct net_device tr4_dev = {
     "tr4",0,0,0,0,0,0,0,0,0, &tr5_dev, trif_probe };
-static struct device tr3_dev = {
+static struct net_device tr3_dev = {
     "tr3",0,0,0,0,0,0,0,0,0, &tr4_dev, trif_probe };
-static struct device tr2_dev = {
+static struct net_device tr2_dev = {
     "tr2",0,0,0,0,0,0,0,0,0, &tr3_dev, trif_probe };
-static struct device tr1_dev = {
+static struct net_device tr1_dev = {
     "tr1",0,0,0,0,0,0,0,0,0, &tr2_dev, trif_probe };
-static struct device tr0_dev = {
+static struct net_device tr0_dev = {
     "tr0",0,0,0,0,0,0,0,0,0, &tr1_dev, trif_probe };
 #   undef       NEXT_DEV
 #   define      NEXT_DEV        (&tr0_dev)
@@ -784,34 +784,34 @@
 #endif 
 
 #ifdef CONFIG_FDDI
-	static struct device fddi7_dev =
+	static struct net_device fddi7_dev =
 		{"fddi7", 0, 0, 0, 0, 0, 0, 0, 0, 0, NEXT_DEV, fddiif_probe};
-	static struct device fddi6_dev =
+	static struct net_device fddi6_dev =
 		{"fddi6", 0, 0, 0, 0, 0, 0, 0, 0, 0, &fddi7_dev, fddiif_probe};
-	static struct device fddi5_dev =
+	static struct net_device fddi5_dev =
 		{"fddi5", 0, 0, 0, 0, 0, 0, 0, 0, 0, &fddi6_dev, fddiif_probe};
-	static struct device fddi4_dev =
+	static struct net_device fddi4_dev =
 		{"fddi4", 0, 0, 0, 0, 0, 0, 0, 0, 0, &fddi5_dev, fddiif_probe};
-	static struct device fddi3_dev =
+	static struct net_device fddi3_dev =
 		{"fddi3", 0, 0, 0, 0, 0, 0, 0, 0, 0, &fddi4_dev, fddiif_probe};
-	static struct device fddi2_dev =
+	static struct net_device fddi2_dev =
 		{"fddi2", 0, 0, 0, 0, 0, 0, 0, 0, 0, &fddi3_dev, fddiif_probe};
-	static struct device fddi1_dev =
+	static struct net_device fddi1_dev =
 		{"fddi1", 0, 0, 0, 0, 0, 0, 0, 0, 0, &fddi2_dev, fddiif_probe};
-	static struct device fddi0_dev =
+	static struct net_device fddi0_dev =
 		{"fddi0", 0, 0, 0, 0, 0, 0, 0, 0, 0, &fddi1_dev, fddiif_probe};
 #undef	NEXT_DEV
 #define	NEXT_DEV	(&fddi0_dev)
 #endif 
 
 #ifdef CONFIG_HIPPI
-	static struct device hip3_dev =
+	static struct net_device hip3_dev =
 		{"hip3", 0, 0, 0, 0, 0, 0, 0, 0, 0, NEXT_DEV, hippi_probe};
-	static struct device hip2_dev =
+	static struct net_device hip2_dev =
 		{"hip2", 0, 0, 0, 0, 0, 0, 0, 0, 0, &hip3_dev, hippi_probe};
-	static struct device hip1_dev =
+	static struct net_device hip1_dev =
 		{"hip1", 0, 0, 0, 0, 0, 0, 0, 0, 0, &hip2_dev, hippi_probe};
-	static struct device hip0_dev =
+	static struct net_device hip0_dev =
 		{"hip0", 0, 0, 0, 0, 0, 0, 0, 0, 0, &hip1_dev, hippi_probe};
 
 #undef	NEXT_DEV
@@ -819,15 +819,15 @@
 #endif 
 
 #ifdef CONFIG_APBIF
-    extern int bif_init(struct device *dev);
-    static struct device bif_dev = {
+    extern int bif_init(struct net_device *dev);
+    static struct net_device bif_dev = {
         "bif", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NEXT_DEV, bif_init };
 #   undef       NEXT_DEV
 #   define      NEXT_DEV        (&bif_dev)
 #endif
 	
-extern int loopback_init(struct device *dev);
-struct device loopback_dev = {
+extern int loopback_init(struct net_device *dev);
+struct net_device loopback_dev = {
 	"lo",			/* Software Loopback interface		*/
 	0x0,			/* recv memory end			*/
 	0x0,			/* recv memory start			*/
@@ -840,5 +840,5 @@
 	loopback_init		/* loopback_init should set up the rest	*/
 };
 
-struct device *dev_base = &loopback_dev;
+struct net_device *dev_base = &loopback_dev;
 rwlock_t dev_base_lock = RW_LOCK_UNLOCKED;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/a2065.c linux/drivers/net/a2065.c
--- v2.3.13/linux/drivers/net/a2065.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/a2065.c	Wed Aug 18 11:36:41 1999
@@ -169,7 +169,7 @@
 
 /* Setup the Lance Rx and Tx rings */
 /* Sets dev->tbusy */
-static void lance_init_ring (struct device *dev)
+static void lance_init_ring (struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_init_block *ib = lp->init_block;
@@ -270,7 +270,7 @@
 	return 0;
 }
 
-static int lance_rx (struct device *dev)
+static int lance_rx (struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_init_block *ib = lp->init_block;
@@ -345,7 +345,7 @@
 	return 0;
 }
 
-static int lance_tx (struct device *dev)
+static int lance_tx (struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_init_block *ib = lp->init_block;
@@ -430,12 +430,12 @@
 
 static void lance_interrupt (int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev;
+	struct net_device *dev;
 	struct lance_private *lp;
 	volatile struct lance_regs *ll;
 	int csr0;
 
-	dev = (struct device *) dev_id;
+	dev = (struct net_device *) dev_id;
 
 	lp = (struct lance_private *) dev->priv;
 	ll = lp->ll;
@@ -488,9 +488,9 @@
 	dev->interrupt = 0;
 }
 
-struct device *last_dev = 0;
+struct net_device *last_dev = 0;
 
-static int lance_open (struct device *dev)
+static int lance_open (struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *)dev->priv;
 	volatile struct lance_regs *ll = lp->ll;
@@ -499,7 +499,7 @@
 	last_dev = dev;
 
 	/* Install the Interrupt handler */
-	if (request_irq(IRQ_AMIGA_PORTS, lance_interrupt, 0,
+	if (request_irq(IRQ_AMIGA_PORTS, lance_interrupt, SA_SHIRQ,
 			"a2065 Ethernet", dev))
 		return -EAGAIN;
 
@@ -521,7 +521,7 @@
 	return status;
 }
 
-static int lance_close (struct device *dev)
+static int lance_close (struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_regs *ll = lp->ll;
@@ -541,7 +541,7 @@
 	return 0;
 }
 
-static inline int lance_reset (struct device *dev)
+static inline int lance_reset (struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *)dev->priv;
 	volatile struct lance_regs *ll = lp->ll;
@@ -564,7 +564,7 @@
 	return status;
 }
 
-static int lance_start_xmit (struct sk_buff *skb, struct device *dev)
+static int lance_start_xmit (struct sk_buff *skb, struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *)dev->priv;
 	volatile struct lance_regs *ll = lp->ll;
@@ -644,7 +644,7 @@
 	return status;
 }
 
-static struct net_device_stats *lance_get_stats (struct device *dev)
+static struct net_device_stats *lance_get_stats (struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 
@@ -652,7 +652,7 @@
 }
 
 /* taken from the depca driver */
-static void lance_load_multicast (struct device *dev)
+static void lance_load_multicast (struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_init_block *ib = lp->init_block;
@@ -702,7 +702,7 @@
 	return;
 }
 
-static void lance_set_multicast (struct device *dev)
+static void lance_set_multicast (struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_init_block *ib = lp->init_block;
@@ -739,7 +739,7 @@
 	mark_bh(NET_BH);
 }
 
-int __init a2065_probe(struct device *dev)
+int __init a2065_probe(struct net_device *dev)
 {
 	unsigned int key, is_cbm;
 	const struct ConfigDev *cd;
@@ -821,7 +821,7 @@
 #ifdef MODULE
 static char devicename[9] = { 0, };
 
-static struct device a2065_dev =
+static struct net_device a2065_dev =
 {
 	devicename,			/* filled in by register_netdev() */
 	0, 0, 0, 0,			/* memory */
diff -u --recursive --new-file v2.3.13/linux/drivers/net/ac3200.c linux/drivers/net/ac3200.c
--- v2.3.13/linux/drivers/net/ac3200.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/ac3200.c	Wed Aug 18 11:36:41 1999
@@ -74,19 +74,19 @@
 #define AC_START_PG		0x00	/* First page of 8390 TX buffer */
 #define AC_STOP_PG		0x80	/* Last page +1 of the 8390 RX ring */
 
-int ac3200_probe(struct device *dev);
-static int ac_probe1(int ioaddr, struct device *dev);
+int ac3200_probe(struct net_device *dev);
+static int ac_probe1(int ioaddr, struct net_device *dev);
 
-static int ac_open(struct device *dev);
-static void ac_reset_8390(struct device *dev);
-static void ac_block_input(struct device *dev, int count,
+static int ac_open(struct net_device *dev);
+static void ac_reset_8390(struct net_device *dev);
+static void ac_block_input(struct net_device *dev, int count,
 					struct sk_buff *skb, int ring_offset);
-static void ac_block_output(struct device *dev, const int count,
+static void ac_block_output(struct net_device *dev, const int count,
 							const unsigned char *buf, const int start_page);
-static void ac_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
+static void ac_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
 					int ring_page);
 
-static int ac_close_card(struct device *dev);
+static int ac_close_card(struct net_device *dev);
 
 
 /*	Probe for the AC3200.
@@ -95,7 +95,7 @@
 	or the unique value in the station address PROM.
 	*/
 
-int __init ac3200_probe(struct device *dev)
+int __init ac3200_probe(struct net_device *dev)
 {
 	unsigned short ioaddr = dev->base_addr;
 
@@ -117,7 +117,7 @@
 	return ENODEV;
 }
 
-static int __init ac_probe1(int ioaddr, struct device *dev)
+static int __init ac_probe1(int ioaddr, struct net_device *dev)
 {
 	int i;
 
@@ -254,7 +254,7 @@
 	return 0;
 }
 
-static int ac_open(struct device *dev)
+static int ac_open(struct net_device *dev)
 {
 #ifdef notyet
 	/* Someday we may enable the IRQ and shared memory here. */
@@ -271,7 +271,7 @@
 	return 0;
 }
 
-static void ac_reset_8390(struct device *dev)
+static void ac_reset_8390(struct net_device *dev)
 {
 	ushort ioaddr = dev->base_addr;
 
@@ -290,7 +290,7 @@
    the start of a page, so we optimize accordingly. */
 
 static void
-ac_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+ac_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 {
 	unsigned long hdr_start = dev->mem_start + ((ring_page - AC_START_PG)<<8);
 	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
@@ -299,7 +299,7 @@
 /*  Block input and output are easy on shared memory ethercards, the only
 	complication is when the ring buffer wraps. */
 
-static void ac_block_input(struct device *dev, int count, struct sk_buff *skb,
+static void ac_block_input(struct net_device *dev, int count, struct sk_buff *skb,
 						  int ring_offset)
 {
 	unsigned long xfer_start = dev->mem_start + ring_offset - (AC_START_PG<<8);
@@ -316,7 +316,7 @@
 	}
 }
 
-static void ac_block_output(struct device *dev, int count,
+static void ac_block_output(struct net_device *dev, int count,
 							const unsigned char *buf, int start_page)
 {
 	unsigned long shmem = dev->mem_start + ((start_page - AC_START_PG)<<8);
@@ -324,7 +324,7 @@
 	memcpy_toio(shmem, buf, count);
 }
 
-static int ac_close_card(struct device *dev)
+static int ac_close_card(struct net_device *dev)
 {
 	dev->start = 0;
 	dev->tbusy = 1;
@@ -349,7 +349,7 @@
 #define MAX_AC32_CARDS	4	/* Max number of AC32 cards per module */
 #define NAMELEN		8	/* # of chars for storing dev->name */
 static char namelist[NAMELEN * MAX_AC32_CARDS] = { 0, };
-static struct device dev_ac32[MAX_AC32_CARDS] = {
+static struct net_device dev_ac32[MAX_AC32_CARDS] = {
 	{
 		NULL,		/* assign a chunk of namelist[] below */
 		0, 0, 0, 0,
@@ -371,7 +371,7 @@
 	int this_dev, found = 0;
 
 	for (this_dev = 0; this_dev < MAX_AC32_CARDS; this_dev++) {
-		struct device *dev = &dev_ac32[this_dev];
+		struct net_device *dev = &dev_ac32[this_dev];
 		dev->name = namelist+(NAMELEN*this_dev);
 		dev->irq = irq[this_dev];
 		dev->base_addr = io[this_dev];
@@ -399,7 +399,7 @@
 	int this_dev;
 
 	for (this_dev = 0; this_dev < MAX_AC32_CARDS; this_dev++) {
-		struct device *dev = &dev_ac32[this_dev];
+		struct net_device *dev = &dev_ac32[this_dev];
 		if (dev->priv != NULL) {
 			void *priv = dev->priv;
 			/* Someday free_irq may be in ac_close_card() */
diff -u --recursive --new-file v2.3.13/linux/drivers/net/acenic.c linux/drivers/net/acenic.c
--- v2.3.13/linux/drivers/net/acenic.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/acenic.c	Wed Aug 18 11:36:41 1999
@@ -173,11 +173,11 @@
 
 static const char __initdata *version = "acenic.c: v0.32 03/15/99  Jes Sorensen (Jes.Sorensen@cern.ch)\n";
 
-static struct device *root_dev = NULL;
+static struct net_device *root_dev = NULL;
 
 static int probed __initdata = 0;
 
-int __init acenic_probe (struct device *dev)
+int __init acenic_probe (struct net_device *dev)
 {
 	int boards_found = 0;
 	int version_disp;
@@ -363,7 +363,7 @@
 {
 	struct ace_private *ap;
 	struct ace_regs *regs;
-	struct device *next;
+	struct net_device *next;
 	short i;
 	unsigned long flags;
 
@@ -423,7 +423,7 @@
 }
 
 
-static int __init ace_init(struct device *dev, int board_idx)
+static int __init ace_init(struct net_device *dev, int board_idx)
 {
 	struct ace_private *ap;
 	struct ace_regs *regs;
@@ -802,7 +802,7 @@
  */
 static void ace_timer(unsigned long data)
 {
-	struct device *dev = (struct device *)data;
+	struct net_device *dev = (struct net_device *)data;
 	struct ace_private *ap = (struct ace_private *)dev->priv;
 	struct ace_regs *regs = ap->regs;
 
@@ -837,7 +837,7 @@
 /*
  * Load the standard rx ring.
  */
-static int ace_load_std_rx_ring(struct device *dev)
+static int ace_load_std_rx_ring(struct net_device *dev)
 {
 	struct ace_private *ap;
 	struct ace_regs *regs;
@@ -906,7 +906,7 @@
  * Load the jumbo rx ring, this may happen at any time if the MTU
  * is changed to a value > 1500.
  */
-static int ace_load_jumbo_rx_ring(struct device *dev)
+static int ace_load_jumbo_rx_ring(struct net_device *dev)
 {
 	struct ace_private *ap;
 	struct ace_regs *regs;
@@ -962,7 +962,7 @@
  * Tell the firmware not to accept jumbos and flush the jumbo ring.
  * This function must be called with the spinlock held.
  */
-static int ace_flush_jumbo_rx_ring(struct device *dev)
+static int ace_flush_jumbo_rx_ring(struct net_device *dev)
 {
 	struct ace_private *ap;
 	struct ace_regs *regs;
@@ -998,7 +998,7 @@
  * events) and are handled here, outside the main interrupt handler,
  * to reduce the size of the handler.
  */
-static u32 ace_handle_event(struct device *dev, u32 evtcsm, u32 evtprd)
+static u32 ace_handle_event(struct net_device *dev, u32 evtcsm, u32 evtprd)
 {
 	struct ace_private *ap;
 
@@ -1059,7 +1059,7 @@
 }
 
 
-static int ace_rx_int(struct device *dev, u32 rxretprd, u32 rxretcsm)
+static int ace_rx_int(struct net_device *dev, u32 rxretprd, u32 rxretcsm)
 {
 	struct ace_private *ap = (struct ace_private *)dev->priv;
 	struct ace_regs *regs = ap->regs;
@@ -1210,7 +1210,7 @@
 {
 	struct ace_private *ap;
 	struct ace_regs *regs;
-	struct device *dev = (struct device *)dev_id;
+	struct net_device *dev = (struct net_device *)dev_id;
 	u32 txcsm, rxretcsm, rxretprd;
 	u32 evtcsm, evtprd;
 
@@ -1293,7 +1293,7 @@
 }
 
 
-static int ace_open(struct device *dev)
+static int ace_open(struct net_device *dev)
 {
 	struct ace_private *ap;
 	struct ace_regs *regs;
@@ -1355,7 +1355,7 @@
 }
 
 
-static int ace_close(struct device *dev)
+static int ace_close(struct net_device *dev)
 {
 	struct ace_private *ap;
 	struct ace_regs *regs;
@@ -1405,7 +1405,7 @@
 }
 
 
-static int ace_start_xmit(struct sk_buff *skb, struct device *dev)
+static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ace_private *ap = (struct ace_private *)dev->priv;
 	struct ace_regs *regs = ap->regs;
@@ -1450,7 +1450,7 @@
 }
 
 
-static int ace_change_mtu(struct device *dev, int new_mtu)
+static int ace_change_mtu(struct net_device *dev, int new_mtu)
 {
 	struct ace_private *ap = dev->priv;
 	struct ace_regs *regs = ap->regs;
@@ -1486,7 +1486,7 @@
 /*
  * Set the hardware MAC address.
  */
-static int ace_set_mac_addr(struct device *dev, void *p)
+static int ace_set_mac_addr(struct net_device *dev, void *p)
 {
 	struct sockaddr *addr=p;
 	struct ace_regs *regs;
@@ -1512,7 +1512,7 @@
 }
 
 
-static void ace_set_multicast_list(struct device *dev)
+static void ace_set_multicast_list(struct net_device *dev)
 {
 	struct ace_private *ap = dev->priv;
 	struct ace_regs *regs = ap->regs;
@@ -1566,7 +1566,7 @@
 }
 
 
-static struct net_device_stats *ace_get_stats(struct device *dev)
+static struct net_device_stats *ace_get_stats(struct net_device *dev)
 {
 	struct ace_private *ap = dev->priv;
 
@@ -1642,7 +1642,7 @@
  * This operation requires the NIC to be halted and is performed with
  * interrupts disabled and with the spinlock hold.
  */
-int __init ace_load_firmware(struct device *dev)
+int __init ace_load_firmware(struct net_device *dev)
 {
 	struct ace_private *ap;
 	struct ace_regs *regs;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/acenic.h linux/drivers/net/acenic.h
--- v2.3.13/linux/drivers/net/acenic.h	Mon Mar 22 08:08:12 1999
+++ linux/drivers/net/acenic.h	Wed Aug 18 11:36:45 1999
@@ -634,7 +634,7 @@
 				__attribute__ ((aligned (L1_CACHE_BYTES)));
 	volatile u32		tx_csm
 				__attribute__ ((aligned (L1_CACHE_BYTES)));
-	struct device		*next
+	struct net_device		*next
 				__attribute__ ((aligned (L1_CACHE_BYTES)));
 	unsigned char		*trace_buf;
 	int			fw_running, fw_up, jumbo, promisc, mcast_all;
@@ -654,21 +654,21 @@
 /*
  * Prototypes
  */
-static int ace_init(struct device *dev, int board_idx);
-static int ace_load_std_rx_ring(struct device *dev);
-static int ace_load_jumbo_rx_ring(struct device *dev);
-static int ace_flush_jumbo_rx_ring(struct device *dev);
+static int ace_init(struct net_device *dev, int board_idx);
+static int ace_load_std_rx_ring(struct net_device *dev);
+static int ace_load_jumbo_rx_ring(struct net_device *dev);
+static int ace_flush_jumbo_rx_ring(struct net_device *dev);
 static void ace_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static int ace_load_firmware(struct device *dev);
-static int ace_open(struct device *dev);
-static int ace_start_xmit(struct sk_buff *skb, struct device *dev);
-static int ace_close(struct device *dev);
+static int ace_load_firmware(struct net_device *dev);
+static int ace_open(struct net_device *dev);
+static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int ace_close(struct net_device *dev);
 static void ace_timer(unsigned long data);
 static void ace_dump_trace(struct ace_private *ap);
-static void ace_set_multicast_list(struct device *dev);
-static int ace_change_mtu(struct device *dev, int new_mtu);
-static int ace_set_mac_addr(struct device *dev, void *p);
-static struct net_device_stats *ace_get_stats(struct device *dev);
+static void ace_set_multicast_list(struct net_device *dev);
+static int ace_change_mtu(struct net_device *dev, int new_mtu);
+static int ace_set_mac_addr(struct net_device *dev, void *p);
+static struct net_device_stats *ace_get_stats(struct net_device *dev);
 static u8 read_eeprom_byte(struct ace_regs *regs, unsigned long offset);
 
 #endif /* _ACENIC_H_ */
diff -u --recursive --new-file v2.3.13/linux/drivers/net/am79c961a.c linux/drivers/net/am79c961a.c
--- v2.3.13/linux/drivers/net/am79c961a.c	Fri May  8 00:42:39 1998
+++ linux/drivers/net/am79c961a.c	Wed Aug 18 11:36:41 1999
@@ -36,7 +36,7 @@
 static unsigned int net_debug = NET_DEBUG;
 
 static void
-am79c961_setmulticastlist (struct device *dev);
+am79c961_setmulticastlist (struct net_device *dev);
 
 static char *version = "am79c961 ethernet driver (c) 1995 R.M.King v0.00\n";
 
@@ -69,7 +69,7 @@
 		" : : "r" ((val) & 0xffff), "r" (0xe0000000 + ((off) << 1)));
 
 static inline void
-am_writebuffer(struct device *dev, unsigned int offset, unsigned char *buf, unsigned int length)
+am_writebuffer(struct net_device *dev, unsigned int offset, unsigned char *buf, unsigned int length)
 {
 	offset = 0xe0000000 + (offset << 1);
 	length = (length + 1) & ~1;
@@ -115,7 +115,7 @@
 }
 
 static inline unsigned short
-am_readword (struct device *dev, unsigned long off)
+am_readword (struct net_device *dev, unsigned long off)
 {
 	unsigned long address = 0xe0000000 + (off << 1);
 	unsigned short val;
@@ -127,7 +127,7 @@
 }
 
 static inline void
-am_readbuffer(struct device *dev, unsigned int offset, unsigned char *buf, unsigned int length)
+am_readbuffer(struct net_device *dev, unsigned int offset, unsigned char *buf, unsigned int length)
 {
 	offset = 0xe0000000 + (offset << 1);
 	length = (length + 1) & ~1;
@@ -168,7 +168,7 @@
 }
 
 static int
-am79c961_ramtest(struct device *dev, unsigned int val)
+am79c961_ramtest(struct net_device *dev, unsigned int val)
 {
 	unsigned char *buffer = kmalloc (65536, GFP_KERNEL);
 	int i, error = 0, errorcount = 0;
@@ -196,7 +196,7 @@
 }
 
 static void
-am79c961_init_for_open(struct device *dev)
+am79c961_init_for_open(struct net_device *dev)
 {
 	struct dev_priv *priv = (struct dev_priv *)dev->priv;
 	unsigned long hdr_addr, first_free_addr;
@@ -264,7 +264,7 @@
 }
 
 static int
-am79c961_init(struct device *dev)
+am79c961_init(struct net_device *dev)
 {
 	unsigned long flags;
 
@@ -286,7 +286,7 @@
  * This is the real probe routine.
  */
 static int
-am79c961_probe1(struct device *dev)
+am79c961_probe1(struct net_device *dev)
 {
 	static unsigned version_printed = 0;
 	struct dev_priv *priv;
@@ -351,7 +351,7 @@
 }
 
 int
-am79c961_probe(struct device *dev)
+am79c961_probe(struct net_device *dev)
 {
 	static int initialised = 0;
 
@@ -374,7 +374,7 @@
  * there is non-reboot way to recover if something goes wrong.
  */
 static int
-am79c961_open(struct device *dev)
+am79c961_open(struct net_device *dev)
 {
 	struct dev_priv *priv = (struct dev_priv *)dev->priv;
 
@@ -397,7 +397,7 @@
  * The inverse routine to am79c961_open().
  */
 static int
-am79c961_close(struct device *dev)
+am79c961_close(struct net_device *dev)
 {
 	dev->tbusy = 1;
 	dev->start = 0;
@@ -414,7 +414,7 @@
  * Get the current statistics.	This may be called with the card open or
  * closed.
  */
-static struct enet_statistics *am79c961_getstats (struct device *dev)
+static struct enet_statistics *am79c961_getstats (struct net_device *dev)
 {
 	struct dev_priv *priv = (struct dev_priv *)dev->priv;
 	return &priv->stats;
@@ -426,7 +426,7 @@
  * We don't attempt any packet filtering.  The card may have a SEEQ 8004
  * in which does not have the other ethernet address registers present...
  */
-static void am79c961_setmulticastlist (struct device *dev)
+static void am79c961_setmulticastlist (struct net_device *dev)
 {
 	unsigned long flags;
 	int i;
@@ -446,7 +446,7 @@
  * Transmit a packet
  */
 static int
-am79c961_sendpacket(struct sk_buff *skb, struct device *dev)
+am79c961_sendpacket(struct sk_buff *skb, struct net_device *dev)
 {
 	struct dev_priv *priv = (struct dev_priv *)dev->priv;
 
@@ -494,7 +494,7 @@
 static void
 am79c961_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev = (struct device *)dev_id;
+	struct net_device *dev = (struct net_device *)dev_id;
 	struct dev_priv *priv = (struct dev_priv *)dev->priv;
 	unsigned int status;
 
@@ -527,7 +527,7 @@
  * If we have a good packet(s), get it/them out of the buffers.
  */
 static void
-am79c961_rx(struct device *dev, struct dev_priv *priv)
+am79c961_rx(struct net_device *dev, struct dev_priv *priv)
 {
 	unsigned long hdraddr;
 	unsigned long pktaddr;
@@ -589,7 +589,7 @@
  * Update stats for the transmitted packet
  */
 static void
-am79c961_tx(struct device *dev, struct dev_priv *priv)
+am79c961_tx(struct net_device *dev, struct dev_priv *priv)
 {
 	do {
 		unsigned long hdraddr;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/am79c961a.h linux/drivers/net/am79c961a.h
--- v2.3.13/linux/drivers/net/am79c961a.h	Mon Feb 16 15:50:21 1998
+++ linux/drivers/net/am79c961a.h	Wed Aug 18 11:36:45 1999
@@ -114,15 +114,15 @@
     unsigned long	txhdr;
 };
 
-extern int	am79c961_probe (struct device *dev);
-static int	am79c961_probe1 (struct device *dev);
-static int	am79c961_open (struct device *dev);
-static int	am79c961_sendpacket (struct sk_buff *skb, struct device *dev);
+extern int	am79c961_probe (struct net_device *dev);
+static int	am79c961_probe1 (struct net_device *dev);
+static int	am79c961_open (struct net_device *dev);
+static int	am79c961_sendpacket (struct sk_buff *skb, struct net_device *dev);
 static void	am79c961_interrupt (int irq, void *dev_id, struct pt_regs *regs);
-static void	am79c961_rx (struct device *dev, struct dev_priv *priv);
-static void	am79c961_tx (struct device *dev, struct dev_priv *priv);
-static int	am79c961_close (struct device *dev);
-static struct enet_statistics *am79c961_getstats (struct device *dev);
-static void	am79c961_setmulticastlist (struct device *dev);
+static void	am79c961_rx (struct net_device *dev, struct dev_priv *priv);
+static void	am79c961_tx (struct net_device *dev, struct dev_priv *priv);
+static int	am79c961_close (struct net_device *dev);
+static struct enet_statistics *am79c961_getstats (struct net_device *dev);
+static void	am79c961_setmulticastlist (struct net_device *dev);
 
 #endif
diff -u --recursive --new-file v2.3.13/linux/drivers/net/apne.c linux/drivers/net/apne.c
--- v2.3.13/linux/drivers/net/apne.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/apne.c	Wed Aug 18 11:36:41 1999
@@ -74,18 +74,18 @@
 #define NESM_STOP_PG	0x80	/* Last page +1 of RX ring */
 
 
-int apne_probe(struct device *dev);
-static int apne_probe1(struct device *dev, int ioaddr);
+int apne_probe(struct net_device *dev);
+static int apne_probe1(struct net_device *dev, int ioaddr);
 
-static int apne_open(struct device *dev);
-static int apne_close(struct device *dev);
+static int apne_open(struct net_device *dev);
+static int apne_close(struct net_device *dev);
 
-static void apne_reset_8390(struct device *dev);
-static void apne_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
+static void apne_reset_8390(struct net_device *dev);
+static void apne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
 			  int ring_page);
-static void apne_block_input(struct device *dev, int count,
+static void apne_block_input(struct net_device *dev, int count,
 								struct sk_buff *skb, int ring_offset);
-static void apne_block_output(struct device *dev, const int count,
+static void apne_block_output(struct net_device *dev, const int count,
 							const unsigned char *buf, const int start_page);
 static void apne_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 
@@ -121,7 +121,7 @@
 
 static int apne_owned = 0;	/* signal if card already owned */
 
-int __init apne_probe(struct device *dev)
+int __init apne_probe(struct net_device *dev)
 {
 #ifndef MANUAL_CONFIG
 	char tuple[8];
@@ -161,7 +161,7 @@
 
 }
 
-static int __init apne_probe1(struct device *dev, int ioaddr)
+static int __init apne_probe1(struct net_device *dev, int ioaddr)
 {
     int i;
     unsigned char SA_prom[32];
@@ -294,7 +294,8 @@
     dev->base_addr = ioaddr;
 
     /* Install the Interrupt handler */
-    if (request_irq(IRQ_AMIGA_PORTS, apne_interrupt, 0, "apne Ethernet", dev))
+    if (request_irq(IRQ_AMIGA_PORTS, apne_interrupt, SA_SHIRQ,
+		    "apne Ethernet", dev))
         return -EAGAIN;
 
 
@@ -337,7 +338,7 @@
 }
 
 static int
-apne_open(struct device *dev)
+apne_open(struct net_device *dev)
 {
     ei_open(dev);
     MOD_INC_USE_COUNT;
@@ -345,7 +346,7 @@
 }
 
 static int
-apne_close(struct device *dev)
+apne_close(struct net_device *dev)
 {
     if (ei_debug > 1)
 	printk("%s: Shutting down ethercard.\n", dev->name);
@@ -357,7 +358,7 @@
 /* Hard reset the card.  This used to pause for the same period that a
    8390 reset command required, but that shouldn't be necessary. */
 static void
-apne_reset_8390(struct device *dev)
+apne_reset_8390(struct net_device *dev)
 {
     unsigned long reset_start_time = jiffies;
 
@@ -384,7 +385,7 @@
    the start of a page, so we optimize accordingly. */
 
 static void
-apne_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+apne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 {
 
     int nic_base = dev->base_addr;
@@ -433,7 +434,7 @@
    the packet out through the "remote DMA" dataport using writeb. */
 
 static void
-apne_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
+apne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
 {
     int nic_base = dev->base_addr;
     char *buf = skb->data;
@@ -475,7 +476,7 @@
 }
 
 static void
-apne_block_output(struct device *dev, int count,
+apne_block_output(struct net_device *dev, int count,
 		const unsigned char *buf, const int start_page)
 {
     int nic_base = NE_BASE;
@@ -560,7 +561,7 @@
 #ifdef MODULE
 static char devicename[9] = {0, };
 
-static struct device apne_dev =
+static struct net_device apne_dev =
 {
 	devicename,
 	0, 0, 0, 0,
diff -u --recursive --new-file v2.3.13/linux/drivers/net/arc-rimi.c linux/drivers/net/arc-rimi.c
--- v2.3.13/linux/drivers/net/arc-rimi.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/arc-rimi.c	Wed Aug 18 11:36:41 1999
@@ -74,15 +74,15 @@
 
 /* Internal function declarations */
 
-static int arcrimi_probe(struct device *dev);
-static void arcrimi_rx(struct device *dev,int recbuf);
-static int arcrimi_found(struct device *dev,int ioaddr,int airq,u_long shmem);
-static void arcrimi_inthandler (struct device *dev);
-static int arcrimi_reset (struct device *dev, int reset_delay);
-static void arcrimi_setmask (struct device *dev, u_char mask);
-static void arcrimi_command (struct device *dev, u_char command);
-static u_char arcrimi_status (struct device *dev);
-static void arcrimi_prepare_tx(struct device *dev,u_char *hdr,int hdrlen,
+static int arcrimi_probe(struct net_device *dev);
+static void arcrimi_rx(struct net_device *dev,int recbuf);
+static int arcrimi_found(struct net_device *dev,int ioaddr,int airq,u_long shmem);
+static void arcrimi_inthandler (struct net_device *dev);
+static int arcrimi_reset (struct net_device *dev, int reset_delay);
+static void arcrimi_setmask (struct net_device *dev, u_char mask);
+static void arcrimi_command (struct net_device *dev, u_char command);
+static u_char arcrimi_status (struct net_device *dev);
+static void arcrimi_prepare_tx(struct net_device *dev,u_char *hdr,int hdrlen,
        	       char *data,int length,int daddr,int exceptA, int offset);
 static  void arcrimi_openclose(int open);
 
@@ -101,7 +101,7 @@
 MODULE_PARM (node, "i");
 #else
 void __init arcrimi_setup (char *str, int *ints);
-extern struct device arcnet_devs[];
+extern struct net_device arcnet_devs[];
 extern char arcnet_dev_names[][10];
 extern int arcnet_num_devs;
 #endif
@@ -140,7 +140,7 @@
  * them.  In fact, we can't even get their node ID automatically.  So, we
  * need to be passed a specific shmem address, IRQ, and node ID.
  */
-int __init arcrimi_probe(struct device *dev)
+int __init arcrimi_probe(struct net_device *dev)
 {
   BUGLVL(D_NORMAL) printk(version);
   BUGMSG(D_NORMAL,"Given: node %02Xh, shmem %lXh, irq %d\n",
@@ -164,10 +164,10 @@
 }
 
 
-/* Set up the struct device associated with this card.  Called after
+/* Set up the struct net_device associated with this card.  Called after
  * probing succeeds.
  */
-int __init arcrimi_found(struct device *dev,int node,int airq, u_long shmem)
+int __init arcrimi_found(struct net_device *dev,int node,int airq, u_long shmem)
 {
   struct arcnet_local *lp;
   u_long first_mirror,last_mirror;
@@ -275,7 +275,7 @@
  *
  * However, it does make sure the card is in a defined state.
  */
-int arcrimi_reset(struct device *dev,int reset_delay)
+int arcrimi_reset(struct net_device *dev,int reset_delay)
 {
   struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
   short ioaddr=dev->mem_start + 0x800;
@@ -333,21 +333,21 @@
     MOD_DEC_USE_COUNT;
 }
 
-static void arcrimi_setmask(struct device *dev, u_char mask)
+static void arcrimi_setmask(struct net_device *dev, u_char mask)
 {
   int ioaddr=dev->mem_start+0x800;
 
   AINTMASK(mask);
 }
 
-static u_char arcrimi_status(struct device *dev)
+static u_char arcrimi_status(struct net_device *dev)
 {
   int ioaddr=dev->mem_start+0x800;
 
   return ARCSTATUS;
 }
 
-static void arcrimi_command(struct device *dev, u_char cmd)
+static void arcrimi_command(struct net_device *dev, u_char cmd)
 {
   int ioaddr=dev->mem_start+0x800;
 
@@ -359,7 +359,7 @@
  * by the card.
  */
 static void
-arcrimi_inthandler(struct device *dev)
+arcrimi_inthandler(struct net_device *dev)
 {
   struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
   int ioaddr=dev->mem_start+0x800, status, boguscount = 3, didsomething;
@@ -578,7 +578,7 @@
  */
 
 static void
-arcrimi_rx(struct device *dev,int recbuf)
+arcrimi_rx(struct net_device *dev,int recbuf)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
   int ioaddr=dev->mem_start+0x800;
@@ -636,7 +636,7 @@
  * by arcnet_go_tx.
  */
 static void
-arcrimi_prepare_tx(struct device *dev,u_char *hdr,int hdrlen,
+arcrimi_prepare_tx(struct net_device *dev,u_char *hdr,int hdrlen,
 		   char *data,int length,int daddr,int exceptA, int offset)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
@@ -734,7 +734,7 @@
 #ifdef MODULE
 
 static char devicename[9] = "";
-static struct device thiscard = {
+static struct net_device thiscard = {
   devicename, /* device name is inserted by linux/drivers/net/net_init.c */
   0, 0, 0, 0,
   0, 0,  /* I/O address, IRQ */
@@ -744,7 +744,7 @@
 
 int init_module(void)
 {
-  struct device *dev=&thiscard;
+  struct net_device *dev=&thiscard;
   if (device)
     strcpy(dev->name,device);
   else arcnet_makename(dev->name);
@@ -771,7 +771,7 @@
 
 void cleanup_module(void)
 {
-  struct device *dev=&thiscard;
+  struct net_device *dev=&thiscard;
   int ioaddr=dev->mem_start;
 
   if (dev->start) (*dev->stop)(dev);
@@ -799,7 +799,7 @@
 
 void __init arcrimi_setup (char *str, int *ints)
 {
-  struct device *dev;
+  struct net_device *dev;
 
   if (arcnet_num_devs == MAX_ARCNET_DEVS)
     {
diff -u --recursive --new-file v2.3.13/linux/drivers/net/arcnet.c linux/drivers/net/arcnet.c
--- v2.3.13/linux/drivers/net/arcnet.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/arcnet.c	Wed Aug 18 11:36:41 1999
@@ -242,16 +242,16 @@
 static int init_module(void);
 #ifdef CONFIG_ARCNET_COM90xx
 extern char com90xx_explicit;
-extern int arc90xx_probe(struct device *dev);
+extern int arc90xx_probe(struct net_device *dev);
 #endif
 #endif
 
-void arcnet_tx_done(struct device *dev, struct arcnet_local *lp);
+void arcnet_tx_done(struct net_device *dev, struct arcnet_local *lp);
 void arcnet_use_count (int open);
-void arcnet_setup(struct device *dev);
+void arcnet_setup(struct net_device *dev);
 void arcnet_makename(char *device);
-void arcnetA_continue_tx(struct device *dev);
-int arcnet_go_tx(struct device *dev,int enable_irq);
+void arcnetA_continue_tx(struct net_device *dev);
+int arcnet_go_tx(struct net_device *dev,int enable_irq);
 void arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs);
 void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr);
 
@@ -266,7 +266,7 @@
 EXPORT_SYMBOL(arcnet_rx);
 
 #if ARCNET_DEBUG_MAX & D_SKB
-void arcnet_dump_skb(struct device *dev,struct sk_buff *skb,
+void arcnet_dump_skb(struct net_device *dev,struct sk_buff *skb,
 	char *desc);
 EXPORT_SYMBOL(arcnet_dump_skb);
 #else
@@ -274,7 +274,7 @@
 #endif
 
 #if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX)
-void arcnet_dump_packet(struct device *dev,u_char *buffer,int ext,
+void arcnet_dump_packet(struct net_device *dev,u_char *buffer,int ext,
 	char *desc);
 EXPORT_SYMBOL(arcnet_dump_packet);
 #else
@@ -283,41 +283,41 @@
 
 /* Internal function prototypes */
 
-static int arcnet_open(struct device *dev);
-static int arcnet_close(struct device *dev);
-static int arcnetA_header(struct sk_buff *skb,struct device *dev,
+static int arcnet_open(struct net_device *dev);
+static int arcnet_close(struct net_device *dev);
+static int arcnetA_header(struct sk_buff *skb,struct net_device *dev,
 		unsigned short type,void *daddr,void *saddr,unsigned len);
 static int arcnetA_rebuild_header(struct sk_buff *skb);
-static int arcnet_send_packet_bad(struct sk_buff *skb,struct device *dev);
-static int arcnetA_send_packet(struct sk_buff *skb, struct device *dev);
-static void arcnetA_rx(struct device *dev,u_char *buf,
+static int arcnet_send_packet_bad(struct sk_buff *skb,struct net_device *dev);
+static int arcnetA_send_packet(struct sk_buff *skb, struct net_device *dev);
+static void arcnetA_rx(struct net_device *dev,u_char *buf,
 	int length,u_char saddr, u_char daddr);
-static struct net_device_stats *arcnet_get_stats(struct device *dev);
+static struct net_device_stats *arcnet_get_stats(struct net_device *dev);
 static unsigned short arcnetA_type_trans(struct sk_buff *skb,
-					 struct device *dev);
+					 struct net_device *dev);
 
 
 #ifdef CONFIG_ARCNET_ETH
 	/* functions specific to Ethernet-Encap */
-static int arcnetE_init(struct device *dev);
-static int arcnetE_open_close(struct device *dev);
-static int arcnetE_send_packet(struct sk_buff *skb, struct device *dev);
-static void arcnetE_rx(struct device *dev,u_char *arcsoft,
+static int arcnetE_init(struct net_device *dev);
+static int arcnetE_open_close(struct net_device *dev);
+static int arcnetE_send_packet(struct sk_buff *skb, struct net_device *dev);
+static void arcnetE_rx(struct net_device *dev,u_char *arcsoft,
 	int length,u_char saddr, u_char daddr);
 #endif
 
 
 #ifdef CONFIG_ARCNET_1051
 	/* functions specific to RFC1051 */
-static int arcnetS_init(struct device *dev);
-static int arcnetS_open_close(struct device *dev);
-static int arcnetS_send_packet(struct sk_buff *skb, struct device *dev);
-static void arcnetS_rx(struct device *dev,u_char *buf,
+static int arcnetS_init(struct net_device *dev);
+static int arcnetS_open_close(struct net_device *dev);
+static int arcnetS_send_packet(struct sk_buff *skb, struct net_device *dev);
+static void arcnetS_rx(struct net_device *dev,u_char *buf,
 	int length,u_char saddr, u_char daddr);
-static int arcnetS_header(struct sk_buff *skb,struct device *dev,
+static int arcnetS_header(struct sk_buff *skb,struct net_device *dev,
 		unsigned short type,void *daddr,void *saddr,unsigned len);
 static int arcnetS_rebuild_header(struct sk_buff *skb);
-static unsigned short arcnetS_type_trans(struct sk_buff *skb,struct device *dev);
+static unsigned short arcnetS_type_trans(struct sk_buff *skb,struct net_device *dev);
 #endif
 
 
@@ -330,7 +330,7 @@
 /* Dump the contents of an sk_buff
  */
 #if ARCNET_DEBUG_MAX & D_SKB
-void arcnet_dump_skb(struct device *dev,struct sk_buff *skb,char *desc)
+void arcnet_dump_skb(struct net_device *dev,struct sk_buff *skb,char *desc)
 {
 	int i;
 	long flags;
@@ -353,7 +353,7 @@
 /* Dump the contents of an ARCnet buffer
  */
 #if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX)
-void arcnet_dump_packet(struct device *dev,u_char *buffer,int ext,char *desc)
+void arcnet_dump_packet(struct net_device *dev,u_char *buffer,int ext,char *desc)
 {
 	int i;
 	long flags;
@@ -373,7 +373,7 @@
 #endif
 
 
-/* Setup a struct device for ARCnet.  This should really be in net_init.c
+/* Setup a struct net_device for ARCnet.  This should really be in net_init.c
  * but since there are three different ARCnet devices ANYWAY... <gargle>
  *
  * Actually, the whole idea of having all this kernel-dependent stuff (ie.
@@ -382,7 +382,7 @@
  * Intelligent defaults?!  Nah.
  */
 
-void arcnet_setup(struct device *dev)
+void arcnet_setup(struct net_device *dev)
 {
 	dev_init_buffers(dev);
 
@@ -421,7 +421,7 @@
  * there is non-reboot way to recover if something goes wrong.
  */
 static int
-arcnet_open(struct device *dev)
+arcnet_open(struct net_device *dev)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
 
@@ -453,10 +453,10 @@
 
 #ifdef CONFIG_ARCNET_ETH
   /* Initialize the ethernet-encap protocol driver */
-  lp->edev=(struct device *)kmalloc(sizeof(struct device),GFP_KERNEL);
+  lp->edev=(struct net_device *)kmalloc(sizeof(struct net_device),GFP_KERNEL);
   if (lp->edev == NULL)
     return -ENOMEM;
-  memcpy(lp->edev,dev,sizeof(struct device));
+  memcpy(lp->edev,dev,sizeof(struct net_device));
   lp->edev->type=ARPHRD_ETHER;
   lp->edev->name=(char *)kmalloc(10,GFP_KERNEL);
   if (lp->edev->name == NULL) {
@@ -471,7 +471,7 @@
 
 #ifdef CONFIG_ARCNET_1051
   /* Initialize the RFC1051-encap protocol driver */
-  lp->sdev=(struct device *)kmalloc(sizeof(struct device)+10,GFP_KERNEL);
+  lp->sdev=(struct net_device *)kmalloc(sizeof(struct net_device)+10,GFP_KERNEL);
   if(lp->sdev = NULL)
   {
   	if(lp->edev)
@@ -479,7 +479,7 @@
   	lp->edev=NULL;
   	return -ENOMEM;
   }
-  memcpy(lp->sdev,dev,sizeof(struct device));
+  memcpy(lp->sdev,dev,sizeof(struct net_device));
   lp->sdev->name=(char *)(lp+1);
   sprintf(lp->sdev->name,"%ss",dev->name);
   lp->sdev->init=arcnetS_init;
@@ -513,7 +513,7 @@
 /* The inverse routine to arcnet_open - shuts down the card.
  */
 static int
-arcnet_close(struct device *dev)
+arcnet_close(struct net_device *dev)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
 
@@ -591,7 +591,7 @@
 /* Generic error checking routine for arcnet??_send_packet
  */
 static int
-arcnet_send_packet_bad(struct sk_buff *skb, struct device *dev)
+arcnet_send_packet_bad(struct sk_buff *skb, struct net_device *dev)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
 
@@ -709,7 +709,7 @@
 /* Called by the kernel in order to transmit a packet.
  */
 static int
-arcnetA_send_packet(struct sk_buff *skb, struct device *dev)
+arcnetA_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
   int bad,oldmask=0;
@@ -832,7 +832,7 @@
  * arcnetAS_prepare_tx to load the next segment into the card.  This function
  * does NOT automatically call arcnet_go_tx.
  */
-void arcnetA_continue_tx(struct device *dev)
+void arcnetA_continue_tx(struct net_device *dev)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
   int maxsegsize=XMTU-4;
@@ -885,7 +885,7 @@
  * to the card; TXFREEflag is always OR'ed into the memory variable either
  * way.
  */
-int arcnet_go_tx(struct device *dev,int enable_irq)
+int arcnet_go_tx(struct net_device *dev,int enable_irq)
 {
 	struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
 
@@ -934,7 +934,7 @@
 void
 arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs)
 {
-	struct device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	struct arcnet_local *lp;
 
 	if (dev==NULL)
@@ -994,7 +994,7 @@
 
 }
 
-void arcnet_tx_done(struct device *dev, struct arcnet_local *lp)
+void arcnet_tx_done(struct net_device *dev, struct arcnet_local *lp)
 {
   if (dev->tbusy)
     {
@@ -1026,7 +1026,7 @@
 
 void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr)
 {
-  struct device *dev=lp->adev;
+  struct net_device *dev=lp->adev;
 
   BUGMSG(D_DURING,"received packet from %02Xh to %02Xh (%d bytes)\n",
 	 saddr,daddr,length);
@@ -1080,7 +1080,7 @@
 /* Packet receiver for "standard" RFC1201-style packets
  */
 static void
-arcnetA_rx(struct device *dev,u_char *buf,
+arcnetA_rx(struct net_device *dev,u_char *buf,
 	   int length, u_char saddr, u_char daddr)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
@@ -1361,7 +1361,7 @@
  * closed.
  */
 
-static struct net_device_stats *arcnet_get_stats(struct device *dev)
+static struct net_device_stats *arcnet_get_stats(struct net_device *dev)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
 
@@ -1374,7 +1374,7 @@
  * saddr=NULL	means use device source address (always will anyway)
  * daddr=NULL	means leave destination address (eg unresolved arp)
  */
-static int arcnetA_header(struct sk_buff *skb,struct device *dev,
+static int arcnetA_header(struct sk_buff *skb,struct net_device *dev,
 			  unsigned short type,void *daddr,void *saddr,unsigned len)
 {
   struct ClientData *head = (struct ClientData *)
@@ -1450,7 +1450,7 @@
 static int arcnetA_rebuild_header(struct sk_buff *skb)
 {
   struct ClientData *head = (struct ClientData *)skb->data;
-  struct device *dev=skb->dev;
+  struct net_device *dev=skb->dev;
   struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
 #ifdef CONFIG_INET
   int status;
@@ -1493,7 +1493,7 @@
  *
  * With ARCnet we have to convert everything to Ethernet-style stuff.
  */
-static unsigned short arcnetA_type_trans(struct sk_buff *skb,struct device *dev)
+static unsigned short arcnetA_type_trans(struct sk_buff *skb,struct net_device *dev)
 {
   struct ClientData *head;
   struct arcnet_local *lp=(struct arcnet_local *) (dev->priv);
@@ -1541,7 +1541,7 @@
 
 /* Initialize the arc0e device.
  */
-static int arcnetE_init(struct device *dev)
+static int arcnetE_init(struct net_device *dev)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
 
@@ -1560,7 +1560,7 @@
 /* Bring up/down the arc0e device - we don't actually have to do anything,
  * since our parent arc0 handles the card I/O itself.
  */
-static int arcnetE_open_close(struct device *dev)
+static int arcnetE_open_close(struct net_device *dev)
 {
   return 0;
 }
@@ -1569,7 +1569,7 @@
 /* Called by the kernel in order to transmit an ethernet-type packet.
  */
 static int
-arcnetE_send_packet(struct sk_buff *skb, struct device *dev)
+arcnetE_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
   int bad,oldmask=0;
@@ -1655,7 +1655,7 @@
 /* Packet receiver for ethernet-encap packets.
  */
 static void
-arcnetE_rx(struct device *dev,u_char *arcsoft,
+arcnetE_rx(struct net_device *dev,u_char *arcsoft,
 	int length,u_char saddr, u_char daddr)
 {
 	struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
@@ -1695,7 +1695,7 @@
 
 /* Initialize the arc0s device.
  */
-static int arcnetS_init(struct device *dev)
+static int arcnetS_init(struct net_device *dev)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
 
@@ -1719,7 +1719,7 @@
 /* Bring up/down the arc0s device - we don't actually have to do anything,
  * since our parent arc0 handles the card I/O itself.
  */
-static int arcnetS_open_close(struct device *dev)
+static int arcnetS_open_close(struct net_device *dev)
 {
   return 0;
 }
@@ -1728,7 +1728,7 @@
 /* Called by the kernel in order to transmit an RFC1051-type packet.
  */
 static int
-arcnetS_send_packet(struct sk_buff *skb, struct device *dev)
+arcnetS_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
   int bad,length;
@@ -1791,7 +1791,7 @@
 /* Packet receiver for RFC1051 packets;
  */
 static void
-arcnetS_rx(struct device *dev,u_char *buf,
+arcnetS_rx(struct net_device *dev,u_char *buf,
 	   int length,u_char saddr, u_char daddr)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
@@ -1837,7 +1837,7 @@
  * saddr=NULL	means use device source address (always will anyway)
  * daddr=NULL	means leave destination address (eg unresolved arp)
  */
-static int arcnetS_header(struct sk_buff *skb,struct device *dev,
+static int arcnetS_header(struct sk_buff *skb,struct net_device *dev,
 			  unsigned short type,void *daddr,void *saddr,unsigned len)
 {
   struct S_ClientData *head = (struct S_ClientData *)
@@ -1895,7 +1895,7 @@
  */
 static int arcnetS_rebuild_header(struct sk_buff *skb)
 {
-  struct device *dev=skb->dev;
+  struct net_device *dev=skb->dev;
   struct S_ClientData *head = (struct S_ClientData *)skb->data;
   struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
 
@@ -1929,7 +1929,7 @@
  *
  * With ARCnet we have to convert everything to Ethernet-style stuff.
  */
-unsigned short arcnetS_type_trans(struct sk_buff *skb,struct device *dev)
+unsigned short arcnetS_type_trans(struct sk_buff *skb,struct net_device *dev)
 {
   struct S_ClientData *head;
   struct arcnet_local *lp=(struct arcnet_local *) (dev->priv);
@@ -1993,7 +1993,7 @@
 {
 }
 
-struct device arcnet_devs[MAX_ARCNET_DEVS];
+struct net_device arcnet_devs[MAX_ARCNET_DEVS];
 int arcnet_num_devs=0;
 char arcnet_dev_names[MAX_ARCNET_DEVS][10];
 
@@ -2079,7 +2079,7 @@
 
 void arcnet_makename(char *device)
 {
-  struct device *dev;
+  struct net_device *dev;
   int arcnum;
 
   arcnum = 0;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/ariadne.c linux/drivers/net/ariadne.c
--- v2.3.13/linux/drivers/net/ariadne.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/ariadne.c	Wed Aug 18 11:36:41 1999
@@ -123,15 +123,15 @@
 };
 
 
-static int ariadne_open(struct device *dev);
-static void ariadne_init_ring(struct device *dev);
-static int ariadne_start_xmit(struct sk_buff *skb, struct device *dev);
-static int ariadne_rx(struct device *dev);
+static int ariadne_open(struct net_device *dev);
+static void ariadne_init_ring(struct net_device *dev);
+static int ariadne_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int ariadne_rx(struct net_device *dev);
 static void ariadne_interrupt(int irq, void *data, struct pt_regs *fp);
-static int ariadne_close(struct device *dev);
-static struct net_device_stats *ariadne_get_stats(struct device *dev);
+static int ariadne_close(struct net_device *dev);
+static struct net_device_stats *ariadne_get_stats(struct net_device *dev);
 #ifdef HAVE_MULTICAST
-static void set_multicast_list(struct device *dev);
+static void set_multicast_list(struct net_device *dev);
 #endif
 
 
@@ -146,7 +146,7 @@
 }
 
 
-int __init ariadne_probe(struct device *dev)
+int __init ariadne_probe(struct net_device *dev)
 {
     unsigned int key;
     const struct ConfigDev *cd;
@@ -193,7 +193,7 @@
 }
 
 
-static int ariadne_open(struct device *dev)
+static int ariadne_open(struct net_device *dev)
 {
     struct ariadne_private *priv = (struct ariadne_private *)dev->priv;
     struct AriadneBoard *board = priv->board;
@@ -293,7 +293,7 @@
     dev->interrupt = 0;
     dev->start = 1;
 
-    if (request_irq(IRQ_AMIGA_PORTS, ariadne_interrupt, 0,
+    if (request_irq(IRQ_AMIGA_PORTS, ariadne_interrupt, SA_SHIRQ,
                     "Ariadne Ethernet", dev))
 	return(-EAGAIN);
 
@@ -306,7 +306,7 @@
 }
 
 
-static void ariadne_init_ring(struct device *dev)
+static void ariadne_init_ring(struct net_device *dev)
 {
     struct ariadne_private *priv = (struct ariadne_private *)dev->priv;
     struct AriadneBoard *board = priv->board;
@@ -353,7 +353,7 @@
 }
 
 
-static int ariadne_close(struct device *dev)
+static int ariadne_close(struct net_device *dev)
 {
     struct ariadne_private *priv = (struct ariadne_private *)dev->priv;
     struct AriadneBoard *board = priv->board;
@@ -385,7 +385,7 @@
 
 static void ariadne_interrupt(int irq, void *data, struct pt_regs *fp)
 {
-    struct device *dev = (struct device *)data;
+    struct net_device *dev = (struct net_device *)data;
     struct ariadne_private *priv;
     struct AriadneBoard *board;
     int csr0, boguscnt = 10;
@@ -542,7 +542,7 @@
 }
 
 
-static int ariadne_start_xmit(struct sk_buff *skb, struct device *dev)
+static int ariadne_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
     struct ariadne_private *priv = (struct ariadne_private *)dev->priv;
     struct AriadneBoard *board = priv->board;
@@ -692,7 +692,7 @@
 }
 
 
-static int ariadne_rx(struct device *dev)
+static int ariadne_rx(struct net_device *dev)
 {
     struct ariadne_private *priv = (struct ariadne_private *)dev->priv;
     int entry = priv->cur_rx % RX_RING_SIZE;
@@ -780,7 +780,7 @@
 }
 
 
-static struct net_device_stats *ariadne_get_stats(struct device *dev)
+static struct net_device_stats *ariadne_get_stats(struct net_device *dev)
 {
     struct ariadne_private *priv = (struct ariadne_private *)dev->priv;
     struct AriadneBoard *board = priv->board;
@@ -805,7 +805,7 @@
     num_addrs > 0	Multicast mode, receive normal and MC packets, and do
 			best-effort filtering.
  */
-static void set_multicast_list(struct device *dev)
+static void set_multicast_list(struct net_device *dev)
 {
     struct ariadne_private *priv = (struct ariadne_private *)dev->priv;
     struct AriadneBoard *board = priv->board;
@@ -842,7 +842,7 @@
 #ifdef MODULE
 static char devicename[9] = { 0, };
 
-static struct device ariadne_dev =
+static struct net_device ariadne_dev =
 {
     devicename,				/* filled in by register_netdev() */
     0, 0, 0, 0,				/* memory */
diff -u --recursive --new-file v2.3.13/linux/drivers/net/ariadne2.c linux/drivers/net/ariadne2.c
--- v2.3.13/linux/drivers/net/ariadne2.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/ariadne2.c	Wed Aug 18 11:36:41 1999
@@ -65,23 +65,23 @@
 
 #define WORDSWAP(a)	((((a)>>8)&0xff) | ((a)<<8))
 
-int ariadne2_probe(struct device *dev);
-static int ariadne2_init(struct device *dev, unsigned int key,
+int ariadne2_probe(struct net_device *dev);
+static int ariadne2_init(struct net_device *dev, unsigned int key,
 			 unsigned long board);
 
-static int ariadne2_open(struct device *dev);
-static int ariadne2_close(struct device *dev);
+static int ariadne2_open(struct net_device *dev);
+static int ariadne2_close(struct net_device *dev);
 
-static void ariadne2_reset_8390(struct device *dev);
-static void ariadne2_get_8390_hdr(struct device *dev,
+static void ariadne2_reset_8390(struct net_device *dev);
+static void ariadne2_get_8390_hdr(struct net_device *dev,
 				  struct e8390_pkt_hdr *hdr, int ring_page);
-static void ariadne2_block_input(struct device *dev, int count,
+static void ariadne2_block_input(struct net_device *dev, int count,
 				 struct sk_buff *skb, int ring_offset);
-static void ariadne2_block_output(struct device *dev, const int count,
+static void ariadne2_block_output(struct net_device *dev, const int count,
 				  const unsigned char *buf,
 				  const int start_page);
 
-int __init ariadne2_probe(struct device *dev)
+int __init ariadne2_probe(struct net_device *dev)
 {
     unsigned int key;
     const struct ConfigDev *cd;
@@ -100,7 +100,7 @@
     return -ENODEV;
 }
 
-static int __init ariadne2_init(struct device *dev, unsigned int key,
+static int __init ariadne2_init(struct net_device *dev, unsigned int key,
 				    unsigned long board)
 {
     int i;
@@ -180,8 +180,8 @@
     dev->irq = IRQ_AMIGA_PORTS;
 
     /* Install the Interrupt handler */
-    if (request_irq(IRQ_AMIGA_PORTS, ei_interrupt, 0, "AriadNE2 Ethernet",
-		    dev))
+    if (request_irq(IRQ_AMIGA_PORTS, ei_interrupt, SA_SHIRQ,
+		    "AriadNE2 Ethernet", dev))
 	return -EAGAIN;
 
     /* Allocate dev->priv and fill in 8390 specific dev fields. */
@@ -221,14 +221,14 @@
     return 0;
 }
 
-static int ariadne2_open(struct device *dev)
+static int ariadne2_open(struct net_device *dev)
 {
     ei_open(dev);
     MOD_INC_USE_COUNT;
     return 0;
 }
 
-static int ariadne2_close(struct device *dev)
+static int ariadne2_close(struct net_device *dev)
 {
     if (ei_debug > 1)
 	printk("%s: Shutting down ethercard.\n", dev->name);
@@ -239,7 +239,7 @@
 
 /* Hard reset the card.  This used to pause for the same period that a
    8390 reset command required, but that shouldn't be necessary. */
-static void ariadne2_reset_8390(struct device *dev)
+static void ariadne2_reset_8390(struct net_device *dev)
 {
     unsigned long reset_start_time = jiffies;
 
@@ -264,7 +264,7 @@
    we don't need to be concerned with ring wrap as the header will be at
    the start of a page, so we optimize accordingly. */
 
-static void ariadne2_get_8390_hdr(struct device *dev,
+static void ariadne2_get_8390_hdr(struct net_device *dev,
 				  struct e8390_pkt_hdr *hdr, int ring_page)
 {
     int nic_base = dev->base_addr;
@@ -304,7 +304,7 @@
    The NEx000 doesn't share the on-board packet memory -- you have to put
    the packet out through the "remote DMA" dataport using writeb. */
 
-static void ariadne2_block_input(struct device *dev, int count,
+static void ariadne2_block_input(struct net_device *dev, int count,
 				 struct sk_buff *skb, int ring_offset)
 {
     int nic_base = dev->base_addr;
@@ -338,7 +338,7 @@
     ei_status.dmaing &= ~0x01;
 }
 
-static void ariadne2_block_output(struct device *dev, int count,
+static void ariadne2_block_output(struct net_device *dev, int count,
 				  const unsigned char *buf,
 				  const int start_page)
 {
@@ -395,7 +395,7 @@
 #ifdef MODULE
 static char devicename[9] = { 0, };
 
-static struct device ariadne2_dev =
+static struct net_device ariadne2_dev =
 {
     devicename,
     0, 0, 0, 0,
diff -u --recursive --new-file v2.3.13/linux/drivers/net/arlan-proc.c linux/drivers/net/arlan-proc.c
--- v2.3.13/linux/drivers/net/arlan-proc.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/arlan-proc.c	Wed Aug 18 11:36:41 1999
@@ -7,10 +7,10 @@
 #include <linux/sysctl.h>
 #include <linux/version.h>
 
-/* void enableReceive(struct device* dev);
+/* void enableReceive(struct net_device* dev);
 */
 
-static  int	arlan_command(struct device * dev, int command);
+static  int	arlan_command(struct net_device * dev, int command);
 
 
 #define ARLAN_STR_SIZE 	0x2ff0
@@ -58,7 +58,7 @@
 }
 
 
-const char *arlan_diagnostic_info_string(struct device *dev)
+const char *arlan_diagnostic_info_string(struct net_device *dev)
 {
 
 	volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
@@ -113,7 +113,7 @@
 	  }
 };
 
-static const char *arlan_hardware_type_string(struct device *dev)
+static const char *arlan_hardware_type_string(struct net_device *dev)
 {
 	u_char hardwareType;
 	volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
@@ -186,7 +186,7 @@
 	}
 }
 
-static void arlan_print_diagnostic_info(struct device *dev)
+static void arlan_print_diagnostic_info(struct net_device *dev)
 {
 	int i;
 	u_char diagnosticInfo;
@@ -251,7 +251,7 @@
 
 /******************************		TEST 	MEMORY	**************/
 
-static int arlan_hw_test_memory(struct device *dev)
+static int arlan_hw_test_memory(struct net_device *dev)
 {
 	u_char *ptr;
 	int i;
@@ -320,7 +320,7 @@
 }
 
 
-static int arlan_setup_card_by_book(struct device *dev)
+static int arlan_setup_card_by_book(struct net_device *dev)
 {
 	u_char irqLevel, configuredStatusFlag;
 	volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
@@ -408,7 +408,7 @@
 	int i;
 	int retv, pos, devnum;
 	struct arlan_private *priva = NULL;
-	struct device *dev;
+	struct net_device *dev;
 	pos = 0;
 	if (write)
 	{
diff -u --recursive --new-file v2.3.13/linux/drivers/net/arlan.c linux/drivers/net/arlan.c
--- v2.3.13/linux/drivers/net/arlan.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/arlan.c	Wed Aug 18 11:36:41 1999
@@ -10,7 +10,7 @@
 
 static const char *arlan_version = "C.Jennigs 97 & Elmer.Joandi@ut.ee  Oct'98, http://www.ylenurme.ee/~elmer/655/";
 
-struct device *arlan_device[MAX_ARLANS];
+struct net_device *arlan_device[MAX_ARLANS];
 int last_arlan = 0;
 
 static int SID = SIDUNKNOWN;
@@ -87,20 +87,20 @@
 struct arlan_conf_stru arlan_conf[MAX_ARLANS];
 int arlans_found = 0;
 
-static  int 	arlan_probe_here(struct device *dev, int ioaddr);
-static  int 	arlan_open(struct device *dev);
-static  int 	arlan_tx(struct sk_buff *skb, struct device *dev);
+static  int 	arlan_probe_here(struct net_device *dev, int ioaddr);
+static  int 	arlan_open(struct net_device *dev);
+static  int 	arlan_tx(struct sk_buff *skb, struct net_device *dev);
 static  void 	arlan_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static  int 	arlan_close(struct device *dev);
+static  int 	arlan_close(struct net_device *dev);
 static  struct enet_statistics *
-		arlan_statistics		(struct device *dev);
-static  void 	arlan_set_multicast		(struct device *dev);
-static  int 	arlan_hw_tx			(struct device* dev, char *buf, int length );
-static  int	arlan_hw_config			(struct device * dev);
-static  void 	arlan_tx_done_interrupt		(struct device * dev, int status);
-static  void	arlan_rx_interrupt		(struct device * dev, u_char rxStatus, u_short, u_short);
-static  void	arlan_process_interrupt		(struct device * dev);
-static  int	arlan_command(struct device * dev, int command);
+		arlan_statistics		(struct net_device *dev);
+static  void 	arlan_set_multicast		(struct net_device *dev);
+static  int 	arlan_hw_tx			(struct net_device* dev, char *buf, int length );
+static  int	arlan_hw_config			(struct net_device * dev);
+static  void 	arlan_tx_done_interrupt		(struct net_device * dev, int status);
+static  void	arlan_rx_interrupt		(struct net_device * dev, u_char rxStatus, u_short, u_short);
+static  void	arlan_process_interrupt		(struct net_device * dev);
+static  int	arlan_command(struct net_device * dev, int command);
 
 EXPORT_SYMBOL(arlan_command);
 
@@ -162,7 +162,7 @@
 
 
 
-extern inline int arlan_drop_tx(struct device *dev)
+extern inline int arlan_drop_tx(struct net_device *dev)
 {
 	struct arlan_private *priv = ((struct arlan_private *) dev->priv);
 
@@ -189,7 +189,7 @@
 };
 
 
-static int arlan_command(struct device *dev, int command_p)
+static int arlan_command(struct net_device *dev, int command_p)
 {
 
 	volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
@@ -532,7 +532,7 @@
 
 };
 
-extern inline void arlan_command_process(struct device *dev)
+extern inline void arlan_command_process(struct net_device *dev)
 {
 	struct arlan_private *priv = ((struct arlan_private *) dev->priv);
 
@@ -553,7 +553,7 @@
 }
 
 
-extern inline void arlan_retransmit_now(struct device *dev)
+extern inline void arlan_retransmit_now(struct net_device *dev)
 {
 	struct arlan_private *priv = ((struct arlan_private *) dev->priv);
 
@@ -596,7 +596,7 @@
 
 static void arlan_registration_timer(unsigned long data)
 {
-	struct device *dev = (struct device *) data;
+	struct net_device *dev = (struct net_device *) data;
 	struct arlan_private *priv = (struct arlan_private *) dev->priv;
 
 	int lostTime = ((int) (jiffies - priv->registrationLastSeen)) * 1000 / HZ;
@@ -696,7 +696,7 @@
 
 
 
-static void arlan_print_registers(struct device *dev, int line)
+static void arlan_print_registers(struct net_device *dev, int line)
 {
 	volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
 
@@ -722,7 +722,7 @@
 }
 
 
-static int arlan_hw_tx(struct device *dev, char *buf, int length)
+static int arlan_hw_tx(struct net_device *dev, char *buf, int length)
 {
 	int i;
 
@@ -827,7 +827,7 @@
 }
 
 
-static int arlan_hw_config(struct device *dev)
+static int arlan_hw_config(struct net_device *dev)
 {
 	volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
 	struct arlan_conf_stru *conf = ((struct arlan_private *) dev->priv)->Conf;
@@ -909,7 +909,7 @@
 }
 
 
-static int arlan_read_card_configuration(struct device *dev)
+static int arlan_read_card_configuration(struct net_device *dev)
 {
 	u_char tlx415;
 	volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
@@ -1056,7 +1056,7 @@
 
 }
 
-__initfunctio(int arlan_probe_everywhere(struct device *dev))
+__initfunctio(int arlan_probe_everywhere(struct net_device *dev))
 {
 	int m;
 	int probed = 0;
@@ -1113,7 +1113,7 @@
 }
 
 
-static int arlan_change_mtu(struct device *dev, int new_mtu)
+static int arlan_change_mtu(struct net_device *dev, int new_mtu)
 {
 	struct arlan_conf_stru *conf = ((struct arlan_private *) dev->priv)->Conf;
 
@@ -1134,7 +1134,7 @@
 	return 0;
 }
 
-static int arlan_mac_addr(struct device *dev, void *p)
+static int arlan_mac_addr(struct net_device *dev, void *p)
 {
 	struct sockaddr *addr = p;
 
@@ -1154,10 +1154,10 @@
 
 
 __initfunctio(static int
-	      arlan_allocate_device(int num, struct device *devs))
+	      arlan_allocate_device(int num, struct net_device *devs))
 {
 
-	struct device *dev;
+	struct net_device *dev;
 
 	ARLAN_DEBUG_ENTRY("arlan_allocate_device");
 
@@ -1214,7 +1214,7 @@
 }
 
 
-__initfunctio(int arlan_probe_here(struct device *dev, int memaddr))
+__initfunctio(int arlan_probe_here(struct net_device *dev, int memaddr))
 {
 	volatile struct arlan_shmem *arlan;
 
@@ -1249,7 +1249,7 @@
 
 
 
-static int arlan_open(struct device *dev)
+static int arlan_open(struct net_device *dev)
 {
 	struct arlan_private *priv = (struct arlan_private *) dev->priv;
 	volatile struct arlan_shmem *arlan = priv->card;
@@ -1323,7 +1323,7 @@
 
 
 
-static int arlan_tx(struct sk_buff *skb, struct device *dev)
+static int arlan_tx(struct sk_buff *skb, struct net_device *dev)
 {
 	struct arlan_private *priv = ((struct arlan_private *) dev->priv);
 	struct arlan_conf_stru *conf = ((struct arlan_private *) dev->priv)->Conf;
@@ -1399,7 +1399,7 @@
 }
 
 
-extern inline int DoNotReTransmitCrap(struct device *dev)
+extern inline int DoNotReTransmitCrap(struct net_device *dev)
 {
 	struct arlan_private *priv = ((struct arlan_private *) dev->priv);
 
@@ -1409,7 +1409,7 @@
 
 }
 
-extern inline int DoNotWaitReTransmitCrap(struct device *dev)
+extern inline int DoNotWaitReTransmitCrap(struct net_device *dev)
 {
 	struct arlan_private *priv = ((struct arlan_private *) dev->priv);
 
@@ -1418,7 +1418,7 @@
 	return 0;
 }
 
-extern inline void arlan_queue_retransmit(struct device *dev)
+extern inline void arlan_queue_retransmit(struct net_device *dev)
 {
 	struct arlan_private *priv = ((struct arlan_private *) dev->priv);
 
@@ -1433,7 +1433,7 @@
 	ARLAN_DEBUG_EXIT("arlan_queue_retransmit");
 };
 
-extern inline void RetryOrFail(struct device *dev)
+extern inline void RetryOrFail(struct net_device *dev)
 {
 	struct arlan_private *priv = ((struct arlan_private *) dev->priv);
 
@@ -1454,7 +1454,7 @@
 }
 
 
-static void arlan_tx_done_interrupt(struct device *dev, int status)
+static void arlan_tx_done_interrupt(struct net_device *dev, int status)
 {
 	struct arlan_private *priv = ((struct arlan_private *) dev->priv);
 
@@ -1596,7 +1596,7 @@
 }
 
 
-static void arlan_rx_interrupt(struct device *dev, u_char rxStatus, u_short rxOffset, u_short pkt_len)
+static void arlan_rx_interrupt(struct net_device *dev, u_char rxStatus, u_short rxOffset, u_short pkt_len)
 {
 	char *skbtmp;
 	int i = 0;
@@ -1749,7 +1749,7 @@
 	ARLAN_DEBUG_EXIT("arlan_rx_interrupt");
 }
 
-static void arlan_process_interrupt(struct device *dev)
+static void arlan_process_interrupt(struct net_device *dev)
 {
 	struct arlan_private *priv = (struct arlan_private *) dev->priv;
 	volatile struct arlan_shmem *arlan = priv->card;
@@ -1859,7 +1859,7 @@
 
 static void arlan_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	struct arlan_private *priv = (struct arlan_private *) dev->priv;
 	volatile struct arlan_shmem *arlan = priv->card;
 	u_char rxStatus = READSHMB(arlan->rxStatus);
@@ -1883,7 +1883,7 @@
 }
 
 
-static int arlan_close(struct device *dev)
+static int arlan_close(struct net_device *dev)
 {
 	struct arlan_private *priv = (struct arlan_private *) dev->priv;
 
@@ -1929,7 +1929,7 @@
  * This may be called with the card open or closed.
  */
 
-static struct enet_statistics *arlan_statistics(struct device *dev)
+static struct enet_statistics *arlan_statistics(struct net_device *dev)
 {
 	struct arlan_private *priv = (struct arlan_private *) dev->priv;
 	volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
@@ -1959,7 +1959,7 @@
 }
 
 
-static void arlan_set_multicast(struct device *dev)
+static void arlan_set_multicast(struct net_device *dev)
 {
 	volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
 	struct arlan_conf_stru *conf = ((struct arlan_private *) dev->priv)->Conf;
@@ -1992,7 +1992,7 @@
 }
 
 
-__initfunctio(int arlan_probe(struct device *dev))
+__initfunctio(int arlan_probe(struct net_device *dev))
 {
 	printk("Arlan driver %s\n", arlan_version);
 
diff -u --recursive --new-file v2.3.13/linux/drivers/net/arlan.h linux/drivers/net/arlan.h
--- v2.3.13/linux/drivers/net/arlan.h	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/arlan.h	Wed Aug 18 11:36:45 1999
@@ -45,7 +45,7 @@
 extern int 	init_arlan_proc(void);
 #endif
 
-extern struct device *arlan_device[MAX_ARLANS];
+extern struct net_device *arlan_device[MAX_ARLANS];
 static int	arlan_debug;
 static char *	siteName;
 static int	arlan_entry_debug;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/at1700.c linux/drivers/net/at1700.c
--- v2.3.13/linux/drivers/net/at1700.c	Tue Jan 19 10:51:24 1999
+++ linux/drivers/net/at1700.c	Wed Aug 18 11:36:41 1999
@@ -150,17 +150,17 @@
 #define AT1700_IO_EXTENT	32
 /* Index to functions, as function prototypes. */
 
-extern int at1700_probe(struct device *dev);
+extern int at1700_probe(struct net_device *dev);
 
-static int at1700_probe1(struct device *dev, int ioaddr);
+static int at1700_probe1(struct net_device *dev, int ioaddr);
 static int read_eeprom(int ioaddr, int location);
-static int net_open(struct device *dev);
-static int	net_send_packet(struct sk_buff *skb, struct device *dev);
+static int net_open(struct net_device *dev);
+static int	net_send_packet(struct sk_buff *skb, struct net_device *dev);
 static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void net_rx(struct device *dev);
-static int net_close(struct device *dev);
-static struct enet_statistics *net_get_stats(struct device *dev);
-static void set_rx_mode(struct device *dev);
+static void net_rx(struct net_device *dev);
+static int net_close(struct net_device *dev);
+static struct enet_statistics *net_get_stats(struct net_device *dev);
+static void set_rx_mode(struct net_device *dev);
 
 
 #ifdef CONFIG_MCA
@@ -192,7 +192,7 @@
 {"at1700", at1700_probe1, AT1700_IO_EXTENT, at1700_probe_list};
 #else
 
-int at1700_probe(struct device *dev)
+int at1700_probe(struct net_device *dev)
 {
 	int i;
 	int base_addr = dev ? dev->base_addr : 0;
@@ -221,7 +221,7 @@
    that can be done is checking a few bits and then diving right into an
    EEPROM read. */
 
-int at1700_probe1(struct device *dev, int ioaddr)
+int at1700_probe1(struct net_device *dev, int ioaddr)
 {
 	char fmv_irqmap[4] = {3, 7, 10, 15};
 	char fmv_irqmap_pnp[8] = {3, 4, 5, 7, 9, 10, 11, 15};
@@ -498,7 +498,7 @@
 
 
 
-static int net_open(struct device *dev)
+static int net_open(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -535,7 +535,7 @@
 }
 
 static int
-net_send_packet(struct sk_buff *skb, struct device *dev)
+net_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -615,7 +615,7 @@
 static void
 net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	struct net_local *lp;
 	int ioaddr, status;
 
@@ -681,7 +681,7 @@
 
 /* We have a good packet(s), get it/them out of the buffers. */
 static void
-net_rx(struct device *dev)
+net_rx(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -762,7 +762,7 @@
 }
 
 /* The inverse routine to net_open(). */
-static int net_close(struct device *dev)
+static int net_close(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -794,7 +794,7 @@
    There are no on-chip counters, so this function is trivial.
 */
 static struct enet_statistics *
-net_get_stats(struct device *dev)
+net_get_stats(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	return &lp->stats;
@@ -826,7 +826,7 @@
 }
 
 static void
-set_rx_mode(struct device *dev)
+set_rx_mode(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr;
 	struct net_local *lp = (struct net_local *)dev->priv;
@@ -875,7 +875,7 @@
 
 #ifdef MODULE
 static char devicename[9] = { 0, };
-static struct device dev_at1700 = {
+static struct net_device dev_at1700 = {
 	devicename, /* device name is inserted by linux/drivers/net/net_init.c */
 	0, 0, 0, 0,
 	0, 0,
diff -u --recursive --new-file v2.3.13/linux/drivers/net/atari_bionet.c linux/drivers/net/atari_bionet.c
--- v2.3.13/linux/drivers/net/atari_bionet.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/atari_bionet.c	Wed Aug 18 11:36:41 1999
@@ -115,7 +115,7 @@
 #include <asm/atari_stdma.h>
 
 
-extern struct device *init_etherdev(struct device *dev, int sizeof_private);
+extern struct net_device *init_etherdev(struct net_device *dev, int sizeof_private);
 
 /* use 0 for production, 1 for verification, >2 for debug
  */
@@ -149,13 +149,13 @@
 
 /* Index to functions, as function prototypes.
  */
-extern int bionet_probe(struct device *dev);
+extern int bionet_probe(struct net_device *dev);
 
-static int bionet_open(struct device *dev);
-static int bionet_send_packet(struct sk_buff *skb, struct device *dev);
-static void bionet_poll_rx(struct device *);
-static int bionet_close(struct device *dev);
-static struct net_device_stats *net_get_stats(struct device *dev);
+static int bionet_open(struct net_device *dev);
+static int bionet_send_packet(struct sk_buff *skb, struct net_device *dev);
+static void bionet_poll_rx(struct net_device *);
+static int bionet_close(struct net_device *dev);
+static struct net_device_stats *net_get_stats(struct net_device *dev);
 static void bionet_tick(unsigned long);
 
 static struct timer_list bionet_timer = { NULL, NULL, 0, 0, bionet_tick };
@@ -325,7 +325,7 @@
 /* Check for a network adaptor of this type, and return '0' if one exists.
  */
 int __init 
-bionet_probe(struct device *dev){
+bionet_probe(struct net_device *dev){
 	unsigned char station_addr[6];
 	static unsigned version_printed = 0;
 	static int no_more_found = 0; /* avoid "Probing for..." printed 4 times */
@@ -404,7 +404,7 @@
    there is non-reboot way to recover if something goes wrong.
  */
 static int
-bionet_open(struct device *dev) {
+bionet_open(struct net_device *dev) {
 	struct net_local *lp = (struct net_local *)dev->priv;
 
 	if (bionet_debug > 0)
@@ -430,7 +430,7 @@
 }
 
 static int
-bionet_send_packet(struct sk_buff *skb, struct device *dev) {
+bionet_send_packet(struct sk_buff *skb, struct net_device *dev) {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	unsigned long flags;
 
@@ -497,7 +497,7 @@
 /* We have a good packet(s), get it/them out of the buffers.
  */
 static void
-bionet_poll_rx(struct device *dev) {
+bionet_poll_rx(struct net_device *dev) {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int boguscount = 10;
 	int pkt_len, status;
@@ -599,7 +599,7 @@
  */
 static void
 bionet_tick(unsigned long data) {
-	struct device	 *dev = (struct device *)data;
+	struct net_device	 *dev = (struct net_device *)data;
 	struct net_local *lp = (struct net_local *)dev->priv;
 
 	if( bionet_debug > 0 && (lp->open_time++ & 7) == 8 )
@@ -614,7 +614,7 @@
 /* The inverse routine to bionet_open().
  */
 static int
-bionet_close(struct device *dev) {
+bionet_close(struct net_device *dev) {
 	struct net_local *lp = (struct net_local *)dev->priv;
 
 	if (bionet_debug > 0)
@@ -636,7 +636,7 @@
 /* Get the current statistics.
    This may be called with the card open or closed.
  */
-static struct net_device_stats *net_get_stats(struct device *dev) 
+static struct net_device_stats *net_get_stats(struct net_device *dev) 
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	return &lp->stats;
@@ -646,7 +646,7 @@
 #ifdef MODULE
 
 static char bio_name[16];
-static struct device bio_dev =
+static struct net_device bio_dev =
 	{
 		bio_name,	/* filled in by register_netdev() */
 		0, 0, 0, 0,	/* memory */
diff -u --recursive --new-file v2.3.13/linux/drivers/net/atari_pamsnet.c linux/drivers/net/atari_pamsnet.c
--- v2.3.13/linux/drivers/net/atari_pamsnet.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/atari_pamsnet.c	Wed Aug 18 11:36:41 1999
@@ -111,7 +111,7 @@
 #undef READ
 #undef WRITE
 
-extern struct device *init_etherdev(struct device *dev, int sizeof_private);
+extern struct net_device *init_etherdev(struct net_device *dev, int sizeof_private);
 
 /* use 0 for production, 1 for verification, >2 for debug
  */
@@ -157,13 +157,13 @@
 static int	get_status (void);
 static int	calc_received (void *start_address);
 
-extern int pamsnet_probe(struct device *dev);
+extern int pamsnet_probe(struct net_device *dev);
 
-static int pamsnet_open(struct device *dev);
-static int pamsnet_send_packet(struct sk_buff *skb, struct device *dev);
-static void pamsnet_poll_rx(struct device *);
-static int pamsnet_close(struct device *dev);
-static struct net_device_stats *net_get_stats(struct device *dev);
+static int pamsnet_open(struct net_device *dev);
+static int pamsnet_send_packet(struct sk_buff *skb, struct net_device *dev);
+static void pamsnet_poll_rx(struct net_device *);
+static int pamsnet_close(struct net_device *dev);
+static struct net_device_stats *net_get_stats(struct net_device *dev);
 static void pamsnet_tick(unsigned long);
 
 static void pamsnet_intr(int irq, void *data, struct pt_regs *fp);
@@ -563,7 +563,7 @@
 
 extern int __init 
 pamsnet_probe (dev)
-	struct device *dev;
+	struct net_device *dev;
 {
 	int i;
 	HADDR *hwaddr;
@@ -661,7 +661,7 @@
    there is non-reboot way to recover if something goes wrong.
  */
 static int
-pamsnet_open(struct device *dev) {
+pamsnet_open(struct net_device *dev) {
 	struct net_local *lp = (struct net_local *)dev->priv;
 
 	if (pamsnet_debug > 0)
@@ -691,7 +691,7 @@
 }
 
 static int
-pamsnet_send_packet(struct sk_buff *skb, struct device *dev) {
+pamsnet_send_packet(struct sk_buff *skb, struct net_device *dev) {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	unsigned long flags;
 
@@ -738,7 +738,7 @@
 /* We have a good packet(s), get it/them out of the buffers.
  */
 static void
-pamsnet_poll_rx(struct device *dev) {
+pamsnet_poll_rx(struct net_device *dev) {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int boguscount;
 	int pkt_len;
@@ -813,7 +813,7 @@
  */
 static void
 pamsnet_tick(unsigned long data) {
-	struct device	 *dev = (struct device *)data;
+	struct net_device	 *dev = (struct net_device *)data;
 	struct net_local *lp = (struct net_local *)dev->priv;
 
 	if( pamsnet_debug > 0 && (lp->open_time++ & 7) == 8 )
@@ -828,7 +828,7 @@
 /* The inverse routine to pamsnet_open().
  */
 static int
-pamsnet_close(struct device *dev) {
+pamsnet_close(struct net_device *dev) {
 	struct net_local *lp = (struct net_local *)dev->priv;
 
 	if (pamsnet_debug > 0)
@@ -855,7 +855,7 @@
 /* Get the current statistics.
    This may be called with the card open or closed.
  */
-static struct net_device_stats *net_get_stats(struct device *dev) 
+static struct net_device_stats *net_get_stats(struct net_device *dev) 
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	return &lp->stats;
@@ -865,7 +865,7 @@
 #ifdef MODULE
 
 static char devicename[9] = { 0, };
-static struct device pam_dev =
+static struct net_device pam_dev =
 	{
 		devicename,	/* filled in by register_netdev() */
 		0, 0, 0, 0,	/* memory */
diff -u --recursive --new-file v2.3.13/linux/drivers/net/atarilance.c linux/drivers/net/atarilance.c
--- v2.3.13/linux/drivers/net/atarilance.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/atarilance.c	Wed Aug 18 11:36:41 1999
@@ -339,17 +339,17 @@
 
 static int addr_accessible( volatile void *regp, int wordflag, int
                             writeflag );
-static unsigned long lance_probe1( struct device *dev, struct lance_addr
+static unsigned long lance_probe1( struct net_device *dev, struct lance_addr
                                    *init_rec );
-static int lance_open( struct device *dev );
-static void lance_init_ring( struct device *dev );
-static int lance_start_xmit( struct sk_buff *skb, struct device *dev );
+static int lance_open( struct net_device *dev );
+static void lance_init_ring( struct net_device *dev );
+static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev );
 static void lance_interrupt( int irq, void *dev_id, struct pt_regs *fp );
-static int lance_rx( struct device *dev );
-static int lance_close( struct device *dev );
-static struct net_device_stats *lance_get_stats( struct device *dev );
-static void set_multicast_list( struct device *dev );
-static int lance_set_mac_address( struct device *dev, void *addr );
+static int lance_rx( struct net_device *dev );
+static int lance_close( struct net_device *dev );
+static struct net_device_stats *lance_get_stats( struct net_device *dev );
+static void set_multicast_list( struct net_device *dev );
+static int lance_set_mac_address( struct net_device *dev, void *addr );
 
 /************************* End of Prototypes **************************/
 
@@ -370,7 +370,7 @@
 }
 
 
-int __init atarilance_probe( struct device *dev )
+int __init atarilance_probe( struct net_device *dev )
 {	
     int i;
 	static int found = 0;
@@ -443,7 +443,7 @@
 }
 
 
-static unsigned long __init lance_probe1( struct device *dev,
+static unsigned long __init lance_probe1( struct net_device *dev,
 								   struct lance_addr *init_rec )
 {
 	volatile unsigned short *memaddr =
@@ -623,7 +623,7 @@
 }
 
 
-static int lance_open( struct device *dev )
+static int lance_open( struct net_device *dev )
 
 {	struct lance_private *lp = (struct lance_private *)dev->priv;
 	struct lance_ioreg	 *IO = lp->iobase;
@@ -667,7 +667,7 @@
 
 /* Initialize the LANCE Rx and Tx rings. */
 
-static void lance_init_ring( struct device *dev )
+static void lance_init_ring( struct net_device *dev )
 
 {	struct lance_private *lp = (struct lance_private *)dev->priv;
 	int i;
@@ -713,7 +713,7 @@
 }
 
 
-static int lance_start_xmit( struct sk_buff *skb, struct device *dev )
+static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev )
 
 {	struct lance_private *lp = (struct lance_private *)dev->priv;
 	struct lance_ioreg	 *IO = lp->iobase;
@@ -844,7 +844,7 @@
 
 static void lance_interrupt( int irq, void *dev_id, struct pt_regs *fp)
 {
-	struct device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	struct lance_private *lp;
 	struct lance_ioreg	 *IO;
 	int csr0, boguscnt = 10;
@@ -952,7 +952,7 @@
 }
 
 
-static int lance_rx( struct device *dev )
+static int lance_rx( struct net_device *dev )
 
 {	struct lance_private *lp = (struct lance_private *)dev->priv;
 	int entry = lp->cur_rx & RX_RING_MOD_MASK;
@@ -1045,7 +1045,7 @@
 }
 
 
-static int lance_close( struct device *dev )
+static int lance_close( struct net_device *dev )
 
 {	struct lance_private *lp = (struct lance_private *)dev->priv;
 	struct lance_ioreg	 *IO = lp->iobase;
@@ -1067,7 +1067,7 @@
 }
 
 
-static struct net_device_stats *lance_get_stats( struct device *dev )
+static struct net_device_stats *lance_get_stats( struct net_device *dev )
 
 {	struct lance_private *lp = (struct lance_private *)dev->priv;
 
@@ -1082,7 +1082,7 @@
 						best-effort filtering.
  */
 
-static void set_multicast_list( struct device *dev )
+static void set_multicast_list( struct net_device *dev )
 
 {	struct lance_private *lp = (struct lance_private *)dev->priv;
 	struct lance_ioreg	 *IO = lp->iobase;
@@ -1124,7 +1124,7 @@
 
 /* This is needed for old RieblCards and possible for new RieblCards */
 
-static int lance_set_mac_address( struct device *dev, void *addr )
+static int lance_set_mac_address( struct net_device *dev, void *addr )
 
 {	struct lance_private *lp = (struct lance_private *)dev->priv;
 	struct sockaddr *saddr = addr;
@@ -1154,7 +1154,7 @@
 #ifdef MODULE
 static char devicename[9] = { 0, };
 
-static struct device atarilance_dev =
+static struct net_device atarilance_dev =
 {
 	devicename,	/* filled in by register_netdev() */
 	0, 0, 0, 0,	/* memory */
diff -u --recursive --new-file v2.3.13/linux/drivers/net/atp.c linux/drivers/net/atp.c
--- v2.3.13/linux/drivers/net/atp.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/atp.c	Wed Aug 18 11:36:41 1999
@@ -120,28 +120,28 @@
 #ifdef TIMED_CHECKER
 #include <linux/timer.h>
 static void atp_timed_checker(unsigned long ignored);
-static struct device *atp_timed_dev;
+static struct net_device *atp_timed_dev;
 static struct timer_list atp_timer = {NULL, NULL, 0, 0, atp_timed_checker};
 #endif
 
 /* Index to functions, as function prototypes. */
 
-extern int atp_probe(struct device *dev);
+extern int atp_probe(struct net_device *dev);
 
-static int atp_probe1(struct device *dev, short ioaddr);
-static void get_node_ID(struct device *dev);
+static int atp_probe1(struct net_device *dev, short ioaddr);
+static void get_node_ID(struct net_device *dev);
 static unsigned short eeprom_op(short ioaddr, unsigned int cmd);
-static int net_open(struct device *dev);
-static void hardware_init(struct device *dev);
+static int net_open(struct net_device *dev);
+static void hardware_init(struct net_device *dev);
 static void write_packet(short ioaddr, int length, unsigned char *packet, int mode);
 static void trigger_send(short ioaddr, int length);
-static int	net_send_packet(struct sk_buff *skb, struct device *dev);
+static int	net_send_packet(struct sk_buff *skb, struct net_device *dev);
 static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void net_rx(struct device *dev);
+static void net_rx(struct net_device *dev);
 static void read_block(short ioaddr, int length, unsigned char *buffer, int data_mode);
-static int net_close(struct device *dev);
-static struct net_device_stats *net_get_stats(struct device *dev);
-static void set_multicast_list(struct device *dev);
+static int net_close(struct net_device *dev);
+static struct net_device_stats *net_get_stats(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
 
 
 /* Check for a network adapter of this type, and return '0' iff one exists.
@@ -151,7 +151,7 @@
    (detachable devices only).
    */
 int __init 
-atp_init(struct device *dev)
+atp_init(struct net_device *dev)
 {
 	int *port, ports[] = {0x378, 0x278, 0x3bc, 0};
 	int base_addr = dev->base_addr;
@@ -173,7 +173,7 @@
 	return ENODEV;
 }
 
-static int __init atp_probe1(struct device *dev, short ioaddr)
+static int __init atp_probe1(struct net_device *dev, short ioaddr)
 {
 	int saved_ctrl_reg, status;
 
@@ -259,7 +259,7 @@
 }
 
 /* Read the station address PROM, usually a word-wide EEPROM. */
-static void __init get_node_ID(struct device *dev)
+static void __init get_node_ID(struct net_device *dev)
 {
 	short ioaddr = dev->base_addr;
 	int sa_offset = 0;
@@ -321,7 +321,7 @@
    This is an attachable device: if there is no dev->priv entry then it wasn't
    probed for at boot-time, and we need to probe for it again.
    */
-static int net_open(struct device *dev)
+static int net_open(struct net_device *dev)
 {
 
 	/* The interrupt line is turned off (tri-stated) when the device isn't in
@@ -338,7 +338,7 @@
 
 /* This routine resets the hardware.  We initialize everything, assuming that
    the hardware may have been temporarily detached. */
-static void hardware_init(struct device *dev)
+static void hardware_init(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -412,7 +412,7 @@
 }
 
 static int
-net_send_packet(struct sk_buff *skb, struct device *dev)
+net_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -477,7 +477,7 @@
 static void
 net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
-	struct device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	struct net_local *lp;
 	int ioaddr, status, boguscount = 20;
 	static int num_tx_since_rx = 0;
@@ -634,7 +634,7 @@
 #endif
 
 /* We have a good packet(s), get it/them out of the buffers. */
-static void net_rx(struct device *dev)
+static void net_rx(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -713,7 +713,7 @@
 
 /* The inverse routine to net_open(). */
 static int
-net_close(struct device *dev)
+net_close(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -737,7 +737,7 @@
 
 /* Get the current statistics.	This may be called with the card open or
    closed. */
-static struct net_device_stats *net_get_stats(struct device *dev)
+static struct net_device_stats *net_get_stats(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	return &lp->stats;
@@ -747,7 +747,7 @@
  *	Set or clear the multicast filter for this adapter.
  */
  
-static void set_multicast_list(struct device *dev)
+static void set_multicast_list(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	short ioaddr = dev->base_addr;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/bagetlance.c linux/drivers/net/bagetlance.c
--- v2.3.13/linux/drivers/net/bagetlance.c	Wed Jun 30 13:38:20 1999
+++ linux/drivers/net/bagetlance.c	Wed Aug 18 11:36:41 1999
@@ -329,17 +329,17 @@
 
 static int addr_accessible( volatile void *regp, int wordflag, int
                             writeflag );
-static unsigned long lance_probe1( struct device *dev, struct lance_addr
+static unsigned long lance_probe1( struct net_device *dev, struct lance_addr
                                    *init_rec );
-static int lance_open( struct device *dev );
-static void lance_init_ring( struct device *dev );
-static int lance_start_xmit( struct sk_buff *skb, struct device *dev );
+static int lance_open( struct net_device *dev );
+static void lance_init_ring( struct net_device *dev );
+static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev );
 static void lance_interrupt( int irq, void *dev_id, struct pt_regs *fp );
-static int lance_rx( struct device *dev );
-static int lance_close( struct device *dev );
-static struct net_device_stats *lance_get_stats( struct device *dev );
-static void set_multicast_list( struct device *dev );
-static int lance_set_mac_address( struct device *dev, void *addr );
+static int lance_rx( struct net_device *dev );
+static int lance_close( struct net_device *dev );
+static struct net_device_stats *lance_get_stats( struct net_device *dev );
+static void set_multicast_list( struct net_device *dev );
+static int lance_set_mac_address( struct net_device *dev, void *addr );
 
 /************************* End of Prototypes **************************/
 
@@ -469,7 +469,7 @@
 }
 
 
-__initfunc(int bagetlance_probe( struct device *dev ))
+__initfunc(int bagetlance_probe( struct net_device *dev ))
 
 {	int i;
 	static int found = 0;
@@ -508,7 +508,7 @@
 #define IRQ_TYPE_PRIO SA_INTERRUPT
 #define IRQ_SOURCE_TO_VECTOR(x) (x)
 
-__initfunc(static unsigned long lance_probe1( struct device *dev,
+__initfunc(static unsigned long lance_probe1( struct net_device *dev,
 								   struct lance_addr *init_rec ))
 
 {	volatile unsigned short *memaddr =
@@ -723,7 +723,7 @@
 }
 
 
-static int lance_open( struct device *dev )
+static int lance_open( struct net_device *dev )
 
 {	struct lance_private *lp = (struct lance_private *)dev->priv;
 	struct lance_ioreg	 *IO = lp->iobase;
@@ -767,7 +767,7 @@
 
 /* Initialize the LANCE Rx and Tx rings. */
 
-static void lance_init_ring( struct device *dev )
+static void lance_init_ring( struct net_device *dev )
 
 {	struct lance_private *lp = (struct lance_private *)dev->priv;
 	int i;
@@ -823,7 +823,7 @@
 }
 
 
-static int lance_start_xmit( struct sk_buff *skb, struct device *dev )
+static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev )
 
 {	struct lance_private *lp = (struct lance_private *)dev->priv;
 	struct lance_ioreg	 *IO = lp->iobase;
@@ -962,7 +962,7 @@
 
 static void lance_interrupt( int irq, void *dev_id, struct pt_regs *fp)
 {
-	struct device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	struct lance_private *lp;
 	struct lance_ioreg	 *IO;
 	int csr0, boguscnt = 10;
@@ -1082,7 +1082,7 @@
 }
 
 
-static int lance_rx( struct device *dev )
+static int lance_rx( struct net_device *dev )
 
 {	struct lance_private *lp = (struct lance_private *)dev->priv;
 	int entry = lp->cur_rx & RX_RING_MOD_MASK;
@@ -1205,7 +1205,7 @@
 }
 
 
-static int lance_close( struct device *dev )
+static int lance_close( struct net_device *dev )
 
 {	struct lance_private *lp = (struct lance_private *)dev->priv;
 	struct lance_ioreg	 *IO = lp->iobase;
@@ -1227,7 +1227,7 @@
 }
 
 
-static struct net_device_stats *lance_get_stats( struct device *dev )
+static struct net_device_stats *lance_get_stats( struct net_device *dev )
 
 {	
 	struct lance_private *lp = (struct lance_private *)dev->priv;
@@ -1242,7 +1242,7 @@
 						best-effort filtering.
  */
 
-static void set_multicast_list( struct device *dev )
+static void set_multicast_list( struct net_device *dev )
 
 {	struct lance_private *lp = (struct lance_private *)dev->priv;
 	struct lance_ioreg	 *IO = lp->iobase;
@@ -1284,7 +1284,7 @@
 
 /* This is needed for old RieblCards and possible for new RieblCards */
 
-static int lance_set_mac_address( struct device *dev, void *addr )
+static int lance_set_mac_address( struct net_device *dev, void *addr )
 
 {	struct lance_private *lp = (struct lance_private *)dev->priv;
 	struct sockaddr *saddr = addr;
@@ -1326,7 +1326,7 @@
 #ifdef MODULE
 static char devicename[9] = { 0, };
 
-static struct device bagetlance_dev =
+static struct net_device bagetlance_dev =
 {
 	devicename,	/* filled in by register_netdev() */
 	0, 0, 0, 0,	/* memory */
diff -u --recursive --new-file v2.3.13/linux/drivers/net/bmac.c linux/drivers/net/bmac.c
--- v2.3.13/linux/drivers/net/bmac.c	Wed Dec 30 10:55:07 1998
+++ linux/drivers/net/bmac.c	Wed Aug 18 11:36:41 1999
@@ -114,7 +114,7 @@
 	{"RXCV", RXCV}
 };
 
-struct device *bmac_devs = NULL;
+struct net_device *bmac_devs = NULL;
 static int is_bmac_plus;
 
 #if 0
@@ -135,25 +135,25 @@
 	+ sizeof(struct sk_buff_head))
 
 static unsigned char bitrev(unsigned char b);
-static int bmac_open(struct device *dev);
-static int bmac_close(struct device *dev);
-static int bmac_transmit_packet(struct sk_buff *skb, struct device *dev);
-static struct net_device_stats *bmac_stats(struct device *dev);
-static void bmac_set_multicast(struct device *dev);
-static int bmac_reset_and_enable(struct device *dev, int enable);
-static void bmac_start_chip(struct device *dev);
-static int bmac_init_chip(struct device *dev);
-static void bmac_init_registers(struct device *dev);
-static void bmac_reset_chip(struct device *dev);
-static int bmac_set_address(struct device *dev, void *addr);
+static int bmac_open(struct net_device *dev);
+static int bmac_close(struct net_device *dev);
+static int bmac_transmit_packet(struct sk_buff *skb, struct net_device *dev);
+static struct net_device_stats *bmac_stats(struct net_device *dev);
+static void bmac_set_multicast(struct net_device *dev);
+static int bmac_reset_and_enable(struct net_device *dev, int enable);
+static void bmac_start_chip(struct net_device *dev);
+static int bmac_init_chip(struct net_device *dev);
+static void bmac_init_registers(struct net_device *dev);
+static void bmac_reset_chip(struct net_device *dev);
+static int bmac_set_address(struct net_device *dev, void *addr);
 static void bmac_misc_intr(int irq, void *dev_id, struct pt_regs *regs);
 static void bmac_txdma_intr(int irq, void *dev_id, struct pt_regs *regs);
 static void bmac_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs);
-static void bmac_set_timeout(struct device *dev);
+static void bmac_set_timeout(struct net_device *dev);
 static void bmac_tx_timeout(unsigned long data);
 static int bmac_proc_info ( char *buffer, char **start, off_t offset, int length, int dummy);
-static int bmac_output(struct sk_buff *skb, struct device *dev);
-static void bmac_start(struct device *dev);
+static int bmac_output(struct sk_buff *skb, struct net_device *dev);
+static void bmac_start(struct net_device *dev);
 
 #define	DBDMA_SET(x)	( ((x) | (x) << 16) )
 #define	DBDMA_CLEAR(x)	( (x) << 16)
@@ -214,20 +214,20 @@
 }
 
 static __inline__
-void bmwrite(struct device *dev, unsigned long reg_offset, unsigned data )
+void bmwrite(struct net_device *dev, unsigned long reg_offset, unsigned data )
 {
 	out_le16((void *)dev->base_addr + reg_offset, data);
 }
 
 
 static __inline__
-volatile unsigned short bmread(struct device *dev, unsigned long reg_offset )
+volatile unsigned short bmread(struct net_device *dev, unsigned long reg_offset )
 {
 	return in_le16((void *)dev->base_addr + reg_offset); 
 }
 
 static void
-bmac_reset_chip(struct device *dev)
+bmac_reset_chip(struct net_device *dev)
 {
 	struct bmac_data *bp = (struct bmac_data *) dev->priv;
 	volatile struct dbdma_regs *rd = bp->rx_dma;
@@ -247,7 +247,7 @@
 #define MIFDELAY	udelay(500)
 
 static unsigned int
-bmac_mif_readbits(struct device *dev, int nb)
+bmac_mif_readbits(struct net_device *dev, int nb)
 {
 	unsigned int val = 0;
 
@@ -267,7 +267,7 @@
 }
 
 static void
-bmac_mif_writebits(struct device *dev, unsigned int val, int nb)
+bmac_mif_writebits(struct net_device *dev, unsigned int val, int nb)
 {
 	int b;
 
@@ -281,7 +281,7 @@
 }
 
 static unsigned int
-bmac_mif_read(struct device *dev, unsigned int addr)
+bmac_mif_read(struct net_device *dev, unsigned int addr)
 {
 	unsigned int val;
 
@@ -302,7 +302,7 @@
 }
 
 static void
-bmac_mif_write(struct device *dev, unsigned int addr, unsigned int val)
+bmac_mif_write(struct net_device *dev, unsigned int addr, unsigned int val)
 {
 	bmwrite(dev, MIFCSR, 4);
 	MIFDELAY;
@@ -315,7 +315,7 @@
 }
 
 static void
-bmac_init_registers(struct device *dev)
+bmac_init_registers(struct net_device *dev)
 {
 	struct bmac_data *bp = (struct bmac_data *) dev->priv;
 	volatile unsigned short regValue;
@@ -396,13 +396,13 @@
 
 #if 0
 static void
-bmac_disable_interrupts(struct device *dev)
+bmac_disable_interrupts(struct net_device *dev)
 {
 	bmwrite(dev, INTDISABLE, DisableAll);
 }
 
 static void
-bmac_enable_interrupts(struct device *dev)
+bmac_enable_interrupts(struct net_device *dev)
 {
 	bmwrite(dev, INTDISABLE, EnableNormal);
 }
@@ -410,7 +410,7 @@
 
 
 static void
-bmac_start_chip(struct device *dev)
+bmac_start_chip(struct net_device *dev)
 {
 	struct bmac_data *bp = (struct bmac_data *) dev->priv;
 	volatile struct dbdma_regs *rd = bp->rx_dma;
@@ -429,7 +429,7 @@
 }
 
 static int
-bmac_init_chip(struct device *dev)
+bmac_init_chip(struct net_device *dev)
 {
 	if (is_bmac_plus && bmac_mif_read(dev, 2) == 0x7810) {
 		if (bmac_mif_read(dev, 4) == 0xa1) {
@@ -448,7 +448,7 @@
 	return 1;
 }
 
-static int bmac_set_address(struct device *dev, void *addr)
+static int bmac_set_address(struct net_device *dev, void *addr)
 {
 	unsigned char *p = addr;
 	unsigned short *pWord16;
@@ -472,7 +472,7 @@
 	return 0;
 }
 
-static inline void bmac_set_timeout(struct device *dev)
+static inline void bmac_set_timeout(struct net_device *dev)
 {
 	struct bmac_data *bp = (struct bmac_data *) dev->priv;
 	unsigned long flags;
@@ -580,7 +580,7 @@
 }
 
 
-static int bmac_transmit_packet(struct sk_buff *skb, struct device *dev)
+static int bmac_transmit_packet(struct sk_buff *skb, struct net_device *dev)
 {
 	struct bmac_data *bp = (struct bmac_data *) dev->priv;
 	volatile struct dbdma_regs *td = bp->tx_dma;
@@ -616,7 +616,7 @@
 
 static void bmac_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev = (struct device *) dev_id;
+	struct net_device *dev = (struct net_device *) dev_id;
 	struct bmac_data *bp = (struct bmac_data *) dev->priv;
 	volatile struct dbdma_regs *rd = bp->rx_dma;
 	volatile struct dbdma_cmd *cp;
@@ -684,7 +684,7 @@
 
 static void bmac_txdma_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev = (struct device *) dev_id;
+	struct net_device *dev = (struct net_device *) dev_id;
 	struct bmac_data *bp = (struct bmac_data *) dev->priv;
 	volatile struct dbdma_cmd *cp;
 	int stat;
@@ -730,7 +730,7 @@
 	bmac_start(dev);
 }
 
-static struct net_device_stats *bmac_stats(struct device *dev)
+static struct net_device_stats *bmac_stats(struct net_device *dev)
 {
 	struct bmac_data *p = (struct bmac_data *) dev->priv;
 
@@ -833,7 +833,7 @@
  */
 
 static void
-bmac_rx_off(struct device *dev)
+bmac_rx_off(struct net_device *dev)
 {
 	unsigned short rx_cfg;
 
@@ -846,7 +846,7 @@
 }
 
 unsigned short
-bmac_rx_on(struct device *dev, int hash_enable, int promisc_enable)
+bmac_rx_on(struct net_device *dev, int hash_enable, int promisc_enable)
 {
 	unsigned short rx_cfg;
 
@@ -864,7 +864,7 @@
 }
 
 static void
-bmac_update_hash_table_mask(struct device *dev, struct bmac_data *bp)
+bmac_update_hash_table_mask(struct net_device *dev, struct bmac_data *bp)
 {
 	bmwrite(dev, BHASH3, bp->hash_table_mask[0]); /* bits 15 - 0 */
 	bmwrite(dev, BHASH2, bp->hash_table_mask[1]); /* bits 31 - 16 */
@@ -874,7 +874,7 @@
 
 #if 0
 static void
-bmac_add_multi(struct device *dev,
+bmac_add_multi(struct net_device *dev,
 	       struct bmac_data *bp, unsigned char *addr)
 {
 	/* XXDEBUG(("bmac: enter bmac_add_multi\n")); */
@@ -886,7 +886,7 @@
 }
 
 static void
-bmac_remove_multi(struct device *dev,
+bmac_remove_multi(struct net_device *dev,
 		  struct bmac_data *bp, unsigned char *addr)
 {
 	bmac_removehash(bp, addr);
@@ -902,7 +902,7 @@
     num_addrs > 0	Multicast mode, receive normal and MC packets, and do
 			best-effort filtering.
  */
-static void bmac_set_multicast(struct device *dev)
+static void bmac_set_multicast(struct net_device *dev)
 {
 	struct dev_mc_list *dmi;
 	struct bmac_data *bp = (struct bmac_data *) dev->priv;
@@ -946,7 +946,7 @@
 #define CRC_POLYNOMIAL_BE 0x04c11db7UL  /* Ethernet CRC, big endian */
 #define CRC_POLYNOMIAL_LE 0xedb88320UL  /* Ethernet CRC, little endian */
 
-static void bmac_set_multicast(struct device *dev)
+static void bmac_set_multicast(struct net_device *dev)
 {
 	struct dev_mc_list *dmi = dev->mc_list;
 	char *addrs;
@@ -1014,7 +1014,7 @@
 
 static void bmac_misc_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev = (struct device *) dev_id;
+	struct net_device *dev = (struct net_device *) dev_id;
 	struct bmac_data *bp = (struct bmac_data *)dev->priv;
 	unsigned int status = bmread(dev, STATUS);
 	if (miscintcount++ < 10) {
@@ -1052,7 +1052,7 @@
 #define EnetAddressOffset	20
 
 static unsigned char
-bmac_clock_out_bit(struct device *dev)
+bmac_clock_out_bit(struct net_device *dev)
 {
 	unsigned short         data;
 	unsigned short         val;
@@ -1071,7 +1071,7 @@
 }
 
 static void
-bmac_clock_in_bit(struct device *dev, unsigned int val)
+bmac_clock_in_bit(struct net_device *dev, unsigned int val)
 {
 	unsigned short		data;    
 
@@ -1089,7 +1089,7 @@
 }
 
 static void
-reset_and_select_srom(struct device *dev)
+reset_and_select_srom(struct net_device *dev)
 {
 	/* first reset */
 	bmwrite(dev, SROMCSR, 0);
@@ -1102,7 +1102,7 @@
 }
 
 static unsigned short
-read_srom(struct device *dev, unsigned int addr, unsigned int addr_len)
+read_srom(struct net_device *dev, unsigned int addr, unsigned int addr_len)
 {
 	unsigned short data, val;
 	int i;
@@ -1131,7 +1131,7 @@
  */
 
 static int
-bmac_verify_checksum(struct device *dev)
+bmac_verify_checksum(struct net_device *dev)
 {
 	unsigned short data, storedCS;
     
@@ -1144,7 +1144,7 @@
 
 
 static void
-bmac_get_station_address(struct device *dev, unsigned char *ea)
+bmac_get_station_address(struct net_device *dev, unsigned char *ea)
 {
 	int i;
 	unsigned short data;
@@ -1158,7 +1158,7 @@
 		}
 }
 
-static int bmac_reset_and_enable(struct device *dev, int enable)
+static int bmac_reset_and_enable(struct net_device *dev, int enable)
 {
 	struct bmac_data *bp = dev->priv;
 	unsigned long flags;
@@ -1191,7 +1191,7 @@
 }
 
 int
-bmac_probe(struct device *dev)
+bmac_probe(struct net_device *dev)
 {
 	int j, rev;
 	struct bmac_data *bp;
@@ -1322,7 +1322,7 @@
 	return 0;
 }
 
-static int bmac_open(struct device *dev)
+static int bmac_open(struct net_device *dev)
 {
 	/* XXDEBUG(("bmac: enter open\n")); */
 	/* reset the chip */
@@ -1333,7 +1333,7 @@
 	return 0;
 }
 
-static int bmac_close(struct device *dev)
+static int bmac_close(struct net_device *dev)
 {
 	struct bmac_data *bp = (struct bmac_data *) dev->priv;
 	volatile struct dbdma_regs *rd = bp->rx_dma;
@@ -1379,7 +1379,7 @@
 }
 
 static void
-bmac_start(struct device *dev)
+bmac_start(struct net_device *dev)
 {
 	struct bmac_data *bp = dev->priv;
 	int i;
@@ -1399,7 +1399,7 @@
 }
 
 static int
-bmac_output(struct sk_buff *skb, struct device *dev)
+bmac_output(struct sk_buff *skb, struct net_device *dev)
 {
 	struct bmac_data *bp = dev->priv;
 	skb_queue_tail(bp->queue, skb);
@@ -1409,7 +1409,7 @@
 
 static void bmac_tx_timeout(unsigned long data)
 {
-	struct device *dev = (struct device *) data;
+	struct net_device *dev = (struct net_device *) data;
 	struct bmac_data *bp = (struct bmac_data *) dev->priv;
 	volatile struct dbdma_regs *td = bp->tx_dma;
 	volatile struct dbdma_regs *rd = bp->rx_dma;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/com20020.c linux/drivers/net/com20020.c
--- v2.3.13/linux/drivers/net/com20020.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/com20020.c	Wed Aug 18 11:36:41 1999
@@ -58,23 +58,23 @@
 
 /* Internal function declarations */
 
-static int arc20020_probe(struct device *dev);
-static void arc20020_rx(struct device *dev,int recbuf);
-static int arc20020_found(struct device *dev,int ioaddr,int airq);
-static void arc20020_inthandler (struct device *dev);
-static int arc20020_reset (struct device *dev, int reset_delay);
-static void arc20020_setmask (struct device *dev, u_char mask);
-static void arc20020_command (struct device *dev, u_char command);
-static u_char arc20020_status (struct device *dev);
-static void arc20020_en_dis_able_TX (struct device *dev, int enable); 
-static void arc20020_prepare_tx(struct device *dev,u_char *hdr,int hdrlen,
+static int arc20020_probe(struct net_device *dev);
+static void arc20020_rx(struct net_device *dev,int recbuf);
+static int arc20020_found(struct net_device *dev,int ioaddr,int airq);
+static void arc20020_inthandler (struct net_device *dev);
+static int arc20020_reset (struct net_device *dev, int reset_delay);
+static void arc20020_setmask (struct net_device *dev, u_char mask);
+static void arc20020_command (struct net_device *dev, u_char command);
+static u_char arc20020_status (struct net_device *dev);
+static void arc20020_en_dis_able_TX (struct net_device *dev, int enable); 
+static void arc20020_prepare_tx(struct net_device *dev,u_char *hdr,int hdrlen,
        		      char *data,int length,int daddr,int exceptA, int offset);
 static  void arc20020_openclose(int open);
-static void arc20020_set_mc_list(struct device *dev);
-static u_char get_buffer_byte (struct device *dev, unsigned offset);
-static void put_buffer_byte (struct device *dev, unsigned offset, u_char datum);
-static void get_whole_buffer (struct device *dev, unsigned offset, unsigned length, char *dest);
-static void put_whole_buffer (struct device *dev, unsigned offset, unsigned length, char *dest);
+static void arc20020_set_mc_list(struct net_device *dev);
+static u_char get_buffer_byte (struct net_device *dev, unsigned offset);
+static void put_buffer_byte (struct net_device *dev, unsigned offset, u_char datum);
+static void get_whole_buffer (struct net_device *dev, unsigned offset, unsigned length, char *dest);
+static void put_whole_buffer (struct net_device *dev, unsigned offset, unsigned length, char *dest);
 
 
 /* Module parameters */
@@ -97,7 +97,7 @@
 MODULE_PARM(clock,"i");
 #else
 void __init com20020_setup (char *str, int *ints);
-extern struct device arcnet_devs[];
+extern struct net_device arcnet_devs[];
 extern char arcnet_dev_names[][10];
 extern int arcnet_num_devs;
 #endif
@@ -155,7 +155,7 @@
  *                                                                          *
  ****************************************************************************/
 
-u_char get_buffer_byte (struct device *dev, unsigned offset)
+u_char get_buffer_byte (struct net_device *dev, unsigned offset)
 {
   int ioaddr=dev->base_addr;
 
@@ -165,7 +165,7 @@
   return inb(_MEMDATA);
 }
 
-void put_buffer_byte (struct device *dev, unsigned offset, u_char datum)
+void put_buffer_byte (struct net_device *dev, unsigned offset, u_char datum)
 {
   int ioaddr=dev->base_addr;
 
@@ -179,7 +179,7 @@
 #undef ONE_AT_A_TIME_TX
 #undef ONE_AT_A_TIME_RX
 
-void get_whole_buffer (struct device *dev, unsigned offset, unsigned length, char *dest)
+void get_whole_buffer (struct net_device *dev, unsigned offset, unsigned length, char *dest)
 {
   int ioaddr=dev->base_addr;
 
@@ -194,7 +194,7 @@
 #endif
 }
 
-void put_whole_buffer (struct device *dev, unsigned offset, unsigned length, char *dest)
+void put_whole_buffer (struct net_device *dev, unsigned offset, unsigned length, char *dest)
 {
   int ioaddr=dev->base_addr;
 
@@ -224,7 +224,7 @@
  * it's where we were told it was, and even autoirq
  */
 
-int __init arc20020_probe(struct device *dev)
+int __init arc20020_probe(struct net_device *dev)
 {
   int ioaddr=dev->base_addr,status,delayval;
   unsigned long airqmask;
@@ -324,10 +324,10 @@
 }
 
 
-/* Set up the struct device associated with this card.  Called after
+/* Set up the struct net_device associated with this card.  Called after
  * probing succeeds.
  */
-int __init arc20020_found(struct device *dev,int ioaddr,int airq)
+int __init arc20020_found(struct net_device *dev,int ioaddr,int airq)
 {
   struct arcnet_local *lp;
   
@@ -444,7 +444,7 @@
  *
  * However, it does make sure the card is in a defined state.
  */
-int arc20020_reset(struct device *dev,int reset_delay)
+int arc20020_reset(struct net_device *dev,int reset_delay)
 {
   struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
   short ioaddr=dev->base_addr;
@@ -515,7 +515,7 @@
  *      FIX ME - do multicast stuff, not just promiscuous.
  */
 static void
-arc20020_set_mc_list(struct device *dev)
+arc20020_set_mc_list(struct net_device *dev)
 {
   struct arcnet_local *lp=dev->priv;
   int ioaddr=dev->base_addr;
@@ -550,7 +550,7 @@
 }
 
 
-static void arc20020_en_dis_able_TX(struct device *dev, int enable)
+static void arc20020_en_dis_able_TX(struct net_device *dev, int enable)
 {
   struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
   int ioaddr=dev->base_addr;
@@ -560,7 +560,7 @@
 }
 
 
-static void arc20020_setmask(struct device *dev, u_char mask)
+static void arc20020_setmask(struct net_device *dev, u_char mask)
 {
   short ioaddr=dev->base_addr;
 
@@ -568,7 +568,7 @@
 }
 
 
-static u_char arc20020_status(struct device *dev)
+static u_char arc20020_status(struct net_device *dev)
 {
   short ioaddr=dev->base_addr;
 
@@ -576,7 +576,7 @@
 }
 
 
-static void arc20020_command(struct device *dev, u_char cmd)
+static void arc20020_command(struct net_device *dev, u_char cmd)
 {
   short ioaddr=dev->base_addr;
 
@@ -588,7 +588,7 @@
  * by the card.
  */
 static void
-arc20020_inthandler(struct device *dev)
+arc20020_inthandler(struct net_device *dev)
 {
   struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
   int ioaddr=dev->base_addr, status, boguscount = 3, didsomething,
@@ -828,7 +828,7 @@
  */
 
 static void
-arc20020_rx(struct device *dev,int recbuf)
+arc20020_rx(struct net_device *dev,int recbuf)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
   int ioaddr=dev->base_addr;
@@ -885,7 +885,7 @@
  * by arcnet_go_tx.
  */
 static void
-arc20020_prepare_tx(struct device *dev,u_char *hdr,int hdrlen,
+arc20020_prepare_tx(struct net_device *dev,u_char *hdr,int hdrlen,
 		    char *data,int length,int daddr,int exceptA, int offset)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
@@ -957,19 +957,19 @@
 
 #ifdef MODULE
 
-static struct device *cards[16]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+static struct net_device *cards[16]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
 			  NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
 
 
 int init_module(void)
 {
-  struct device *dev;
+  struct net_device *dev;
 
-  cards[0]=dev=(struct device *)kmalloc(sizeof(struct device), GFP_KERNEL);
+  cards[0]=dev=(struct net_device *)kmalloc(sizeof(struct net_device), GFP_KERNEL);
   if (!dev)
     return -ENOMEM;
 
-  memset(dev, 0, sizeof(struct device));
+  memset(dev, 0, sizeof(struct net_device));
 
   dev->name=(char *)kmalloc(9, GFP_KERNEL);
   if (!dev->name)
@@ -1006,7 +1006,7 @@
 
 void cleanup_module(void)
 {
-  struct device *dev=cards[0];
+  struct net_device *dev=cards[0];
   int ioaddr=dev->base_addr;
 
   if (dev->start) (*dev->stop)(dev);
@@ -1037,7 +1037,7 @@
 
 void __init com20020_setup (char *str, int *ints)
 {
-  struct device *dev;
+  struct net_device *dev;
 
   if (arcnet_num_devs == MAX_ARCNET_DEVS)
     {
diff -u --recursive --new-file v2.3.13/linux/drivers/net/com90io.c linux/drivers/net/com90io.c
--- v2.3.13/linux/drivers/net/com90io.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/com90io.c	Wed Aug 18 11:36:41 1999
@@ -58,22 +58,22 @@
 
 /* Internal function declarations */
 
-static int arc90io_probe(struct device *dev);
-static void arc90io_rx(struct device *dev,int recbuf);
-static int arc90io_found(struct device *dev,int ioaddr,int airq);
-static void arc90io_inthandler (struct device *dev);
-static int arc90io_reset (struct device *dev, int reset_delay);
-static void arc90io_setmask (struct device *dev, u_char mask);
-static void arc90io_command (struct device *dev, u_char command);
-static u_char arc90io_status (struct device *dev);
-static void arc90io_prepare_tx(struct device *dev,u_char *hdr,int hdrlen,
+static int arc90io_probe(struct net_device *dev);
+static void arc90io_rx(struct net_device *dev,int recbuf);
+static int arc90io_found(struct net_device *dev,int ioaddr,int airq);
+static void arc90io_inthandler (struct net_device *dev);
+static int arc90io_reset (struct net_device *dev, int reset_delay);
+static void arc90io_setmask (struct net_device *dev, u_char mask);
+static void arc90io_command (struct net_device *dev, u_char command);
+static u_char arc90io_status (struct net_device *dev);
+static void arc90io_prepare_tx(struct net_device *dev,u_char *hdr,int hdrlen,
        		      char *data,int length,int daddr,int exceptA, int offset);
 static  void arc90io_openclose(int open);
 
-static u_char get_buffer_byte (struct device *dev, unsigned offset);
-static void put_buffer_byte (struct device *dev, unsigned offset, u_char datum);
-static void get_whole_buffer (struct device *dev, unsigned offset, unsigned length, char *dest);
-static void put_whole_buffer (struct device *dev, unsigned offset, unsigned length, char *dest);
+static u_char get_buffer_byte (struct net_device *dev, unsigned offset);
+static void put_buffer_byte (struct net_device *dev, unsigned offset, u_char datum);
+static void get_whole_buffer (struct net_device *dev, unsigned offset, unsigned length, char *dest);
+static void put_whole_buffer (struct net_device *dev, unsigned offset, unsigned length, char *dest);
 
 
 /* Module parameters */
@@ -88,7 +88,7 @@
 MODULE_PARM(device, "s");
 #else
 void __init com90io_setup (char *str, int *ints);
-extern struct device arcnet_devs[];
+extern struct net_device arcnet_devs[];
 extern char arcnet_dev_names[][10];
 extern int arcnet_num_devs;
 #endif
@@ -124,7 +124,7 @@
  *                                                                          *
  ****************************************************************************/
 
-u_char get_buffer_byte (struct device *dev, unsigned offset)
+u_char get_buffer_byte (struct net_device *dev, unsigned offset)
 {
   int ioaddr=dev->base_addr;
 
@@ -134,7 +134,7 @@
   return inb(_MEMDATA);
 }
 
-void put_buffer_byte (struct device *dev, unsigned offset, u_char datum)
+void put_buffer_byte (struct net_device *dev, unsigned offset, u_char datum)
 {
   int ioaddr=dev->base_addr;
 
@@ -148,7 +148,7 @@
 #undef ONE_AT_A_TIME_TX
 #undef ONE_AT_A_TIME_RX
 
-void get_whole_buffer (struct device *dev, unsigned offset, unsigned length, char *dest)
+void get_whole_buffer (struct net_device *dev, unsigned offset, unsigned length, char *dest)
 {
   int ioaddr=dev->base_addr;
 
@@ -163,7 +163,7 @@
 #endif
 }
 
-void put_whole_buffer (struct device *dev, unsigned offset, unsigned length, char *dest)
+void put_whole_buffer (struct net_device *dev, unsigned offset, unsigned length, char *dest)
 {
   int ioaddr=dev->base_addr;
 
@@ -193,7 +193,7 @@
  * it's where we were told it was, and even autoirq
  */
 
-int __init arc90io_probe(struct device *dev)
+int __init arc90io_probe(struct net_device *dev)
 {
   int ioaddr=dev->base_addr,status,delayval;
   unsigned long airqmask;
@@ -284,10 +284,10 @@
 }
 
 
-/* Set up the struct device associated with this card.  Called after
+/* Set up the struct net_device associated with this card.  Called after
  * probing succeeds.
  */
-int __init arc90io_found(struct device *dev,int ioaddr,int airq)
+int __init arc90io_found(struct net_device *dev,int ioaddr,int airq)
 {
   struct arcnet_local *lp;
 
@@ -381,7 +381,7 @@
  *
  * However, it does make sure the card is in a defined state.
  */
-int arc90io_reset(struct device *dev,int reset_delay)
+int arc90io_reset(struct net_device *dev,int reset_delay)
 {
   struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
   short ioaddr=dev->base_addr;
@@ -453,21 +453,21 @@
 }
 
 
-static void arc90io_setmask(struct device *dev, u_char mask)
+static void arc90io_setmask(struct net_device *dev, u_char mask)
 {
   short ioaddr=dev->base_addr;
 
   AINTMASK(mask);
 }
 
-static u_char arc90io_status(struct device *dev)
+static u_char arc90io_status(struct net_device *dev)
 {
   short ioaddr=dev->base_addr;
 
   return ARCSTATUS;
 }
 
-static void arc90io_command(struct device *dev, u_char cmd)
+static void arc90io_command(struct net_device *dev, u_char cmd)
 {
   short ioaddr=dev->base_addr;
 
@@ -479,7 +479,7 @@
  * by the card.
  */
 static void
-arc90io_inthandler(struct device *dev)
+arc90io_inthandler(struct net_device *dev)
 {
   struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
   int ioaddr=dev->base_addr, status, boguscount = 3, didsomething;
@@ -711,7 +711,7 @@
  */
 
 static void
-arc90io_rx(struct device *dev,int recbuf)
+arc90io_rx(struct net_device *dev,int recbuf)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
   int ioaddr=dev->base_addr;
@@ -768,7 +768,7 @@
  * by arcnet_go_tx.
  */
 static void
-arc90io_prepare_tx(struct device *dev,u_char *hdr,int hdrlen,
+arc90io_prepare_tx(struct net_device *dev,u_char *hdr,int hdrlen,
 		    char *data,int length,int daddr,int exceptA, int offset)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
@@ -840,19 +840,19 @@
 
 #ifdef MODULE
 
-static struct device *cards[16]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+static struct net_device *cards[16]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
 			  NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
 
 
 int init_module(void)
 {
-  struct device *dev=cards[0];
+  struct net_device *dev=cards[0];
 
-  cards[0]=dev=(struct device *)kmalloc(sizeof(struct device), GFP_KERNEL);
+  cards[0]=dev=(struct net_device *)kmalloc(sizeof(struct net_device), GFP_KERNEL);
   if (!dev)
     return -ENOMEM;
 
-  memset(dev, 0, sizeof(struct device));
+  memset(dev, 0, sizeof(struct net_device));
 
   dev->name=(char *)kmalloc(9, GFP_KERNEL);
   if (!dev->name)
@@ -881,7 +881,7 @@
 
 void cleanup_module(void)
 {
-  struct device *dev=cards[0];
+  struct net_device *dev=cards[0];
   int ioaddr=dev->base_addr;
 
   if (dev->start) (*dev->stop)(dev);
@@ -916,7 +916,7 @@
 
 void __init com90io_setup (char *str, int *ints)
 {
-  struct device *dev;
+  struct net_device *dev;
 
   if (arcnet_num_devs == MAX_ARCNET_DEVS)
     {
diff -u --recursive --new-file v2.3.13/linux/drivers/net/com90xx.c linux/drivers/net/com90xx.c
--- v2.3.13/linux/drivers/net/com90xx.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/com90xx.c	Wed Aug 18 11:36:41 1999
@@ -91,15 +91,15 @@
 #ifdef MODULE
 static
 #endif
-int arc90xx_probe(struct device *dev);
-static void arc90xx_rx(struct device *dev, int recbuf);
-static int arc90xx_found(struct device *dev, int ioaddr, int airq, u_long shmem, int more);
-static void arc90xx_inthandler(struct device *dev);
-static int arc90xx_reset(struct device *dev, int reset_delay);
-static void arc90xx_setmask(struct device *dev, u_char mask);
-static void arc90xx_command(struct device *dev, u_char command);
-static u_char arc90xx_status(struct device *dev);
-static void arc90xx_prepare_tx(struct device *dev, u_char * hdr, int hdrlen,
+int arc90xx_probe(struct net_device *dev);
+static void arc90xx_rx(struct net_device *dev, int recbuf);
+static int arc90xx_found(struct net_device *dev, int ioaddr, int airq, u_long shmem, int more);
+static void arc90xx_inthandler(struct net_device *dev);
+static int arc90xx_reset(struct net_device *dev, int reset_delay);
+static void arc90xx_setmask(struct net_device *dev, u_char mask);
+static void arc90xx_command(struct net_device *dev, u_char command);
+static u_char arc90xx_status(struct net_device *dev);
+static void arc90xx_prepare_tx(struct net_device *dev, u_char * hdr, int hdrlen,
 	     char *data, int length, int daddr, int exceptA, int offset);
 static void arc90xx_openclose(int open);
 
@@ -120,7 +120,7 @@
 void __init com90xx_setup(char *str, int *ints);
 char __initdata com90xx_explicit = 0;
 
-extern struct device arcnet_devs[];
+extern struct net_device arcnet_devs[];
 extern char arcnet_dev_names[][10];
 extern int arcnet_num_devs;
 #endif
@@ -179,7 +179,7 @@
 	0
 };
 
-int __init arc90xx_probe(struct device *dev)
+int __init arc90xx_probe(struct net_device *dev)
 {
 	static int init_once = 0;
 	static int numports = sizeof(ports) / sizeof(ports[0]), numshmems = sizeof(shmems) / sizeof(shmems[0]);
@@ -490,10 +490,10 @@
 	return retval;
 }
 
-/* Set up the struct device associated with this card.  Called after
+/* Set up the struct net_device associated with this card.  Called after
  * probing succeeds.
  */
-static int __init arc90xx_found(struct device *dev, int ioaddr, int airq, u_long shmem, int more)
+static int __init arc90xx_found(struct net_device *dev, int ioaddr, int airq, u_long shmem, int more)
 {
 	struct arcnet_local *lp;
 	u_long first_mirror, last_mirror;
@@ -623,7 +623,7 @@
  *
  * However, it does make sure the card is in a defined state.
  */
-int arc90xx_reset(struct device *dev, int reset_delay)
+int arc90xx_reset(struct net_device *dev, int reset_delay)
 {
 	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
 	short ioaddr = dev->base_addr;
@@ -690,7 +690,7 @@
 }
 
 
-static void arc90xx_setmask(struct device *dev, u_char mask)
+static void arc90xx_setmask(struct net_device *dev, u_char mask)
 {
 	short ioaddr = dev->base_addr;
 
@@ -698,7 +698,7 @@
 }
 
 
-static u_char arc90xx_status(struct device *dev)
+static u_char arc90xx_status(struct net_device *dev)
 {
 	short ioaddr = dev->base_addr;
 
@@ -706,7 +706,7 @@
 }
 
 
-static void arc90xx_command(struct device *dev, u_char cmd)
+static void arc90xx_command(struct net_device *dev, u_char cmd)
 {
 	short ioaddr = dev->base_addr;
 
@@ -717,7 +717,7 @@
 /* The actual interrupt handler routine - handle various IRQ's generated
  * by the card.
  */
-static void arc90xx_inthandler(struct device *dev)
+static void arc90xx_inthandler(struct net_device *dev)
 {
 	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
 	int ioaddr = dev->base_addr, status, boguscount = 3, didsomething;
@@ -909,7 +909,7 @@
  * arcnet_rx routing to deal with it.
  */
 
-static void arc90xx_rx(struct device *dev, int recbuf)
+static void arc90xx_rx(struct net_device *dev, int recbuf)
 {
 	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
 	int ioaddr = dev->base_addr;
@@ -962,7 +962,7 @@
 /* Given an skb, copy a packet into the ARCnet buffers for later transmission
  * by arcnet_go_tx.
  */
-static void arc90xx_prepare_tx(struct device *dev, u_char * hdr, int hdrlen,
+static void arc90xx_prepare_tx(struct net_device *dev, u_char * hdr, int hdrlen,
 	      char *data, int length, int daddr, int exceptA, int offset)
 {
 	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
@@ -1053,7 +1053,7 @@
 #ifdef MODULE
 
 static char devicename[9] = "";
-static struct device thiscard =
+static struct net_device thiscard =
 {
 	devicename,		/* device name is inserted by linux/drivers/net/net_init.c */
 	0, 0, 0, 0,
@@ -1064,7 +1064,7 @@
 
 int init_module(void)
 {
-	struct device *dev = &thiscard;
+	struct net_device *dev = &thiscard;
 	if (device)
 		strcpy(dev->name, device);
 	else
@@ -1090,7 +1090,7 @@
 
 void cleanup_module(void)
 {
-	struct device *dev = &thiscard;
+	struct net_device *dev = &thiscard;
 	int ioaddr = dev->mem_start;
 
 	if (dev->start)
@@ -1123,7 +1123,7 @@
 
 void __init com90xx_setup(char *str, int *ints)
 {
-	struct device *dev;
+	struct net_device *dev;
 
 	if (arcnet_num_devs == MAX_ARCNET_DEVS) {
 		printk("com90xx: Too many ARCnet devices registered (max %d).\n",
diff -u --recursive --new-file v2.3.13/linux/drivers/net/cops.c linux/drivers/net/cops.c
--- v2.3.13/linux/drivers/net/cops.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/cops.c	Wed Aug 18 11:36:41 1999
@@ -188,28 +188,28 @@
 };
 
 /* Index to functions, as function prototypes. */
-extern int  cops_probe (struct device *dev);
-static int  cops_probe1 (struct device *dev, int ioaddr);
+extern int  cops_probe (struct net_device *dev);
+static int  cops_probe1 (struct net_device *dev, int ioaddr);
 static int  cops_irq (int ioaddr, int board);
 
-static int  cops_open (struct device *dev);
-static int  cops_jumpstart (struct device *dev);
-static void cops_reset (struct device *dev, int sleep);
-static void cops_load (struct device *dev);
-static int  cops_nodeid (struct device *dev, int nodeid);
+static int  cops_open (struct net_device *dev);
+static int  cops_jumpstart (struct net_device *dev);
+static void cops_reset (struct net_device *dev, int sleep);
+static void cops_load (struct net_device *dev);
+static int  cops_nodeid (struct net_device *dev, int nodeid);
 
 static void cops_interrupt (int irq, void *dev_id, struct pt_regs *regs);
 static void cops_poll (unsigned long ltdev);
-static void cops_rx (struct device *dev);
-static int  cops_send_packet (struct sk_buff *skb, struct device *dev);
-static void set_multicast_list (struct device *dev);
-static int  cops_hard_header (struct sk_buff *skb, struct device *dev,
+static void cops_rx (struct net_device *dev);
+static int  cops_send_packet (struct sk_buff *skb, struct net_device *dev);
+static void set_multicast_list (struct net_device *dev);
+static int  cops_hard_header (struct sk_buff *skb, struct net_device *dev,
 			      unsigned short type, void *daddr, void *saddr, 
 			      unsigned len);
 
-static int  cops_ioctl (struct device *dev, struct ifreq *rq, int cmd);
-static int  cops_close (struct device *dev);
-static struct enet_statistics *cops_get_stats (struct device *dev);
+static int  cops_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
+static int  cops_close (struct net_device *dev);
+static struct enet_statistics *cops_get_stats (struct net_device *dev);
 
 
 /*
@@ -218,7 +218,7 @@
  *      If dev->base_addr in [1..0x1ff], always return failure.
  *        otherwise go with what we pass in.
  */
-int __init cops_probe(struct device *dev)
+int __init cops_probe(struct net_device *dev)
 {
 	int i;
         int base_addr = dev ? dev->base_addr : 0;
@@ -252,7 +252,7 @@
  *      probes on the ISA bus. A good device probes avoids doing writes, and
  *      verifies that the correct device exists and functions.
  */
-static int __init cops_probe1(struct device *dev, int ioaddr)
+static int __init cops_probe1(struct net_device *dev, int ioaddr)
 {
         struct cops_local *lp;
 	static unsigned version_printed = 0;
@@ -397,7 +397,7 @@
  * Open/initialize the board. This is called (in the current kernel)
  * sometime after booting when the 'ifconfig' program is run.
  */
-static int cops_open(struct device *dev)
+static int cops_open(struct net_device *dev)
 {
     struct cops_local *lp = (struct cops_local *)dev->priv;
 
@@ -438,7 +438,7 @@
 /*
  *	This allows for a dynamic start/restart of the entire card.
  */
-static int cops_jumpstart(struct device *dev)
+static int cops_jumpstart(struct net_device *dev)
 {
 	struct cops_local *lp = (struct cops_local *)dev->priv;
 
@@ -472,7 +472,7 @@
 /*
  *      Reset the LocalTalk board.
  */
-static void cops_reset(struct device *dev, int sleep)
+static void cops_reset(struct net_device *dev, int sleep)
 {
         struct cops_local *lp = (struct cops_local *)dev->priv;
         int ioaddr=dev->base_addr;
@@ -506,7 +506,7 @@
 	return;
 }
 
-static void cops_load (struct device *dev)
+static void cops_load (struct net_device *dev)
 {
         struct ifreq ifr;
         struct ltfirmware *ltf= (struct ltfirmware *)&ifr.ifr_data;
@@ -601,7 +601,7 @@
  *	address else we can specify 0 as the nodeid and the card
  *	will autoprobe for a nodeid.
  */
-static int cops_nodeid (struct device *dev, int nodeid)
+static int cops_nodeid (struct net_device *dev, int nodeid)
 {
 	struct cops_local *lp = (struct cops_local *) dev->priv;
 	int ioaddr = dev->base_addr;
@@ -678,7 +678,7 @@
 	int ioaddr, status;
 	int boguscount = 0;
 
-	struct device *dev = (struct device *)ltdev;
+	struct net_device *dev = (struct net_device *)ltdev;
 
 	del_timer(&cops_timer);
 
@@ -707,7 +707,7 @@
  */
 static void cops_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
-        struct device *dev = dev_id;
+        struct net_device *dev = dev_id;
         struct cops_local *lp;
         int ioaddr, status;
         int boguscount = 0;
@@ -754,7 +754,7 @@
 /*
  *      We have a good packet(s), get it/them out of the buffers.
  */
-static void cops_rx(struct device *dev)
+static void cops_rx(struct net_device *dev)
 {
         int pkt_len = 0;
         int rsp_type = 0;
@@ -860,7 +860,7 @@
 /*
  *	Make the card transmit a LocalTalk packet.
  */
-static int cops_send_packet(struct sk_buff *skb, struct device *dev)
+static int cops_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
         struct cops_local *lp = (struct cops_local *)dev->priv;
         int ioaddr = dev->base_addr;
@@ -937,7 +937,7 @@
  *	Dummy function to keep the Appletalk layer happy.
  */
  
-static void set_multicast_list(struct device *dev)
+static void set_multicast_list(struct net_device *dev)
 {
         if(cops_debug >= 3)
 		printk("%s: set_multicast_list executed\n", dev->name);
@@ -947,7 +947,7 @@
  *      Another Dummy function to keep the Appletalk layer happy.
  */
  
-static int cops_hard_header(struct sk_buff *skb, struct device *dev,
+static int cops_hard_header(struct sk_buff *skb, struct net_device *dev,
 			    unsigned short type, void *daddr, void *saddr, 
 			    unsigned len)
 {
@@ -960,7 +960,7 @@
  *      System ioctls for the COPS LocalTalk card.
  */
  
-static int cops_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
+static int cops_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
         struct cops_local *lp = (struct cops_local *)dev->priv;
         struct sockaddr_at *sa=(struct sockaddr_at *)&ifr->ifr_addr;
@@ -996,7 +996,7 @@
  *	The inverse routine to cops_open().
  */
  
-static int cops_close(struct device *dev)
+static int cops_close(struct net_device *dev)
 {
 	struct cops_local *lp = (struct cops_local *)dev->priv;
 
@@ -1019,7 +1019,7 @@
  *      Get the current statistics.
  *      This may be called with the card open or closed.
  */
-static struct enet_statistics *cops_get_stats(struct device *dev)
+static struct enet_statistics *cops_get_stats(struct net_device *dev)
 {
         struct cops_local *lp = (struct cops_local *)dev->priv;
         return &lp->stats;
@@ -1028,7 +1028,7 @@
 #ifdef MODULE
 static char lt_name[16];
 
-static struct device cops0_dev =
+static struct net_device cops0_dev =
 {
 	lt_name,	/* device name */
         0, 0, 0, 0,
diff -u --recursive --new-file v2.3.13/linux/drivers/net/cosa.c linux/drivers/net/cosa.c
--- v2.3.13/linux/drivers/net/cosa.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/cosa.c	Wed Aug 18 11:36:41 1999
@@ -274,14 +274,14 @@
 /* SPPP/HDLC stuff */
 static void sppp_channel_init(struct channel_data *chan);
 static void sppp_channel_delete(struct channel_data *chan);
-static int cosa_sppp_open(struct device *d);
-static int cosa_sppp_close(struct device *d);
-static int cosa_sppp_tx(struct sk_buff *skb, struct device *d);
+static int cosa_sppp_open(struct net_device *d);
+static int cosa_sppp_close(struct net_device *d);
+static int cosa_sppp_tx(struct sk_buff *skb, struct net_device *d);
 static char *sppp_setup_rx(struct channel_data *channel, int size);
 static int sppp_rx_done(struct channel_data *channel);
 static int sppp_tx_done(struct channel_data *channel, int size);
-static int cosa_sppp_ioctl(struct device *dev, struct ifreq *ifr, int cmd);
-static struct net_device_stats *cosa_net_stats(struct device *dev);
+static int cosa_sppp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
+static struct net_device_stats *cosa_net_stats(struct net_device *dev);
 
 /* Character device */
 static void chardev_channel_init(struct channel_data *chan);
@@ -568,7 +568,7 @@
 
 static void sppp_channel_init(struct channel_data *chan)
 {
-	struct device *d;
+	struct net_device *d;
 	sppp_attach(&chan->pppdev);
 	d=&chan->pppdev.dev;
 	d->name = chan->name;
@@ -597,7 +597,7 @@
 }
 
 
-static int cosa_sppp_open(struct device *d)
+static int cosa_sppp_open(struct net_device *d)
 {
 	struct channel_data *chan = d->priv;
 	int err, flags;
@@ -633,7 +633,7 @@
 	return 0;
 }
 
-static int cosa_sppp_tx(struct sk_buff *skb, struct device *dev)
+static int cosa_sppp_tx(struct sk_buff *skb, struct net_device *dev)
 {
 	struct channel_data *chan = dev->priv;
 
@@ -665,7 +665,7 @@
 	return 0;
 }
 
-static int cosa_sppp_close(struct device *d)
+static int cosa_sppp_close(struct net_device *d)
 {
 	struct channel_data *chan = d->priv;
 	int flags;
@@ -747,7 +747,7 @@
 	return 1;
 }
 
-static struct net_device_stats *cosa_net_stats(struct device *dev)
+static struct net_device_stats *cosa_net_stats(struct net_device *dev)
 {
 	struct channel_data *chan = dev->priv;
 	return &chan->stats;
@@ -1166,7 +1166,7 @@
 	return -ENOIOCTLCMD;
 }
 
-static int cosa_sppp_ioctl(struct device *dev, struct ifreq *ifr,
+static int cosa_sppp_ioctl(struct net_device *dev, struct ifreq *ifr,
 	int cmd)
 {
 	int rv;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/cs89x0.c linux/drivers/net/cs89x0.c
--- v2.3.13/linux/drivers/net/cs89x0.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/cs89x0.c	Wed Aug 18 11:36:41 1999
@@ -113,20 +113,20 @@
 
 /* Index to functions, as function prototypes. */
 
-extern int cs89x0_probe(struct device *dev);
+extern int cs89x0_probe(struct net_device *dev);
 
-static int cs89x0_probe1(struct device *dev, int ioaddr);
-static int net_open(struct device *dev);
-static int	net_send_packet(struct sk_buff *skb, struct device *dev);
+static int cs89x0_probe1(struct net_device *dev, int ioaddr);
+static int net_open(struct net_device *dev);
+static int	net_send_packet(struct sk_buff *skb, struct net_device *dev);
 static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void set_multicast_list(struct device *dev);
-static void net_rx(struct device *dev);
-static int net_close(struct device *dev);
-static struct net_device_stats *net_get_stats(struct device *dev);
-static void reset_chip(struct device *dev);
-static int get_eeprom_data(struct device *dev, int off, int len, int *buffer);
+static void set_multicast_list(struct net_device *dev);
+static void net_rx(struct net_device *dev);
+static int net_close(struct net_device *dev);
+static struct net_device_stats *net_get_stats(struct net_device *dev);
+static void reset_chip(struct net_device *dev);
+static int get_eeprom_data(struct net_device *dev, int off, int len, int *buffer);
 static int get_eeprom_cksum(int off, int len, int *buffer);
-static int set_mac_address(struct device *dev, void *addr);
+static int set_mac_address(struct net_device *dev, void *addr);
 
 
 /* Example routines you must write ;->. */
@@ -146,7 +146,7 @@
 {"netcard", cs89x0_probe1, NETCARD_IO_EXTENT, netcard_portlist};
 #else
 int __init 
-cs89x0_probe(struct device *dev)
+cs89x0_probe(struct net_device *dev)
 {
 	int i;
 	int base_addr = dev ? dev->base_addr : 0;
@@ -169,14 +169,14 @@
 #endif
 
 static int inline
-readreg(struct device *dev, int portno)
+readreg(struct net_device *dev, int portno)
 {
 	outw(portno, dev->base_addr + ADD_PORT);
 	return inw(dev->base_addr + DATA_PORT);
 }
 
 static void inline
-writereg(struct device *dev, int portno, int value)
+writereg(struct net_device *dev, int portno, int value)
 {
 	outw(portno, dev->base_addr + ADD_PORT);
 	outw(value, dev->base_addr + DATA_PORT);
@@ -184,19 +184,19 @@
 
 
 static int inline
-readword(struct device *dev, int portno)
+readword(struct net_device *dev, int portno)
 {
 	return inw(dev->base_addr + portno);
 }
 
 static void inline
-writeword(struct device *dev, int portno, int value)
+writeword(struct net_device *dev, int portno, int value)
 {
 	outw(value, dev->base_addr + portno);
 }
 
 static int __init 
-wait_eeprom_ready(struct device *dev)
+wait_eeprom_ready(struct net_device *dev)
 {
 	int timeout = jiffies;
 	/* check to see if the EEPROM is ready, a timeout is used -
@@ -209,7 +209,7 @@
 }
 
 static int __init 
-get_eeprom_data(struct device *dev, int off, int len, int *buffer)
+get_eeprom_data(struct net_device *dev, int off, int len, int *buffer)
 {
 	int i;
 
@@ -244,7 +244,7 @@
    probes on the ISA bus.  A good device probes avoids doing writes, and
    verifies that the correct device exists and functions.  */
 
-static int __init cs89x0_probe1(struct device *dev, int ioaddr)
+static int __init cs89x0_probe1(struct net_device *dev, int ioaddr)
 {
 	struct net_local *lp;
 	static unsigned version_printed = 0;
@@ -391,7 +391,7 @@
 }
 
 void  __init 
-reset_chip(struct device *dev)
+reset_chip(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -421,7 +421,7 @@
 
 
 static void
-control_dc_dc(struct device *dev, int on_not_off)
+control_dc_dc(struct net_device *dev, int on_not_off)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	unsigned int selfcontrol;
@@ -442,7 +442,7 @@
 }
 
 static int
-detect_tp(struct device *dev)
+detect_tp(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int timenow = jiffies;
@@ -487,7 +487,7 @@
 
 /* send a test packet - return true if carrier bits are ok */
 static int
-send_test_pkt(struct device *dev)
+send_test_pkt(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr;
 	char test_packet[] = { 0,0,0,0,0,0, 0,0,0,0,0,0,
@@ -532,7 +532,7 @@
 
 
 static int
-detect_aui(struct device *dev)
+detect_aui(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 
@@ -548,7 +548,7 @@
 }
 
 static int
-detect_bnc(struct device *dev)
+detect_bnc(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 
@@ -565,7 +565,7 @@
 
 
 static void
-write_irq(struct device *dev, int chip_type, int irq)
+write_irq(struct net_device *dev, int chip_type, int irq)
 {
 	int i;
 
@@ -591,7 +591,7 @@
    there is non-reboot way to recover if something goes wrong.
    */
 static int
-net_open(struct device *dev)
+net_open(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int result = 0;
@@ -728,7 +728,7 @@
 }
 
 static int
-net_send_packet(struct sk_buff *skb, struct device *dev)
+net_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
 	if (dev->tbusy) {
 		/* If we get here, some higher level has decided we are broken.
@@ -787,7 +787,7 @@
    Handle the network interface interrupts. */
 static void net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
-	struct device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	struct net_local *lp;
 	int ioaddr, status;
 
@@ -857,7 +857,7 @@
 
 /* We have a good packet(s), get it/them out of the buffers. */
 static void
-net_rx(struct device *dev)
+net_rx(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -904,7 +904,7 @@
 
 /* The inverse routine to net_open(). */
 static int
-net_close(struct device *dev)
+net_close(struct net_device *dev)
 {
 
 	writereg(dev, PP_RxCFG, 0);
@@ -926,7 +926,7 @@
 /* Get the current statistics.	This may be called with the card open or
    closed. */
 static struct net_device_stats *
-net_get_stats(struct device *dev)
+net_get_stats(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 
@@ -939,7 +939,7 @@
 	return &lp->stats;
 }
 
-static void set_multicast_list(struct device *dev)
+static void set_multicast_list(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 
@@ -964,7 +964,7 @@
 }
 
 
-static int set_mac_address(struct device *dev, void *addr)
+static int set_mac_address(struct net_device *dev, void *addr)
 {
 	int i;
 	if (dev->start)
@@ -983,7 +983,7 @@
 #ifdef MODULE
 
 static char namespace[16] = "";
-static struct device dev_cs89x0 = {
+static struct net_device dev_cs89x0 = {
         NULL,
         0, 0, 0, 0,
         0, 0,
diff -u --recursive --new-file v2.3.13/linux/drivers/net/cycx_drv.c linux/drivers/net/cycx_drv.c
--- v2.3.13/linux/drivers/net/cycx_drv.c	Wed Jun 30 13:38:20 1999
+++ linux/drivers/net/cycx_drv.c	Thu Aug 12 09:46:13 1999
@@ -57,7 +57,7 @@
 #include <asm/io.h>		/* for inb(), outb(), etc. */
 
 #define	MOD_VERSION	0
-#define	MOD_RELEASE	1
+#define	MOD_RELEASE	2
 
 #ifdef MODULE
 MODULE_AUTHOR("Arnaldo Carvalho de Melo");
@@ -122,7 +122,6 @@
 {
 	printk(KERN_INFO "%s v%u.%u %s\n",
 		fullname, MOD_VERSION, MOD_RELEASE, copyright);
-	printk(KERN_INFO "version=0x%X\n", LINUX_VERSION_CODE);
 	return 0;
 }
 /* Module 'remove' entry point.
diff -u --recursive --new-file v2.3.13/linux/drivers/net/cycx_main.c linux/drivers/net/cycx_main.c
--- v2.3.13/linux/drivers/net/cycx_main.c	Wed Jun  2 14:40:22 1999
+++ linux/drivers/net/cycx_main.c	Thu Aug 12 09:46:13 1999
@@ -13,12 +13,15 @@
 *		as published by the Free Software Foundation; either version
 *		2 of the License, or (at your option) any later version.
 * ============================================================================
+* 1999/08/09	acme		removed references to enable_tx_int
+*				use spinlocks instead of cli/sti in
+*				cyclomx_set_state
 * 1999/05/19	acme		works directly linked into the kernel
 *				init_waitqueue_head for 2.3.* kernel
 * 1999/05/18	acme		major cleanup (polling not needed), etc
-* Aug 28, 1998	Arnaldo		minor cleanup (ioctls for firmware deleted)
+* 1998/08/28	acme		minor cleanup (ioctls for firmware deleted)
 *				queue_task activated
-* Aug 08, 1998	Arnaldo		Initial version.
+* 1998/08/08	acme		Initial version.
 */
 
 #include <linux/config.h>	/* OS configuration options */
@@ -43,7 +46,7 @@
 /* Defines & Macros */
 
 #define	DRV_VERSION	0		/* version number */
-#define	DRV_RELEASE	3		/* release (minor version) number */
+#define	DRV_RELEASE	4		/* release (minor version) number */
 #define	MAX_CARDS	1		/* max number of adapters */
 
 #ifndef	CONFIG_CYCLOMX_CARDS		/* configurable option */
@@ -118,7 +121,6 @@
 		wandev->magic    = ROUTER_MAGIC;
 		wandev->name     = card->devname;
 		wandev->private  = card;
-		wandev->enable_tx_int = 0;
 		wandev->setup    = &setup;
 		wandev->shutdown = &shutdown;
 		wandev->ioctl    = &ioctl;
@@ -239,7 +241,7 @@
 
 	/* Protocol-specific initialization */
 	switch (card->hw.fwid) {
-#ifdef	CONFIG_CYCLOMX_X25
+#ifdef CONFIG_CYCLOMX_X25
 		case CFID_X25_2X: err = cyx_init(card, conf); break;
 #endif
 		default:
@@ -254,7 +256,6 @@
 		return err;
 	}
 
-	wandev->critical = 0;
 	return 0;
 }
 
@@ -280,7 +281,6 @@
 	cycx_down(&card->hw);
 	printk(KERN_INFO "%s: irq %d being freed!\n", wandev->name,wandev->irq);
 	free_irq(wandev->irq, card);
-	wandev->critical = 0;
 	return 0;
 }
 
@@ -306,7 +306,8 @@
 static void cycx_isr (int irq, void *dev_id, struct pt_regs *regs)
 {
 #define	card	((cycx_t*)dev_id)
-	if (!card || card->wandev.state == WAN_UNCONFIGURED) return;
+	if (!card || card->wandev.state == WAN_UNCONFIGURED)
+		return;
 
 	if (card->in_isr) {
 		printk(KERN_WARNING "%s: interrupt re-entrancy on IRQ %d!\n",
@@ -314,7 +315,8 @@
 		return;
 	}
 
-	if (card->isr) card->isr(card);
+	if (card->isr)
+		card->isr(card);
 #undef	card
 }
 
@@ -345,9 +347,9 @@
 /* Set WAN device state.  */
 void cyclomx_set_state (cycx_t *card, int state)
 {
-	unsigned long flags;
+	unsigned long host_cpu_flags;
 
-	save_flags(flags); cli();
+	spin_lock_irqsave(&card->lock, host_cpu_flags);
 
 	if (card->wandev.state != state) {
 		switch (state) {
@@ -371,7 +373,7 @@
 	}
 
 	card->state_tick = jiffies;
-	restore_flags(flags);
+	spin_unlock_irqrestore(&card->lock, host_cpu_flags);
 }
 
 /* End */
diff -u --recursive --new-file v2.3.13/linux/drivers/net/cycx_x25.c linux/drivers/net/cycx_x25.c
--- v2.3.13/linux/drivers/net/cycx_x25.c	Wed Jun  2 14:40:22 1999
+++ linux/drivers/net/cycx_x25.c	Wed Aug 18 11:36:41 1999
@@ -11,6 +11,10 @@
 *		as published by the Free Software Foundation; either version
 *		2 of the License, or (at your option) any later version.
 * ============================================================================
+* 1999/08/10	acme		serialized access to the card thru a spinlock
+*				in x25_exec
+* 1999/08/09	acme		removed per channel spinlocks
+*				removed references to enable_tx_int
 * 1999/05/28	acme		fixed nibble_to_byte, ackvc now properly treated
 *				if_send simplified
 * 1999/05/25	acme		fixed t1, t2, t21 & t23 configuration
@@ -70,11 +74,9 @@
 /* Defines & Macros */
 #define MAX_CMD_RETRY	5
 #define X25_CHAN_MTU	2048	/* unfragmented logical channel MTU */
-#define OUT_INTR	1
-#define IN_INTR		0
 
 /* Data Structures */
-/* This is an extention of the 'struct device' we create for each network
+/* This is an extention of the 'struct net_device' we create for each network
    interface to keep the rest of X.25 channel-specific data. */
 typedef struct x25_channel {
 	char name[WAN_IFNAME_SZ+1];	/* interface name, ASCIIZ */
@@ -84,7 +86,6 @@
 	s16 lcn;			/* logical channel number/conn.req.key*/
 	u8 link;
 	struct timer_list timer;	/* timer used for svc channel disc. */
-	spinlock_t lock;
 	u16 protocol;			/* ethertype, 0 - multiplexed */
 	u8 svc;				/* 0 - permanent, 1 - switched */
 	u8 state;			/* channel state */
@@ -98,19 +99,19 @@
 /* Function Prototypes */
 /* WAN link driver entry points. These are called by the WAN router module. */
 static int update (wan_device_t *wandev),
-	   new_if (wan_device_t *wandev, struct device *dev,wanif_conf_t *conf),
-	   del_if (wan_device_t *wandev, struct device *dev);
+	   new_if (wan_device_t *wandev, struct net_device *dev,wanif_conf_t *conf),
+	   del_if (wan_device_t *wandev, struct net_device *dev);
 
 /* Network device interface */
-static int if_init (struct device *dev),
-	   if_open (struct device *dev),
-	   if_close (struct device *dev),
-	   if_header (struct sk_buff *skb, struct device *dev,
+static int if_init (struct net_device *dev),
+	   if_open (struct net_device *dev),
+	   if_close (struct net_device *dev),
+	   if_header (struct sk_buff *skb, struct net_device *dev,
 		      u16 type, void *daddr, void *saddr, unsigned len),
 	   if_rebuild_hdr (struct sk_buff *skb),
-	   if_send (struct sk_buff *skb, struct device *dev);
+	   if_send (struct sk_buff *skb, struct net_device *dev);
 
-static struct net_device_stats * if_stats (struct device *dev);
+static struct net_device_stats * if_stats (struct net_device *dev);
 
 /* Interrupt handlers */
 static void cyx_isr (cycx_t *card),
@@ -132,22 +133,22 @@
 	   x25_disconnect_response (cycx_t *card, u8 link, u8 lcn);
 
 /* Miscellaneous functions */
-static int chan_connect (struct device *dev),
-	   chan_send (struct device *dev, struct sk_buff *skb);
+static int chan_connect (struct net_device *dev),
+	   chan_send (struct net_device *dev, struct sk_buff *skb);
 
-static void set_chan_state (struct device *dev, u8 state, u8 outside_intr),
+static void set_chan_state (struct net_device *dev, u8 state),
 	    nibble_to_byte (u8 *s, u8 *d, u8 len, u8 nibble),
-	    reset_timer (struct device *dev),
-	    chan_disc (struct device *dev),
-	    chan_timer (unsigned long data);
+	    reset_timer (struct net_device *dev),
+	    chan_disc (struct net_device *dev),
+	    chan_timer (unsigned long d);
 
 static u8 bps_to_speed_code (u32 bps);
 static u8 log2 (u32 n);
 
 static unsigned dec_to_uint (u8 *str, int len);
 
-static struct device *get_dev_by_lcn (wan_device_t *wandev, s16 lcn);
-static struct device *get_dev_by_dte_addr (wan_device_t *wandev, char *dte);
+static struct net_device *get_dev_by_lcn (wan_device_t *wandev, s16 lcn);
+static struct net_device *get_dev_by_dte_addr (wan_device_t *wandev, char *dte);
 
 #ifdef CYCLOMX_X25_DEBUG
 static void hex_dump(char *msg, unsigned char *p, int len);
@@ -187,8 +188,8 @@
 
 	/* Initialize protocol-specific fields */
 	card->mbox  = card->hw.dpmbase + X25_MBOX_OFFS;
-	card->u.x.critical = 0; /* critical section flag */
 	card->u.x.connection_keys = 0;
+	card->u.x.lock = SPIN_LOCK_UNLOCKED;
 
 	/* Configure adapter. Here we set resonable defaults, then parse
 	 * device configuration structure and set configuration options.
@@ -286,7 +287,6 @@
 	card->wandev.new_if	= &new_if;
 	card->wandev.del_if	= &del_if;
 	card->wandev.state	= WAN_DISCONNECTED;
-	card->wandev.enable_tx_int = card->irq_dis_if_send_count = 0;
 	return 0;
 }
 
@@ -315,7 +315,7 @@
  *
  * Return:	0	o.k.
  *		< 0	failure (channel will not be created) */
-static int new_if (wan_device_t *wandev, struct device *dev, wanif_conf_t *conf)
+static int new_if (wan_device_t *wandev, struct net_device *dev, wanif_conf_t *conf)
 {
 	cycx_t *card = wandev->private;
 	x25_channel_t *chan;
@@ -338,21 +338,23 @@
 	chan->rx_skb = NULL;
 	/* only used in svc connected thru crossover cable */
 	chan->local_addr = NULL;
-	chan->lock = SPIN_LOCK_UNLOCKED;
 
 	if (conf->addr[0] == '@') {	/* SVC */
-		int local_len = strlen(conf->local_addr);
+		int len = strlen(conf->local_addr);
 
-		if (local_len) {
-			if (local_len > WAN_ADDRESS_SZ) {
+		if (len) {
+			if (len > WAN_ADDRESS_SZ) {
 				printk(KERN_ERR "%s: %s local addr too long!\n",
 						wandev->name, chan->name);
 				kfree(chan);
 				return -EINVAL;
-			} else if ((chan->local_addr = kmalloc(local_len + 1,
-							 GFP_KERNEL)) == NULL) {
-				kfree(chan);
-				return ENOMEM;
+			} else {
+				chan->local_addr = kmalloc(len + 1, GFP_KERNEL);
+
+				if (!chan->local_addr) {
+					kfree(chan);
+					return ENOMEM;
+				}
 			}
 
                 	strncpy(chan->local_addr, conf->local_addr,
@@ -387,6 +389,7 @@
 	if (err) {
 		if (chan->local_addr)
 			kfree(chan->local_addr);
+
 		kfree(chan);
 		return err;
 	}
@@ -399,7 +402,7 @@
 }
 
 /* Delete logical channel. */
-static int del_if (wan_device_t *wandev, struct device *dev)
+static int del_if (wan_device_t *wandev, struct net_device *dev)
 {
 	if (!dev) {
 		printk(KERN_ERR "cycx_x25:del_if:dev == NULL!\n");
@@ -408,6 +411,7 @@
 
 	if (dev->priv) {
 		x25_channel_t *chan = dev->priv;
+
 		if (chan->svc) {
 			if (chan->local_addr)
 				kfree(chan->local_addr);
@@ -415,6 +419,7 @@
 			if (chan->state == WAN_CONNECTED)
 				del_timer(&chan->timer);
 		}
+
 		kfree(chan);
 		dev->priv = NULL;
 	}
@@ -428,7 +433,7 @@
  * This routine is called only once for each interface, during Linux network
  * interface registration.  Returning anything but zero will fail interface
  * registration. */
-static int if_init (struct device *dev)
+static int if_init (struct net_device *dev)
 {
 	x25_channel_t *chan = dev->priv;
 	cycx_t *card = chan->card;
@@ -464,7 +469,7 @@
 
 	/* Initialize socket buffers */
 	dev_init_buffers(dev);
-	set_chan_state(dev, WAN_DISCONNECTED, OUT_INTR);
+	set_chan_state(dev, WAN_DISCONNECTED);
 	return 0;
 }
 
@@ -473,7 +478,7 @@
  * o if link is disconnected then initiate connection
  *
  * Return 0 if O.k. or errno.  */
-static int if_open (struct device *dev)
+static int if_open (struct net_device *dev)
 {
 	x25_channel_t *chan = dev->priv;
 	cycx_t *card = chan->card;
@@ -481,37 +486,28 @@
 	if (dev->start)
 		return -EBUSY; /* only one open is allowed */ 
 
-	if (test_and_set_bit(0, (void*)&card->wandev.critical))
-		return -EAGAIN;
-
 	dev->interrupt = 0;
 	dev->tbusy = 0;
 	dev->start = 1;
 	cyclomx_open(card);
 
-	card->wandev.critical = 0;
 	return 0;
 }
 
 /* Close network interface.
  * o reset flags.
  * o if there's no more open channels then disconnect physical link. */
-static int if_close (struct device *dev)
+static int if_close (struct net_device *dev)
 {
 	x25_channel_t *chan = dev->priv;
 	cycx_t *card = chan->card;
 
-	if (test_and_set_bit(0, (void*)&card->wandev.critical))
-		return -EAGAIN;
-
 	dev->start = 0;
 
 	if (chan->state == WAN_CONNECTED || chan->state == WAN_CONNECTING)
 		chan_disc(dev);
 		
 	cyclomx_close(card);
-
-	card->wandev.critical = 0;
 	return 0;
 }
 
@@ -523,7 +519,7 @@
  * set skb->protocol to 0 and discard packet later.
  *
  * Return:	media header length. */
-static int if_header (struct sk_buff *skb, struct device *dev,
+static int if_header (struct sk_buff *skb, struct net_device *dev,
 		      u16 type, void *daddr, void *saddr, unsigned len)
 {
 	skb->protocol = type;
@@ -553,7 +549,7 @@
  *    bottom half" (with interrupts enabled).
  * 2. Setting tbusy flag will inhibit further transmit requests from the
  *    protocol stack and can be used for flow control with protocol layer. */
-static int if_send (struct sk_buff *skb, struct device *dev)
+static int if_send (struct sk_buff *skb, struct net_device *dev)
 {
 	x25_channel_t *chan = dev->priv;
 	cycx_t *card = chan->card;
@@ -563,10 +559,6 @@
 		return -EBUSY;	
 	}
 
-	dev->tbusy = 1;
-
-	reset_timer(dev);
-
 	if (!chan->svc)
 		chan->protocol = skb->protocol;
 
@@ -580,13 +572,17 @@
                 ++chan->ifstats.tx_errors;
         } else switch (chan->state) {
 		case WAN_DISCONNECTED:
-			if (chan_connect(dev))
+			if (chan_connect(dev)) {
+				dev->tbusy = 1;
 				return -EBUSY;
+			}
 			/* fall thru */
 		case WAN_CONNECTED:
+			reset_timer(dev);
 			dev->trans_start = jiffies;
+			dev->tbusy = 1;
+
 			if (chan_send(dev, skb)) {
-				dev->tbusy = 1;
 				return -EBUSY;
 			}
 			break;
@@ -601,7 +597,7 @@
 
 /* Get Ethernet-style interface statistics.
  * Return a pointer to struct net_device_stats */
-static struct net_device_stats *if_stats (struct device *dev)
+static struct net_device_stats *if_stats (struct net_device *dev)
 {
         x25_channel_t *chan = dev->priv;
 
@@ -612,25 +608,13 @@
 /* X.25 Interrupt Service Routine. */
 static void cyx_isr (cycx_t *card)
 {
-	unsigned long host_cpu_flags;
 	TX25Cmd cmd;
 	u16 z = 0;
 
 	card->in_isr = 1;
 	card->buff_int_mode_unbusy = 0;
-
-	if (test_and_set_bit(0, (void*)&card->wandev.critical)) {
- 		printk(KERN_INFO "cyx_isr: %s, wandev.critical set to 0x%02X\n",
-				 card->devname, card->wandev.critical);
-		card->in_isr = 0;
-		return;
-	}
-
-	/* For all interrupts set the critical flag to CRITICAL_RX_INTR.
-         * If the if_send routine is called with this flag set it will set
-         * the enable transmit flag to 1. (for a delayed interrupt) */
-	card->wandev.critical = CRITICAL_IN_ISR;
 	cycx_peek(&card->hw, X25_RXMBOX_OFFS, &cmd, sizeof(cmd));
+
 	switch (cmd.command) {
 		case X25_DATA_INDICATION:
 			rx_intr(card, &cmd);
@@ -668,16 +652,7 @@
 
 	cycx_poke(&card->hw, 0, &z, sizeof(z));
 	cycx_poke(&card->hw, X25_RXMBOX_OFFS, &z, sizeof(z));
- 
-	card->wandev.critical = CRITICAL_INTR_HANDLED;
-
-	if (card->wandev.enable_tx_int)
-		card->wandev.enable_tx_int = 0;
-
-	spin_lock_irqsave(&card->lock, host_cpu_flags);
 	card->in_isr = 0;
-	card->wandev.critical = 0;
-	spin_unlock_irqrestore(&card->lock, host_cpu_flags);
 
 	if (card->buff_int_mode_unbusy)
 		mark_bh(NET_BH);
@@ -688,7 +663,7 @@
  *	o Clear 'tbusy' flag */
 static void tx_intr (cycx_t *card, TX25Cmd *cmd)
 {
-	struct device *dev;
+	struct net_device *dev;
 	wan_device_t *wandev = &card->wandev;
 	u8 lcn;
 
@@ -720,7 +695,7 @@
 static void rx_intr (cycx_t *card, TX25Cmd *cmd)
 {
 	wan_device_t *wandev = &card->wandev;
-	struct device *dev;
+	struct net_device *dev;
 	x25_channel_t *chan;
 	struct sk_buff *skb;
 	u8 bitm, lcn;
@@ -740,11 +715,12 @@
 	chan = dev->priv;
 	reset_timer(dev);
 
-	if (chan->drop_sequence)
+	if (chan->drop_sequence) {
 		if (!bitm)
 			chan->drop_sequence = 0;
 		else
 			return;
+	}
 
 	if ((skb = chan->rx_skb) == NULL) {
 		/* Allocate new socket buffer */
@@ -799,29 +775,30 @@
 static void connect_intr (cycx_t *card, TX25Cmd *cmd)
 {
 	wan_device_t *wandev = &card->wandev;
-	struct device *dev = NULL;
+	struct net_device *dev = NULL;
 	x25_channel_t *chan;
-	u8 data[32],
-	   local[24],
+	u8 d[32],
+	   loc[24],
 	   rem[24];
-	u8 lcn, sizelocal, sizerem;
+	u8 lcn, sizeloc, sizerem;
 
 	cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
-	cycx_peek(&card->hw, cmd->buf + 5, &sizelocal, sizeof(sizelocal));
-	cycx_peek(&card->hw, cmd->buf + 6, data, cmd->len - 6);
+	cycx_peek(&card->hw, cmd->buf + 5, &sizeloc, sizeof(sizeloc));
+	cycx_peek(&card->hw, cmd->buf + 6, d, cmd->len - 6);
 
-	sizerem = sizelocal >> 4;
-	sizelocal &= 0x0F;
+	sizerem = sizeloc >> 4;
+	sizeloc &= 0x0F;
 
-	local[0] = rem[0] = '\0';
+	loc[0] = rem[0] = '\0';
 
-	if (sizelocal)
-		nibble_to_byte(data, local, sizelocal, 0);
+	if (sizeloc)
+		nibble_to_byte(d, loc, sizeloc, 0);
 
 	if (sizerem)
-		nibble_to_byte(data + (sizelocal >> 1), rem, sizerem, sizelocal & 1);
+		nibble_to_byte(d + (sizeloc >> 1), rem, sizerem, sizeloc & 1);
+
 	dprintk(KERN_INFO "connect_intr:lcn=%d, local=%s, remote=%s\n",
-			  lcn, local, rem);
+			  lcn, loc, rem);
 	if ((dev = get_dev_by_dte_addr(wandev, rem)) == NULL) {
 		/* Invalid channel, discard packet */
 		printk(KERN_INFO "%s: connect not expected: remote %s!\n",
@@ -832,14 +809,14 @@
 	chan = dev->priv;
 	chan->lcn = lcn;
 	x25_connect_response(card, chan);
-	set_chan_state(dev, WAN_CONNECTED, IN_INTR);
+	set_chan_state(dev, WAN_CONNECTED);
 }
 
 /* Connect confirm interrupt handler. */
 static void connect_confirm_intr (cycx_t *card, TX25Cmd *cmd)
 {
 	wan_device_t *wandev = &card->wandev;
-	struct device *dev;
+	struct net_device *dev;
 	x25_channel_t *chan;
 	u8 lcn, key;
 
@@ -858,14 +835,14 @@
 	clear_bit(--key, (void*)&card->u.x.connection_keys);
 	chan = dev->priv;
 	chan->lcn = lcn;
-	set_chan_state(dev, WAN_CONNECTED, IN_INTR);
+	set_chan_state(dev, WAN_CONNECTED);
 }
 
 /* Disonnect confirm interrupt handler. */
 static void disconnect_confirm_intr (cycx_t *card, TX25Cmd *cmd)
 {
 	wan_device_t *wandev = &card->wandev;
-	struct device *dev;
+	struct net_device *dev;
 	u8 lcn;
 
 	cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
@@ -878,22 +855,26 @@
 		return;
 	}
 
-	set_chan_state(dev, WAN_DISCONNECTED, IN_INTR);
+	set_chan_state(dev, WAN_DISCONNECTED);
 }
 
 /* disconnect interrupt handler. */
 static void disconnect_intr (cycx_t *card, TX25Cmd *cmd)
 {
 	wan_device_t *wandev = &card->wandev;
-	struct device *dev;
+	struct net_device *dev;
 	u8 lcn;
 
 	cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
 	dprintk(KERN_INFO "disconnect_intr:lcn=%d\n", lcn);
-	x25_disconnect_response(card, 0, lcn);
 
-	if ((dev = get_dev_by_lcn(wandev, lcn)) != NULL)
-		set_chan_state(dev, WAN_DISCONNECTED, IN_INTR);
+	if ((dev = get_dev_by_lcn(wandev, lcn)) != NULL) {
+		x25_channel_t *chan = dev->priv;
+
+		x25_disconnect_response(card, chan->link, lcn);
+		set_chan_state(dev, WAN_DISCONNECTED);
+	} else
+		x25_disconnect_response(card, 0, lcn);
 }
 
 /* LOG interrupt handler. */
@@ -960,55 +941,51 @@
 	printk(KERN_INFO "%s: %s\n", msg, hex);
 }
 #endif
-/* CYCLOM X Firmware-Specific Functions
- *
- * Almost all X.25 commands can unexpetedly fail due to so called 'X.25
- * asynchronous events' such as restart, interrupt, incoming call request,
- * call clear request, etc.  They can't be ignored and have to be dealt with
- * immediately.  To tackle with this problem we execute each interface command
- * in a loop until good return code is received or maximum number of retries
- * is reached.  Each interface command returns non-zero return code, an
- * asynchronous event/error handler x25_error() is called.
- */
+/* CYCLOM X Firmware-Specific Functions */
 /* Exec x25 command. */
 static int x25_exec (cycx_t *card, int command, int link,
-		     void *data1, int len1, void *data2, int len2)
+		     void *d1, int len1, void *d2, int len2)
 {
 	TX25Cmd c;
+	unsigned long flags;
 	u32 addr = 0x1200 + 0x2E0 * link + 0x1E2;
+	u8 retry = MAX_CMD_RETRY;
 	int err = 0;
 
 	c.command = command;
 	c.link = link;
 	c.len = len1 + len2;
 
-	if (test_and_set_bit(0, (void*)&card->u.x.critical))
-		return -EAGAIN;
+	spin_lock_irqsave(&card->u.x.lock, flags);
 
 	/* write command */
 	cycx_poke(&card->hw, X25_MBOX_OFFS, &c, sizeof(c) - sizeof(c.buf));
 
 	/* write x25 data */
-	if (data1) {
-		cycx_poke(&card->hw, addr, data1, len1);
+	if (d1) {
+		cycx_poke(&card->hw, addr, d1, len1);
 
-		if (data2)
+		if (d2) {
 			if (len2 > 254) {
 				u32 addr1 = 0xA00 + 0x400 * link;
 
-				cycx_poke(&card->hw, addr + len1, data2, 249);
-				cycx_poke(&card->hw, addr1, ((u8*) data2) + 249,
+				cycx_poke(&card->hw, addr + len1, d2, 249);
+				cycx_poke(&card->hw, addr1, ((u8*) d2) + 249,
 					  len2 - 249);
 			} else
-				cycx_poke(&card->hw, addr + len1, data2, len2);
+				cycx_poke(&card->hw, addr + len1, d2, len2);
+		}
 	}
 
 	/* generate interruption, executing command */
 	cycx_intr(&card->hw);
 
 	/* wait till card->mbox == 0 */
-	err = cycx_exec(card->mbox);
-	card->u.x.critical = 0;
+	do {
+		err = cycx_exec(card->mbox);
+	} while (retry-- && err);
+
+	spin_unlock_irqrestore(&card->u.x.lock, flags);
 
 	return err;
 }
@@ -1110,6 +1087,7 @@
 
 	while (len) {
 		*d++ = '0' + (*s >> 4);
+
 		if (--len) {
 			*d++ = '0' + (*s & 0x0F);
 			--len;
@@ -1125,9 +1103,8 @@
 static int x25_place_call (cycx_t *card, x25_channel_t *chan)
 {
 	int err = 0,
-  	    retry = MAX_CMD_RETRY,
 	    len;
-	char data[64],
+	char d[64],
 	     nibble = 0,
 	     mylen = chan->local_addr ? strlen(chan->local_addr) : 0,
 	     remotelen = strlen(chan->addr);
@@ -1143,24 +1120,24 @@
 	set_bit(key, (void*)&card->u.x.connection_keys);
 	++key;
 	dprintk(KERN_INFO "%s:x25_place_call:key=%d\n", card->devname, key);
-	memset(data, 0, sizeof(data));
-	data[1] = key; /* user key */
-	data[2] = 0x10;
-	data[4] = 0x0B;
-
-	len = byte_to_nibble(chan->addr, data + 6, &nibble);
-	len += chan->local_addr ? byte_to_nibble(chan->local_addr,
-						 data + 6 + len, &nibble) : 0;
+	memset(d, 0, sizeof(d));
+	d[1] = key; /* user key */
+	d[2] = 0x10;
+	d[4] = 0x0B;
+
+	len = byte_to_nibble(chan->addr, d + 6, &nibble);
+
+	if (chan->local_addr)
+		len += byte_to_nibble(chan->local_addr, d + 6 + len, &nibble);
+
 	if (nibble)
 		++len;
-	data[5] = mylen << 4 | remotelen;
-	data[6 + len + 1] = 0xCC; /* TCP/IP over X.25, thanx to Daniela :) */
-	
-	do err = x25_exec(card, X25_CONNECT_REQUEST, chan->link,
-			  &data, 7 + len + 1, NULL, 0);
-	while (err && retry--);
 
-        if (err)
+	d[5] = mylen << 4 | remotelen;
+	d[6 + len + 1] = 0xCC; /* TCP/IP over X.25, thanx to Daniela :) */
+	
+	if ((err = x25_exec(card, X25_CONNECT_REQUEST, chan->link,
+			    &d, 7 + len + 1, NULL, 0)) != 0)
 		clear_bit(--key, (void*)&card->u.x.connection_keys);
 	else {
                 chan->lcn = -key;
@@ -1173,82 +1150,60 @@
 /* Place X.25 CONNECT RESPONSE. */
 static int x25_connect_response (cycx_t *card, x25_channel_t *chan)
 {
-	int err = 0,
-  	    retry = MAX_CMD_RETRY;
-	char data[32];
+	u8 d[8];
 
-	memset(data, 0, sizeof(data));
-	data[0] = data[3] = chan->lcn;
-	data[2] = 0x10;
-	data[4] = 0x0F;
-	data[7] = 0xCC; /* TCP/IP over X.25, thanx Daniela */
-
-	do err = x25_exec(card, X25_CONNECT_RESPONSE, chan->link,
-			  &data, 8, NULL, 0);
-	while (err && retry--);
+	memset(d, 0, sizeof(d));
+	d[0] = d[3] = chan->lcn;
+	d[2] = 0x10;
+	d[4] = 0x0F;
+	d[7] = 0xCC; /* TCP/IP over X.25, thanx Daniela */
 
-        return err;
+	return x25_exec(card, X25_CONNECT_RESPONSE, chan->link, &d, 8, NULL, 0);
 }
 
 /* Place X.25 DISCONNECT RESPONSE.  */
 static int x25_disconnect_response (cycx_t *card, u8 link, u8 lcn)
 {
-	int err = 0,
-  	    retry = MAX_CMD_RETRY;
-	char data[5];
+	char d[5];
 
-	memset(data, 0, sizeof(data));
-	data[0] = data[3] = lcn;
-	data[2] = 0x10;
-	data[4] = 0x17;
-	do err = x25_exec(card, X25_DISCONNECT_RESPONSE, link,
-			  &data, 5, NULL, 0);
-	while (err && retry--);
-
-        return err;
+	memset(d, 0, sizeof(d));
+	d[0] = d[3] = lcn;
+	d[2] = 0x10;
+	d[4] = 0x17;
+	return x25_exec(card, X25_DISCONNECT_RESPONSE, link, &d, 5, NULL, 0);
 }
 
 /* Clear X.25 call.  */
 static int x25_clear_call (cycx_t *card, u8 link, u8 lcn, u8 cause, u8 diagn)
 {
-        int retry = MAX_CMD_RETRY,
-            err;
-	u8 data[7];
-
-	memset(data, 0, sizeof(data));
-	data[0] = data[3] = lcn;
-	data[2] = 0x10;
-	data[4] = 0x13;
-	data[5] = cause;
-	data[6] = diagn;
+	u8 d[7];
 
-	do err = x25_exec(card, X25_DISCONNECT_REQUEST, link, data, 7, NULL, 0);
-	while (err && retry--);
+	memset(d, 0, sizeof(d));
+	d[0] = d[3] = lcn;
+	d[2] = 0x10;
+	d[4] = 0x13;
+	d[5] = cause;
+	d[6] = diagn;
 
-        return err;
+	return x25_exec(card, X25_DISCONNECT_REQUEST, link, d, 7, NULL, 0);
 }
 
 /* Send X.25 data packet. */
 static int x25_send (cycx_t *card, u8 link, u8 lcn, u8 bitm, int len, void *buf)
 {
-	int err = 0,
-  	    retry = MAX_CMD_RETRY;
-	u8 data[] = "?\xFF\x10??"; 
-
-	data[0] = data[3] = lcn;
-	data[4] = bitm;
+	u8 d[] = "?\xFF\x10??"; 
 
-	do err = x25_exec(card, X25_DATA_REQUEST, link, &data, 5, buf, len);
-	while (err && retry--);
+	d[0] = d[3] = lcn;
+	d[4] = bitm;
 
-	return err;
+	return x25_exec(card, X25_DATA_REQUEST, link, &d, 5, buf, len);
 }
 
 /* Miscellaneous */
 /* Find network device by its channel number.  */
-static struct device *get_dev_by_lcn (wan_device_t *wandev, s16 lcn)
+static struct net_device *get_dev_by_lcn (wan_device_t *wandev, s16 lcn)
 {
-	struct device *dev = wandev->dev;
+	struct net_device *dev = wandev->dev;
 
 	for (; dev; dev = dev->slave)
 		if (((x25_channel_t*)dev->priv)->lcn == lcn)
@@ -1257,9 +1212,9 @@
 }
 
 /* Find network device by its remote dte address. */
-static struct device *get_dev_by_dte_addr (wan_device_t *wandev, char *dte)
+static struct net_device *get_dev_by_dte_addr (wan_device_t *wandev, char *dte)
 {
-	struct device *dev = wandev->dev;
+	struct net_device *dev = wandev->dev;
 
 	for (; dev; dev = dev->slave)
 		if (!strcmp (((x25_channel_t*)dev->priv)->addr, dte))
@@ -1274,7 +1229,7 @@
  * Return:	0	connected
  *		>0	connection in progress
  *		<0	failure */
-static int chan_connect (struct device *dev)
+static int chan_connect (struct net_device *dev)
 {
 	x25_channel_t *chan = dev->priv;
 	cycx_t *card = chan->card;
@@ -1286,31 +1241,31 @@
 				  card->devname, chan->addr);
                 if (x25_place_call(card, chan))
 			return -EIO;
-                set_chan_state(dev, WAN_CONNECTING, OUT_INTR);
+                set_chan_state(dev, WAN_CONNECTING);
                 return 1;
         } else 
-		set_chan_state(dev, WAN_CONNECTED, OUT_INTR);
+		set_chan_state(dev, WAN_CONNECTED);
 
 	return 0;
 }
 
 /* Disconnect logical channel.
  * o if SVC then clear X.25 call */
-static void chan_disc (struct device *dev)
+static void chan_disc (struct net_device *dev)
 {
 	x25_channel_t *chan = dev->priv;
 
 	if (chan->svc) {
 		x25_clear_call(chan->card, chan->link, chan->lcn, 0, 0);
-		set_chan_state(dev, WAN_DISCONNECTING, OUT_INTR);
+		set_chan_state(dev, WAN_DISCONNECTING);
 	} else
-		set_chan_state(dev, WAN_DISCONNECTED, OUT_INTR);
+		set_chan_state(dev, WAN_DISCONNECTED);
 }
 
 /* Called by kernel timer */
-static void chan_timer (unsigned long data)
+static void chan_timer (unsigned long d)
 {
-	struct device *dev = (struct device*) data;
+	struct net_device *dev = (struct net_device*) d;
 	x25_channel_t *chan = dev->priv;
 	
 	switch (chan->state) {
@@ -1325,16 +1280,13 @@
 }
 
 /* Set logical channel state. */
-static void set_chan_state (struct device *dev, u8 state, u8 outside_intr)
+static void set_chan_state (struct net_device *dev, u8 state)
 {
 	x25_channel_t *chan = dev->priv;
 	cycx_t *card = chan->card;
 	u32 flags = 0;
 
-	if (outside_intr)
-		spin_lock(&card->lock);
-	else
-		spin_lock_irqsave(&card->lock, flags);
+	spin_lock_irqsave(&card->lock, flags);
 
 	if (chan->state != state) {
 		if (chan->svc && chan->state == WAN_CONNECTED)
@@ -1370,16 +1322,14 @@
 					*(unsigned short*)dev->dev_addr = 0;
 					chan->lcn = 0;
                                 }
+				dev->tbusy = 0;
 				break;
 		}
 
 		chan->state = state;
 	}
 
-	if (outside_intr)
-		spin_unlock(&card->lock);
-	else
-		spin_unlock_irqrestore(&card->lock, flags);
+	spin_unlock_irqrestore(&card->lock, flags);
 }
 
 /* Send packet on a logical channel.
@@ -1395,7 +1345,7 @@
  *    the packet into 'complete sequence' using M-bit.
  * 2. When transmission is complete, an event notification should be issued
  *    to the router.  */
-static int chan_send (struct device *dev, struct sk_buff *skb)
+static int chan_send (struct net_device *dev, struct sk_buff *skb)
 {
 	x25_channel_t *chan = dev->priv;
 	cycx_t *card = chan->card;
@@ -1468,7 +1418,7 @@
 	return val;
 }
 
-static void reset_timer(struct device *dev)
+static void reset_timer(struct net_device *dev)
 {
 	x25_channel_t *chan = dev->priv;
 
@@ -1520,7 +1470,7 @@
 
 static void x25_dump_devs(wan_device_t *wandev)
 {
-	struct device *dev = wandev->dev;
+	struct net_device *dev = wandev->dev;
 
 	printk (KERN_INFO "x25 dev states\n");
 	printk (KERN_INFO "name: addr:           tbusy:\n");
diff -u --recursive --new-file v2.3.13/linux/drivers/net/daynaport.c linux/drivers/net/daynaport.c
--- v2.3.13/linux/drivers/net/daynaport.c	Thu Dec 17 09:04:49 1998
+++ linux/drivers/net/daynaport.c	Wed Aug 18 11:36:41 1999
@@ -37,33 +37,33 @@
 #include <linux/etherdevice.h>
 #include "8390.h"
 
-int ns8390_probe1(struct device *dev, int word16, char *name, int id, int prom);
+int ns8390_probe1(struct net_device *dev, int word16, char *name, int id, int prom);
 
-static int ns8390_open(struct device *dev);
-static void ns8390_no_reset(struct device *dev);
-static int ns8390_close_card(struct device *dev);
+static int ns8390_open(struct net_device *dev);
+static void ns8390_no_reset(struct net_device *dev);
+static int ns8390_close_card(struct net_device *dev);
 
-static void interlan_reset(struct device *dev);
+static void interlan_reset(struct net_device *dev);
 
-static void dayna_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
+static void dayna_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
 						int ring_page);
-static void dayna_block_input(struct device *dev, int count,
+static void dayna_block_input(struct net_device *dev, int count,
 						  struct sk_buff *skb, int ring_offset);
-static void dayna_block_output(struct device *dev, int count,
+static void dayna_block_output(struct net_device *dev, int count,
 						   const unsigned char *buf, const int start_page);
 
-static void sane_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
+static void sane_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
 						int ring_page);
-static void sane_block_input(struct device *dev, int count,
+static void sane_block_input(struct net_device *dev, int count,
 						  struct sk_buff *skb, int ring_offset);
-static void sane_block_output(struct device *dev, int count,
+static void sane_block_output(struct net_device *dev, int count,
 						   const unsigned char *buf, const int start_page);
 
-static void slow_sane_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
+static void slow_sane_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
 						int ring_page);
-static void slow_sane_block_input(struct device *dev, int count,
+static void slow_sane_block_input(struct net_device *dev, int count,
 						  struct sk_buff *skb, int ring_offset);
-static void slow_sane_block_output(struct device *dev, int count,
+static void slow_sane_block_output(struct net_device *dev, int count,
 						   const unsigned char *buf, const int start_page);
 
 
@@ -199,7 +199,7 @@
 
 int ns8390_probe(struct nubus_device_specifier *d, int slot, struct nubus_type *match)
 {
-	struct device *dev;
+	struct net_device *dev;
 	volatile unsigned short *i;
 	volatile unsigned char *p;
 	int plen;
@@ -336,7 +336,7 @@
 	return -ENODEV;
 }
 
-int ns8390_probe1(struct device *dev, int word16, char *model_name, int type, int promoff)
+int ns8390_probe1(struct net_device *dev, int word16, char *model_name, int type, int promoff)
 {
 	static unsigned version_printed = 0;
 
@@ -469,14 +469,14 @@
 	return 0;
 }
 
-static int ns8390_open(struct device *dev)
+static int ns8390_open(struct net_device *dev)
 {
 	ei_open(dev);
 	MOD_INC_USE_COUNT;
 	return 0;
 }
 
-static void ns8390_no_reset(struct device *dev)
+static void ns8390_no_reset(struct net_device *dev)
 {
 	if (ei_debug > 1) 
 		printk("Need to reset the NS8390 t=%lu...", jiffies);
@@ -485,7 +485,7 @@
 	return;
 }
 
-static int ns8390_close_card(struct device *dev)
+static int ns8390_close_card(struct net_device *dev)
 {
 	if (ei_debug > 1)
 		printk("%s: Shutting down ethercard.\n", dev->name);
@@ -504,7 +504,7 @@
  *    Interlan Specific Code Starts Here
  */
 
-static void interlan_reset(struct device *dev)
+static void interlan_reset(struct net_device *dev)
 {
 	unsigned char *target=nubus_slot_addr(dev->irq);
 	if (ei_debug > 1) 
@@ -531,7 +531,7 @@
    The only complications are that the ring buffer wraps.
 */
 
-static void dayna_cpu_memcpy(struct device *dev, void *to, int from, int count)
+static void dayna_cpu_memcpy(struct net_device *dev, void *to, int from, int count)
 {
 	volatile unsigned short *ptr;
 	unsigned short *target=to;
@@ -554,7 +554,7 @@
 	}
 }
 
-static void cpu_dayna_memcpy(struct device *dev, int to, const void *from, int count)
+static void cpu_dayna_memcpy(struct net_device *dev, int to, const void *from, int count)
 {
 	volatile unsigned short *ptr;
 	const unsigned short *src=from;
@@ -577,7 +577,7 @@
 	}
 }
 
-static void dayna_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+static void dayna_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 {
 	unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
 	dayna_cpu_memcpy(dev, (void *)hdr, hdr_start, 4);
@@ -585,7 +585,7 @@
 	hdr->count=(hdr->count&0xFF)<<8|(hdr->count>>8);
 }
 
-static void dayna_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
+static void dayna_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
 {
 	unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
 	unsigned long xfer_start = xfer_base+dev->mem_start;
@@ -610,7 +610,7 @@
 	}
 }
 
-static void dayna_block_output(struct device *dev, int count, const unsigned char *buf,
+static void dayna_block_output(struct net_device *dev, int count, const unsigned char *buf,
 				int start_page)
 {
 	long shmem = (start_page - WD_START_PG)<<8;
@@ -623,7 +623,7 @@
  */
 
 
-static void sane_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+static void sane_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 {
 	unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
 	memcpy((void *)hdr, (char *)dev->mem_start+hdr_start, 4);
@@ -631,7 +631,7 @@
 	hdr->count=(hdr->count&0xFF)<<8|(hdr->count>>8);
 }
 
-static void sane_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
+static void sane_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
 {
 	unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
 	unsigned long xfer_start = xfer_base+dev->mem_start;
@@ -652,7 +652,7 @@
 }
 
 
-static void sane_block_output(struct device *dev, int count, const unsigned char *buf,
+static void sane_block_output(struct net_device *dev, int count, const unsigned char *buf,
 				int start_page)
 {
 	long shmem = (start_page - WD_START_PG)<<8;
@@ -684,7 +684,7 @@
 		*to++=*from++;
 }
 
-static void slow_sane_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+static void slow_sane_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 {
 	unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
 	word_memcpy_fromcard((void *)hdr, (char *)dev->mem_start+hdr_start, 4);
@@ -692,7 +692,7 @@
 	hdr->count=(hdr->count&0xFF)<<8|(hdr->count>>8);
 }
 
-static void slow_sane_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
+static void slow_sane_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
 {
 	unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
 	unsigned long xfer_start = xfer_base+dev->mem_start;
@@ -712,7 +712,7 @@
 	}
 }
 
-static void slow_sane_block_output(struct device *dev, int count, const unsigned char *buf,
+static void slow_sane_block_output(struct net_device *dev, int count, const unsigned char *buf,
 				int start_page)
 {
 	long shmem = (start_page - WD_START_PG)<<8;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/de4x5.c linux/drivers/net/de4x5.c
--- v2.3.13/linux/drivers/net/de4x5.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/de4x5.c	Wed Aug 18 11:36:41 1999
@@ -826,7 +826,7 @@
 	struct sk_buff *skb;                /* Save the (re-ordered) skb's  */
     } cache;
     struct de4x5_srom srom;                 /* A copy of the SROM           */
-    struct device *next_module;             /* Link to the next module      */
+    struct net_device *next_module;             /* Link to the next module      */
     int rx_ovf;                             /* Check for 'RX overflow' tag  */
     int useSROM;                            /* For non-DEC card use SROM    */
     int useMII;                             /* Infoblock using the MII      */
@@ -839,7 +839,7 @@
     int infoleaf_offset;                    /* SROM infoleaf for controller */
     s32 infoblock_csr6;                     /* csr6 value in SROM infoblock */
     int infoblock_media;                    /* infoblock media              */
-    int (*infoleaf_fn)(struct device *);    /* Pointer to infoleaf function */
+    int (*infoleaf_fn)(struct net_device *);    /* Pointer to infoleaf function */
     u_char *rst;                            /* Pointer to Type 5 reset info */
     u_char  ibn;                            /* Infoblock number             */
     struct parameters params;               /* Command line/ #defined params */
@@ -895,63 +895,63 @@
 /*
 ** Public Functions
 */
-static int     de4x5_open(struct device *dev);
-static int     de4x5_queue_pkt(struct sk_buff *skb, struct device *dev);
+static int     de4x5_open(struct net_device *dev);
+static int     de4x5_queue_pkt(struct sk_buff *skb, struct net_device *dev);
 static void    de4x5_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static int     de4x5_close(struct device *dev);
-static struct  net_device_stats *de4x5_get_stats(struct device *dev);
-static void    de4x5_local_stats(struct device *dev, char *buf, int pkt_len);
-static void    set_multicast_list(struct device *dev);
-static int     de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd);
+static int     de4x5_close(struct net_device *dev);
+static struct  net_device_stats *de4x5_get_stats(struct net_device *dev);
+static void    de4x5_local_stats(struct net_device *dev, char *buf, int pkt_len);
+static void    set_multicast_list(struct net_device *dev);
+static int     de4x5_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 
 /*
 ** Private functions
 */
-static int     de4x5_hw_init(struct device *dev, u_long iobase);
-static int     de4x5_init(struct device *dev);
-static int     de4x5_sw_reset(struct device *dev);
-static int     de4x5_rx(struct device *dev);
-static int     de4x5_tx(struct device *dev);
-static int     de4x5_ast(struct device *dev);
-static int     de4x5_txur(struct device *dev);
-static int     de4x5_rx_ovfc(struct device *dev);
+static int     de4x5_hw_init(struct net_device *dev, u_long iobase);
+static int     de4x5_init(struct net_device *dev);
+static int     de4x5_sw_reset(struct net_device *dev);
+static int     de4x5_rx(struct net_device *dev);
+static int     de4x5_tx(struct net_device *dev);
+static int     de4x5_ast(struct net_device *dev);
+static int     de4x5_txur(struct net_device *dev);
+static int     de4x5_rx_ovfc(struct net_device *dev);
 
-static int     autoconf_media(struct device *dev);
-static void    create_packet(struct device *dev, char *frame, int len);
+static int     autoconf_media(struct net_device *dev);
+static void    create_packet(struct net_device *dev, char *frame, int len);
 static void    de4x5_us_delay(u32 usec);
 static void    de4x5_ms_delay(u32 msec);
-static void    load_packet(struct device *dev, char *buf, u32 flags, struct sk_buff *skb);
-static int     dc21040_autoconf(struct device *dev);
-static int     dc21041_autoconf(struct device *dev);
-static int     dc21140m_autoconf(struct device *dev);
-static int     dc2114x_autoconf(struct device *dev);
-static int     srom_autoconf(struct device *dev);
-static int     de4x5_suspect_state(struct device *dev, int timeout, int prev_state, int (*fn)(struct device *, int), int (*asfn)(struct device *));
-static int     dc21040_state(struct device *dev, int csr13, int csr14, int csr15, int timeout, int next_state, int suspect_state, int (*fn)(struct device *, int));
-static int     test_media(struct device *dev, s32 irqs, s32 irq_mask, s32 csr13, s32 csr14, s32 csr15, s32 msec);
-static int     test_for_100Mb(struct device *dev, int msec);
-static int     wait_for_link(struct device *dev);
-static int     test_mii_reg(struct device *dev, int reg, int mask, int pol, long msec);
-static int     is_spd_100(struct device *dev);
-static int     is_100_up(struct device *dev);
-static int     is_10_up(struct device *dev);
-static int     is_anc_capable(struct device *dev);
-static int     ping_media(struct device *dev, int msec);
-static struct sk_buff *de4x5_alloc_rx_buff(struct device *dev, int index, int len);
-static void    de4x5_free_rx_buffs(struct device *dev);
-static void    de4x5_free_tx_buffs(struct device *dev);
-static void    de4x5_save_skbs(struct device *dev);
-static void    de4x5_rst_desc_ring(struct device *dev);
-static void    de4x5_cache_state(struct device *dev, int flag);
-static void    de4x5_put_cache(struct device *dev, struct sk_buff *skb);
-static void    de4x5_putb_cache(struct device *dev, struct sk_buff *skb);
-static struct  sk_buff *de4x5_get_cache(struct device *dev);
-static void    de4x5_setup_intr(struct device *dev);
-static void    de4x5_init_connection(struct device *dev);
-static int     de4x5_reset_phy(struct device *dev);
-static void    reset_init_sia(struct device *dev, s32 sicr, s32 strr, s32 sigr);
-static int     test_ans(struct device *dev, s32 irqs, s32 irq_mask, s32 msec);
-static int     test_tp(struct device *dev, s32 msec);
+static void    load_packet(struct net_device *dev, char *buf, u32 flags, struct sk_buff *skb);
+static int     dc21040_autoconf(struct net_device *dev);
+static int     dc21041_autoconf(struct net_device *dev);
+static int     dc21140m_autoconf(struct net_device *dev);
+static int     dc2114x_autoconf(struct net_device *dev);
+static int     srom_autoconf(struct net_device *dev);
+static int     de4x5_suspect_state(struct net_device *dev, int timeout, int prev_state, int (*fn)(struct net_device *, int), int (*asfn)(struct net_device *));
+static int     dc21040_state(struct net_device *dev, int csr13, int csr14, int csr15, int timeout, int next_state, int suspect_state, int (*fn)(struct net_device *, int));
+static int     test_media(struct net_device *dev, s32 irqs, s32 irq_mask, s32 csr13, s32 csr14, s32 csr15, s32 msec);
+static int     test_for_100Mb(struct net_device *dev, int msec);
+static int     wait_for_link(struct net_device *dev);
+static int     test_mii_reg(struct net_device *dev, int reg, int mask, int pol, long msec);
+static int     is_spd_100(struct net_device *dev);
+static int     is_100_up(struct net_device *dev);
+static int     is_10_up(struct net_device *dev);
+static int     is_anc_capable(struct net_device *dev);
+static int     ping_media(struct net_device *dev, int msec);
+static struct sk_buff *de4x5_alloc_rx_buff(struct net_device *dev, int index, int len);
+static void    de4x5_free_rx_buffs(struct net_device *dev);
+static void    de4x5_free_tx_buffs(struct net_device *dev);
+static void    de4x5_save_skbs(struct net_device *dev);
+static void    de4x5_rst_desc_ring(struct net_device *dev);
+static void    de4x5_cache_state(struct net_device *dev, int flag);
+static void    de4x5_put_cache(struct net_device *dev, struct sk_buff *skb);
+static void    de4x5_putb_cache(struct net_device *dev, struct sk_buff *skb);
+static struct  sk_buff *de4x5_get_cache(struct net_device *dev);
+static void    de4x5_setup_intr(struct net_device *dev);
+static void    de4x5_init_connection(struct net_device *dev);
+static int     de4x5_reset_phy(struct net_device *dev);
+static void    reset_init_sia(struct net_device *dev, s32 sicr, s32 strr, s32 sigr);
+static int     test_ans(struct net_device *dev, s32 irqs, s32 irq_mask, s32 msec);
+static int     test_tp(struct net_device *dev, s32 msec);
 static int     EISA_signature(char *name, s32 eisa_id);
 static int     PCI_signature(char *name, struct bus_type *lp);
 static void    DevicePresent(u_long iobase);
@@ -965,10 +965,10 @@
 /*static void    srom_busy(u_int command, u_long address);*/
 static void    sendto_srom(u_int command, u_long addr);
 static int     getfrom_srom(u_long addr);
-static int     srom_map_media(struct device *dev);
-static int     srom_infoleaf_info(struct device *dev);
-static void    srom_init(struct device *dev);
-static void    srom_exec(struct device *dev, u_char *p);
+static int     srom_map_media(struct net_device *dev);
+static int     srom_infoleaf_info(struct net_device *dev);
+static void    srom_init(struct net_device *dev);
+static void    srom_exec(struct net_device *dev, u_char *p);
 static int     mii_rd(u_char phyreg, u_char phyaddr, u_long ioaddr);
 static void    mii_wr(int data, u_char phyreg, u_char phyaddr, u_long ioaddr);
 static int     mii_rdata(u_long ioaddr);
@@ -979,51 +979,51 @@
 static void    sendto_mii(u32 command, int data, u_long ioaddr);
 static int     getfrom_mii(u32 command, u_long ioaddr);
 static int     mii_get_oui(u_char phyaddr, u_long ioaddr);
-static int     mii_get_phy(struct device *dev);
-static void    SetMulticastFilter(struct device *dev);
-static int     get_hw_addr(struct device *dev);
-static void    srom_repair(struct device *dev, int card);
-static int     test_bad_enet(struct device *dev, int status);
+static int     mii_get_phy(struct net_device *dev);
+static void    SetMulticastFilter(struct net_device *dev);
+static int     get_hw_addr(struct net_device *dev);
+static void    srom_repair(struct net_device *dev, int card);
+static int     test_bad_enet(struct net_device *dev, int status);
 static int     an_exception(struct bus_type *lp);
 #if !defined(__sparc_v9__) && !defined(__powerpc__) && !defined(__alpha__)
-static void    eisa_probe(struct device *dev, u_long iobase);
+static void    eisa_probe(struct net_device *dev, u_long iobase);
 #endif
-static void    pci_probe(struct device *dev, u_long iobase);
+static void    pci_probe(struct net_device *dev, u_long iobase);
 static void    srom_search(struct pci_dev *pdev);
-static char    *build_setup_frame(struct device *dev, int mode);
-static void    disable_ast(struct device *dev);
-static void    enable_ast(struct device *dev, u32 time_out);
-static long    de4x5_switch_mac_port(struct device *dev);
-static int     gep_rd(struct device *dev);
-static void    gep_wr(s32 data, struct device *dev);
-static void    timeout(struct device *dev, void (*fn)(u_long data), u_long data, u_long msec);
-static void    yawn(struct device *dev, int state);
-static void    link_modules(struct device *dev, struct device *tmp);
-static void    de4x5_parse_params(struct device *dev);
-static void    de4x5_dbg_open(struct device *dev);
-static void    de4x5_dbg_mii(struct device *dev, int k);
-static void    de4x5_dbg_media(struct device *dev);
+static char    *build_setup_frame(struct net_device *dev, int mode);
+static void    disable_ast(struct net_device *dev);
+static void    enable_ast(struct net_device *dev, u32 time_out);
+static long    de4x5_switch_mac_port(struct net_device *dev);
+static int     gep_rd(struct net_device *dev);
+static void    gep_wr(s32 data, struct net_device *dev);
+static void    timeout(struct net_device *dev, void (*fn)(u_long data), u_long data, u_long msec);
+static void    yawn(struct net_device *dev, int state);
+static void    link_modules(struct net_device *dev, struct net_device *tmp);
+static void    de4x5_parse_params(struct net_device *dev);
+static void    de4x5_dbg_open(struct net_device *dev);
+static void    de4x5_dbg_mii(struct net_device *dev, int k);
+static void    de4x5_dbg_media(struct net_device *dev);
 static void    de4x5_dbg_srom(struct de4x5_srom *p);
 static void    de4x5_dbg_rx(struct sk_buff *skb, int len);
 static int     de4x5_strncmp(char *a, char *b, int n);
-static int     dc21041_infoleaf(struct device *dev);
-static int     dc21140_infoleaf(struct device *dev);
-static int     dc21142_infoleaf(struct device *dev);
-static int     dc21143_infoleaf(struct device *dev);
-static int     type0_infoblock(struct device *dev, u_char count, u_char *p);
-static int     type1_infoblock(struct device *dev, u_char count, u_char *p);
-static int     type2_infoblock(struct device *dev, u_char count, u_char *p);
-static int     type3_infoblock(struct device *dev, u_char count, u_char *p);
-static int     type4_infoblock(struct device *dev, u_char count, u_char *p);
-static int     type5_infoblock(struct device *dev, u_char count, u_char *p);
-static int     compact_infoblock(struct device *dev, u_char count, u_char *p);
+static int     dc21041_infoleaf(struct net_device *dev);
+static int     dc21140_infoleaf(struct net_device *dev);
+static int     dc21142_infoleaf(struct net_device *dev);
+static int     dc21143_infoleaf(struct net_device *dev);
+static int     type0_infoblock(struct net_device *dev, u_char count, u_char *p);
+static int     type1_infoblock(struct net_device *dev, u_char count, u_char *p);
+static int     type2_infoblock(struct net_device *dev, u_char count, u_char *p);
+static int     type3_infoblock(struct net_device *dev, u_char count, u_char *p);
+static int     type4_infoblock(struct net_device *dev, u_char count, u_char *p);
+static int     type5_infoblock(struct net_device *dev, u_char count, u_char *p);
+static int     compact_infoblock(struct net_device *dev, u_char count, u_char *p);
 
 #ifdef MODULE
 int  init_module(void);
 void cleanup_module(void);
-static struct  device *unlink_modules(struct device *p);
-static struct  device *insert_device(struct device *dev, u_long iobase,
-				     int (*init)(struct device *));
+static struct net_device *unlink_modules(struct net_device *p);
+static struct net_device *insert_device(struct net_device *dev, u_long iobase,
+				     int (*init)(struct net_device *));
 static int count_adapters(void);
 static int loading_module = 1;
 MODULE_PARM(de4x5_debug, "i");
@@ -1046,7 +1046,7 @@
 static int num_de4x5s = 0;
 static int cfrv = 0, useSROM = 0;
 static int lastPCI = -1;
-static struct device *lastModule = NULL;
+static struct net_device *lastModule = NULL;
 static struct pci_dev *pdev = NULL;
 
 /*
@@ -1054,7 +1054,7 @@
 */
 struct InfoLeaf {
     int chipset;
-    int (*fn)(struct device *);
+    int (*fn)(struct net_device *);
 };
 static struct InfoLeaf infoleaf_array[] = {
     {DC21041, dc21041_infoleaf},
@@ -1067,7 +1067,7 @@
 /*
 ** List the SROM info block functions
 */
-static int (*dc_infoblock[])(struct device *dev, u_char, u_char *) = {
+static int (*dc_infoblock[])(struct net_device *dev, u_char, u_char *) = {
     type0_infoblock,
     type1_infoblock,
     type2_infoblock,
@@ -1107,7 +1107,7 @@
 ** more info.
 */
 int __init 
-de4x5_probe(struct device *dev)
+de4x5_probe(struct net_device *dev)
 {
     u_long iobase = dev->base_addr;
 
@@ -1122,7 +1122,7 @@
 }
 
 static int __init 
-de4x5_hw_init(struct device *dev, u_long iobase)
+de4x5_hw_init(struct net_device *dev, u_long iobase)
 {
     struct bus_type *lp = &bus;
     int i, status=0;
@@ -1339,7 +1339,7 @@
 
 
 static int
-de4x5_open(struct device *dev)
+de4x5_open(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -1419,7 +1419,7 @@
 ** ttcp source).
 */
 static int
-de4x5_init(struct device *dev)
+de4x5_init(struct net_device *dev)
 {  
     /* Lock out other processes whilst setting up the hardware */
     test_and_set_bit(0, (void *)&dev->tbusy);
@@ -1433,7 +1433,7 @@
 }
 
 static int
-de4x5_sw_reset(struct device *dev)
+de4x5_sw_reset(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -1510,7 +1510,7 @@
 ** Writes a socket buffer address to the next available transmit descriptor.
 */
 static int
-de4x5_queue_pkt(struct sk_buff *skb, struct device *dev)
+de4x5_queue_pkt(struct sk_buff *skb, struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -1590,7 +1590,7 @@
 static void
 de4x5_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-    struct device *dev = (struct device *)dev_id;
+    struct net_device *dev = (struct net_device *)dev_id;
     struct de4x5_private *lp;
     s32 imr, omr, sts, limit;
     u_long iobase;
@@ -1654,7 +1654,7 @@
 }
 
 static int
-de4x5_rx(struct device *dev)
+de4x5_rx(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -1733,7 +1733,7 @@
 ** Buffer sent - check for TX buffer errors.
 */
 static int
-de4x5_tx(struct device *dev)
+de4x5_tx(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -1784,7 +1784,7 @@
 }
 
 static int
-de4x5_ast(struct device *dev)
+de4x5_ast(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     int next_tick = DE4X5_AUTOSENSE_MS;
@@ -1807,7 +1807,7 @@
 }
 
 static int
-de4x5_txur(struct device *dev)
+de4x5_txur(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -1830,7 +1830,7 @@
 }
 
 static int 
-de4x5_rx_ovfc(struct device *dev)
+de4x5_rx_ovfc(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -1851,7 +1851,7 @@
 }
 
 static int
-de4x5_close(struct device *dev)
+de4x5_close(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -1889,7 +1889,7 @@
 }
 
 static struct net_device_stats *
-de4x5_get_stats(struct device *dev)
+de4x5_get_stats(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -1900,7 +1900,7 @@
 }
 
 static void
-de4x5_local_stats(struct device *dev, char *buf, int pkt_len)
+de4x5_local_stats(struct net_device *dev, char *buf, int pkt_len)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     int i;
@@ -1939,7 +1939,7 @@
 ** the descriptor register is read only to the hardware.
 */
 static void
-load_packet(struct device *dev, char *buf, u32 flags, struct sk_buff *skb)
+load_packet(struct net_device *dev, char *buf, u32 flags, struct sk_buff *skb)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     int entry = (lp->tx_new ? lp->tx_new-1 : lp->txRingSize-1);
@@ -1961,7 +1961,7 @@
 ** Set or clear the multicast filter for this adaptor.
 */
 static void
-set_multicast_list(struct device *dev)
+set_multicast_list(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -1993,7 +1993,7 @@
 ** Little endian crc one liner from Matt Thomas, DEC.
 */
 static void
-SetMulticastFilter(struct device *dev)
+SetMulticastFilter(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     struct dev_mc_list *dmi=dev->mc_list;
@@ -2055,7 +2055,7 @@
 ** the motherboard. Upto 15 EISA devices are supported.
 */
 static void __init 
-eisa_probe(struct device *dev, u_long ioaddr)
+eisa_probe(struct net_device *dev, u_long ioaddr)
 {
     int i, maxSlots, status, device;
     u_char irq;
@@ -2137,7 +2137,7 @@
 #define PCI_LAST_DEV  32
 
 static void __init 
-pci_probe(struct device *dev, u_long ioaddr)
+pci_probe(struct net_device *dev, u_long ioaddr)
 {
     u_char pb, pbus, dev_num, dnum, timer;
     u_short vendor, index, status;
@@ -2308,9 +2308,9 @@
 }
 
 static void __init 
-link_modules(struct device *dev, struct device *tmp)
+link_modules(struct net_device *dev, struct net_device *tmp)
 {
-    struct device *p=dev;
+    struct net_device *p=dev;
 
     if (p) {
 	while (((struct de4x5_private *)(p->priv))->next_module) {
@@ -2335,7 +2335,7 @@
 ** sneaky and changed the port on us.
 */
 static int
-autoconf_media(struct device *dev)
+autoconf_media(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -2376,7 +2376,7 @@
 ** timeouts don't effectively duplicate packets on the network.
 */
 static int
-dc21040_autoconf(struct device *dev)
+dc21040_autoconf(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -2447,9 +2447,9 @@
 }
 
 static int
-dc21040_state(struct device *dev, int csr13, int csr14, int csr15, int timeout,
+dc21040_state(struct net_device *dev, int csr13, int csr14, int csr15, int timeout,
 	      int next_state, int suspect_state, 
-	      int (*fn)(struct device *, int))
+	      int (*fn)(struct net_device *, int))
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     int next_tick = DE4X5_AUTOSENSE_MS;
@@ -2486,9 +2486,9 @@
 }
 
 static int
-de4x5_suspect_state(struct device *dev, int timeout, int prev_state,
-		      int (*fn)(struct device *, int),
-		      int (*asfn)(struct device *))
+de4x5_suspect_state(struct net_device *dev, int timeout, int prev_state,
+		      int (*fn)(struct net_device *, int),
+		      int (*asfn)(struct net_device *))
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     int next_tick = DE4X5_AUTOSENSE_MS;
@@ -2530,7 +2530,7 @@
 ** when the media is found.
 */
 static int
-dc21041_autoconf(struct device *dev)
+dc21041_autoconf(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -2732,7 +2732,7 @@
 ** register, except at the first power up negotiation.
 */
 static int
-dc21140m_autoconf(struct device *dev)
+dc21140m_autoconf(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     int ana, anlpa, cap, cr, slnk, sr;
@@ -2916,7 +2916,7 @@
 ** Only _10Mb and _100Mb are tested here.
 */
 static int
-dc2114x_autoconf(struct device *dev)
+dc2114x_autoconf(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -3167,7 +3167,7 @@
 }
 
 static int
-srom_autoconf(struct device *dev)
+srom_autoconf(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
 
@@ -3180,7 +3180,7 @@
 ** The early return avoids a media state / SROM media space clash.
 */
 static int
-srom_map_media(struct device *dev)
+srom_map_media(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
 
@@ -3244,7 +3244,7 @@
 }
 
 static void
-de4x5_init_connection(struct device *dev)
+de4x5_init_connection(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -3273,7 +3273,7 @@
 ** on the signal pin use. Do a double reset to ensure a reset.
 */
 static int
-de4x5_reset_phy(struct device *dev)
+de4x5_reset_phy(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -3307,7 +3307,7 @@
 }
 
 static int
-test_media(struct device *dev, s32 irqs, s32 irq_mask, s32 csr13, s32 csr14, s32 csr15, s32 msec)
+test_media(struct net_device *dev, s32 irqs, s32 irq_mask, s32 csr13, s32 csr14, s32 csr15, s32 msec)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -3345,7 +3345,7 @@
 }
 
 static int
-test_tp(struct device *dev, s32 msec)
+test_tp(struct net_device *dev, s32 msec)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -3374,7 +3374,7 @@
 #define SAMPLE_INTERVAL 500  /* ms */
 #define SAMPLE_DELAY    2000 /* ms */
 static int
-test_for_100Mb(struct device *dev, int msec)
+test_for_100Mb(struct net_device *dev, int msec)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     int gep = 0, ret = ((lp->chipset & ~0x00ff)==DC2114x? -1 :GEP_SLNK);
@@ -3405,7 +3405,7 @@
 }
 
 static int
-wait_for_link(struct device *dev)
+wait_for_link(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
 
@@ -3427,7 +3427,7 @@
 **
 */
 static int
-test_mii_reg(struct device *dev, int reg, int mask, int pol, long msec)
+test_mii_reg(struct net_device *dev, int reg, int mask, int pol, long msec)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     int test;
@@ -3451,7 +3451,7 @@
 }
 
 static int
-is_spd_100(struct device *dev)
+is_spd_100(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -3475,7 +3475,7 @@
 }
 
 static int
-is_100_up(struct device *dev)
+is_100_up(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -3496,7 +3496,7 @@
 }
 
 static int
-is_10_up(struct device *dev)
+is_10_up(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -3519,7 +3519,7 @@
 }
 
 static int
-is_anc_capable(struct device *dev)
+is_anc_capable(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -3538,7 +3538,7 @@
 ** media is bad or unconnected.
 */
 static int
-ping_media(struct device *dev, int msec)
+ping_media(struct net_device *dev, int msec)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -3579,7 +3579,7 @@
 ** into which the packet is copied.
 */
 static struct sk_buff *
-de4x5_alloc_rx_buff(struct device *dev, int index, int len)
+de4x5_alloc_rx_buff(struct net_device *dev, int index, int len)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     struct sk_buff *p;
@@ -3630,7 +3630,7 @@
 }
 
 static void
-de4x5_free_rx_buffs(struct device *dev)
+de4x5_free_rx_buffs(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     int i;
@@ -3647,7 +3647,7 @@
 }
 
 static void
-de4x5_free_tx_buffs(struct device *dev)
+de4x5_free_tx_buffs(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     int i;
@@ -3676,7 +3676,7 @@
 ** packet meaningful.
 */
 static void
-de4x5_save_skbs(struct device *dev)
+de4x5_save_skbs(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -3697,7 +3697,7 @@
 }
 
 static void
-de4x5_rst_desc_ring(struct device *dev)
+de4x5_rst_desc_ring(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -3729,7 +3729,7 @@
 }
 
 static void
-de4x5_cache_state(struct device *dev, int flag)
+de4x5_cache_state(struct net_device *dev, int flag)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -3759,7 +3759,7 @@
 }
 
 static void
-de4x5_put_cache(struct device *dev, struct sk_buff *skb)
+de4x5_put_cache(struct net_device *dev, struct sk_buff *skb)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     struct sk_buff *p;
@@ -3776,7 +3776,7 @@
 }
 
 static void
-de4x5_putb_cache(struct device *dev, struct sk_buff *skb)
+de4x5_putb_cache(struct net_device *dev, struct sk_buff *skb)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     struct sk_buff *p = lp->cache.skb;
@@ -3788,7 +3788,7 @@
 }
 
 static struct sk_buff *
-de4x5_get_cache(struct device *dev)
+de4x5_get_cache(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     struct sk_buff *p = lp->cache.skb;
@@ -3806,7 +3806,7 @@
 ** is received and the auto-negotiation status is NWAY OK.
 */
 static int
-test_ans(struct device *dev, s32 irqs, s32 irq_mask, s32 msec)
+test_ans(struct net_device *dev, s32 irqs, s32 irq_mask, s32 msec)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -3834,7 +3834,7 @@
 }
 
 static void
-de4x5_setup_intr(struct device *dev)
+de4x5_setup_intr(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -3855,7 +3855,7 @@
 **
 */
 static void
-reset_init_sia(struct device *dev, s32 csr13, s32 csr14, s32 csr15)
+reset_init_sia(struct net_device *dev, s32 csr13, s32 csr14, s32 csr15)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -3889,7 +3889,7 @@
 ** Create a loopback ethernet packet
 */
 static void
-create_packet(struct device *dev, char *frame, int len)
+create_packet(struct net_device *dev, char *frame, int len)
 {
     int i;
     char *buf = frame;
@@ -4098,7 +4098,7 @@
 ** as the first three are invariant - assigned to an organisation.
 */
 static int
-get_hw_addr(struct device *dev)
+get_hw_addr(struct net_device *dev)
 {
     u_long iobase = dev->base_addr;
     int broken, i, k, tmp, status = 0;
@@ -4212,7 +4212,7 @@
 }
 
 static void
-srom_repair(struct device *dev, int card)
+srom_repair(struct net_device *dev, int card)
 {
     struct bus_type *lp = &bus;
 
@@ -4233,7 +4233,7 @@
 ** to be true so far (2 for 2).
 */
 static int
-test_bad_enet(struct device *dev, int status)
+test_bad_enet(struct net_device *dev, int status)
 {
     struct bus_type *lp = &bus;
     int i, tmp;
@@ -4387,7 +4387,7 @@
 }
 
 static int
-srom_infoleaf_info(struct device *dev)
+srom_infoleaf_info(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     int i, count;
@@ -4435,7 +4435,7 @@
 ** will follow the discovery process from MII address 1-31 then 0.
 */
 static void
-srom_init(struct device *dev)
+srom_init(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_char *p = (u_char *)&lp->srom + lp->infoleaf_offset;
@@ -4480,7 +4480,7 @@
 ** to the GEP register (21140) or csr15 GEP portion (2114[23]).
 */
 static void
-srom_exec(struct device *dev, u_char *p)
+srom_exec(struct net_device *dev, u_char *p)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -4511,13 +4511,13 @@
 ** since the existing code will be satisfactory for all boards.
 */
 static int 
-dc21041_infoleaf(struct device *dev)
+dc21041_infoleaf(struct net_device *dev)
 {
     return DE4X5_AUTOSENSE_MS;
 }
 
 static int 
-dc21140_infoleaf(struct device *dev)
+dc21140_infoleaf(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_char count = 0;
@@ -4555,7 +4555,7 @@
 }
 
 static int 
-dc21142_infoleaf(struct device *dev)
+dc21142_infoleaf(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_char count = 0;
@@ -4590,7 +4590,7 @@
 }
 
 static int 
-dc21143_infoleaf(struct device *dev)
+dc21143_infoleaf(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_char count = 0;
@@ -4628,7 +4628,7 @@
 ** we'll reuse the dc21140m_autoconf function. Non MII media only.
 */
 static int 
-compact_infoblock(struct device *dev, u_char count, u_char *p)
+compact_infoblock(struct net_device *dev, u_char count, u_char *p)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_char flags, csr6;
@@ -4668,7 +4668,7 @@
 ** This block describes non MII media for the DC21140[A] only.
 */
 static int 
-type0_infoblock(struct device *dev, u_char count, u_char *p)
+type0_infoblock(struct net_device *dev, u_char count, u_char *p)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_char flags, csr6, len = (*p & BLOCK_LEN)+1;
@@ -4708,7 +4708,7 @@
 /* These functions are under construction! */
 
 static int 
-type1_infoblock(struct device *dev, u_char count, u_char *p)
+type1_infoblock(struct net_device *dev, u_char count, u_char *p)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_char len = (*p & BLOCK_LEN)+1;
@@ -4747,7 +4747,7 @@
 }
 
 static int 
-type2_infoblock(struct device *dev, u_char count, u_char *p)
+type2_infoblock(struct net_device *dev, u_char count, u_char *p)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_char len = (*p & BLOCK_LEN)+1;
@@ -4788,7 +4788,7 @@
 }
 
 static int 
-type3_infoblock(struct device *dev, u_char count, u_char *p)
+type3_infoblock(struct net_device *dev, u_char count, u_char *p)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_char len = (*p & BLOCK_LEN)+1;
@@ -4829,7 +4829,7 @@
 }
 
 static int 
-type4_infoblock(struct device *dev, u_char count, u_char *p)
+type4_infoblock(struct net_device *dev, u_char count, u_char *p)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_char flags, csr6, len = (*p & BLOCK_LEN)+1;
@@ -4874,7 +4874,7 @@
 ** (chips) through the General Purpose Register.
 */
 static int 
-type5_infoblock(struct device *dev, u_char count, u_char *p)
+type5_infoblock(struct net_device *dev, u_char count, u_char *p)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_char len = (*p & BLOCK_LEN)+1;
@@ -5074,7 +5074,7 @@
 ** The SROM spec forces us to search addresses [1-31 0]. Bummer.
 */
 static int
-mii_get_phy(struct device *dev)
+mii_get_phy(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -5138,7 +5138,7 @@
 }
 
 static char *
-build_setup_frame(struct device *dev, int mode)
+build_setup_frame(struct net_device *dev, int mode)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     int i;
@@ -5170,7 +5170,7 @@
 }
 
 static void
-enable_ast(struct device *dev, u32 time_out)
+enable_ast(struct net_device *dev, u32 time_out)
 {
     timeout(dev, (void *)&de4x5_ast, (u_long)dev, time_out);
     
@@ -5178,7 +5178,7 @@
 }
 
 static void
-disable_ast(struct device *dev)
+disable_ast(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     
@@ -5188,7 +5188,7 @@
 }
 
 static long
-de4x5_switch_mac_port(struct device *dev)
+de4x5_switch_mac_port(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -5224,7 +5224,7 @@
 }
 
 static void
-gep_wr(s32 data, struct device *dev)
+gep_wr(s32 data, struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -5239,7 +5239,7 @@
 }
 
 static int
-gep_rd(struct device *dev)
+gep_rd(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -5254,7 +5254,7 @@
 }
 
 static void
-timeout(struct device *dev, void (*fn)(u_long data), u_long data, u_long msec)
+timeout(struct net_device *dev, void (*fn)(u_long data), u_long data, u_long msec)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     int dt;
@@ -5276,7 +5276,7 @@
 }
 
 static void
-yawn(struct device *dev, int state)
+yawn(struct net_device *dev, int state)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -5324,7 +5324,7 @@
 }
 
 static void
-de4x5_parse_params(struct device *dev)
+de4x5_parse_params(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     char *p, *q, t;
@@ -5370,7 +5370,7 @@
 }
 
 static void
-de4x5_dbg_open(struct device *dev)
+de4x5_dbg_open(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     int i;
@@ -5421,7 +5421,7 @@
 }
 
 static void
-de4x5_dbg_mii(struct device *dev, int k)
+de4x5_dbg_mii(struct net_device *dev, int k)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     u_long iobase = dev->base_addr;
@@ -5449,7 +5449,7 @@
 }
 
 static void
-de4x5_dbg_media(struct device *dev)
+de4x5_dbg_media(struct net_device *dev)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     
@@ -5542,7 +5542,7 @@
 ** this function is only used for my testing.
 */
 static int
-de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd)
+de4x5_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     struct de4x5_ioctl *ioc = (struct de4x5_ioctl *) &rq->ifr_data;
@@ -5751,7 +5751,7 @@
 ** to "do the right thing".
 */
 #define LP(a) ((struct de4x5_private *)(a))
-static struct device *mdev = NULL;
+static struct net_device *mdev = NULL;
 static int io=0x0;/* EDIT THIS LINE FOR YOUR CONFIGURATION IF NEEDED        */
 MODULE_PARM(io, "i");
 
@@ -5759,7 +5759,7 @@
 init_module(void)
 {
     int i, num, status = -EIO;
-    struct device *p;
+    struct net_device *p;
 
     num = count_adapters();
 
@@ -5802,10 +5802,10 @@
     return;
 }
 
-static struct device *
-unlink_modules(struct device *p)
+static struct net_device *
+unlink_modules(struct net_device *p)
 {
-    struct device *next = NULL;
+    struct net_device *next = NULL;
 
     if (p->priv) {                          /* Private areas allocated?  */
 	struct de4x5_private *lp = (struct de4x5_private *)p->priv;
@@ -5856,17 +5856,17 @@
 ** If at end of eth device list and can't use current entry, malloc
 ** one up. If memory could not be allocated, print an error message.
 */
-static struct device * __init 
-insert_device(struct device *dev, u_long iobase, int (*init)(struct device *))
+static struct net_device * __init 
+insert_device(struct net_device *dev, u_long iobase, int (*init)(struct net_device *))
 {
-    struct device *new;
+    struct net_device *new;
 
-    new = (struct device *)kmalloc(sizeof(struct device)+8, GFP_KERNEL);
+    new = (struct net_device *)kmalloc(sizeof(struct net_device)+8, GFP_KERNEL);
     if (new == NULL) {
 	printk("de4x5.c: Device not initialised, insufficient memory\n");
 	return NULL;
     } else {
-	memset((char *)new, 0, sizeof(struct device)+8);
+	memset((char *)new, 0, sizeof(struct net_device)+8);
 	new->name = (char *)(new + 1);
 	new->base_addr = iobase;       /* assign the io address */
 	new->init = init;              /* initialisation routine */
diff -u --recursive --new-file v2.3.13/linux/drivers/net/de600.c linux/drivers/net/de600.c
--- v2.3.13/linux/drivers/net/de600.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/de600.c	Wed Aug 18 11:36:41 1999
@@ -243,24 +243,24 @@
  * Index to functions, as function prototypes.
  */
 /* Routines used internally. (See "convenience macros") */
-static byte	de600_read_status(struct device *dev);
-static byte	de600_read_byte(unsigned char type, struct device *dev);
+static byte	de600_read_status(struct net_device *dev);
+static byte	de600_read_byte(unsigned char type, struct net_device *dev);
 
 /* Put in the device structure. */
-static int	de600_open(struct device *dev);
-static int	de600_close(struct device *dev);
-static struct net_device_stats *get_stats(struct device *dev);
-static int	de600_start_xmit(struct sk_buff *skb, struct device *dev);
+static int	de600_open(struct net_device *dev);
+static int	de600_close(struct net_device *dev);
+static struct net_device_stats *get_stats(struct net_device *dev);
+static int	de600_start_xmit(struct sk_buff *skb, struct net_device *dev);
 
 /* Dispatch from interrupts. */
 static void	de600_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static int	de600_tx_intr(struct device *dev, int irq_status);
-static void	de600_rx_intr(struct device *dev);
+static int	de600_tx_intr(struct net_device *dev, int irq_status);
+static void	de600_rx_intr(struct net_device *dev);
 
 /* Initialization */
-static void	trigger_interrupt(struct device *dev);
-int		de600_probe(struct device *dev);
-static int	adapter_init(struct device *dev);
+static void	trigger_interrupt(struct net_device *dev);
+int		de600_probe(struct net_device *dev);
+static int	adapter_init(struct net_device *dev);
 
 /*
  * D-Link driver variables:
@@ -310,7 +310,7 @@
 #define tx_page_adr(a) (((a) + 1) * MEM_2K)
 
 static inline byte
-de600_read_status(struct device *dev)
+de600_read_status(struct net_device *dev)
 {
 	byte status;
 
@@ -322,7 +322,7 @@
 }
 
 static inline byte
-de600_read_byte(unsigned char type, struct device *dev) { /* dev used by macros */
+de600_read_byte(unsigned char type, struct net_device *dev) { /* dev used by macros */
 	byte lo;
 
 	(void)outb_p((type), DATA_PORT);
@@ -340,7 +340,7 @@
  * there is a non-reboot way to recover if something goes wrong.
  */
 static int
-de600_open(struct device *dev)
+de600_open(struct net_device *dev)
 {
 	if (request_irq(DE600_IRQ, de600_interrupt, 0, "de600", dev)) {
 		printk ("%s: unable to get IRQ %d\n", dev->name, DE600_IRQ);
@@ -360,7 +360,7 @@
  * The inverse routine to de600_open().
  */
 static int
-de600_close(struct device *dev)
+de600_close(struct net_device *dev)
 {
 	select_nic();
 	rx_page = 0;
@@ -378,13 +378,13 @@
 }
 
 static struct net_device_stats *
-get_stats(struct device *dev)
+get_stats(struct net_device *dev)
 {
     return (struct net_device_stats *)(dev->priv);
 }
 
 static inline void
-trigger_interrupt(struct device *dev)
+trigger_interrupt(struct net_device *dev)
 {
 	de600_put_command(FLIP_IRQ);
 	select_prn();
@@ -398,7 +398,7 @@
  * Start sending.
  */
 static int
-de600_start_xmit(struct sk_buff *skb, struct device *dev)
+de600_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	int	transmit_from;
 	int	len;
@@ -483,7 +483,7 @@
 static void
 de600_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
-	struct device	*dev = dev_id;
+	struct net_device	*dev = dev_id;
 	byte		irq_status;
 	int		retrig = 0;
 	int		boguscount = 0;
@@ -532,7 +532,7 @@
 }
 
 static int
-de600_tx_intr(struct device *dev, int irq_status)
+de600_tx_intr(struct net_device *dev, int irq_status)
 {
 	/*
 	 * Returns 1 if tx still not done
@@ -568,7 +568,7 @@
  * We have a good packet, get it out of the adapter.
  */
 static void
-de600_rx_intr(struct device *dev)
+de600_rx_intr(struct net_device *dev)
 {
 	struct sk_buff	*skb;
 	int		i;
@@ -628,7 +628,7 @@
 }
 
 int __init 
-de600_probe(struct device *dev)
+de600_probe(struct net_device *dev)
 {
 	int	i;
 	static struct net_device_stats de600_netstats;
@@ -707,7 +707,7 @@
 }
 
 static int
-adapter_init(struct device *dev)
+adapter_init(struct net_device *dev)
 {
 	int	i;
 	long flags;
@@ -818,7 +818,7 @@
 
 #ifdef MODULE
 static char nullname[8];
-static struct device de600_dev = {
+static struct net_device de600_dev = {
 	nullname, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, de600_probe };
 
 int
diff -u --recursive --new-file v2.3.13/linux/drivers/net/de620.c linux/drivers/net/de620.c
--- v2.3.13/linux/drivers/net/de620.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/de620.c	Wed Aug 18 11:36:41 1999
@@ -209,20 +209,20 @@
  */
 
 /* Put in the device structure. */
-static int	de620_open(struct device *);
-static int	de620_close(struct device *);
-static struct	net_device_stats *get_stats(struct device *);
-static void	de620_set_multicast_list(struct device *);
-static int	de620_start_xmit(struct sk_buff *, struct device *);
+static int	de620_open(struct net_device *);
+static int	de620_close(struct net_device *);
+static struct	net_device_stats *get_stats(struct net_device *);
+static void	de620_set_multicast_list(struct net_device *);
+static int	de620_start_xmit(struct sk_buff *, struct net_device *);
 
 /* Dispatch from interrupts. */
 static void	de620_interrupt(int, void *, struct pt_regs *);
-static int	de620_rx_intr(struct device *);
+static int	de620_rx_intr(struct net_device *);
 
 /* Initialization */
-static int	adapter_init(struct device *);
-int		de620_probe(struct device *);
-static int	read_eeprom(struct device *);
+static int	adapter_init(struct net_device *);
+int		de620_probe(struct net_device *);
+static int	read_eeprom(struct net_device *);
 
 
 /*
@@ -260,7 +260,7 @@
 static int tot_cnt;
 #endif
 static inline byte
-de620_ready(struct device *dev)
+de620_ready(struct net_device *dev)
 {
 	byte value;
 	register short int cnt = 0;
@@ -275,7 +275,7 @@
 }
 
 static inline void
-de620_send_command(struct device *dev, byte cmd)
+de620_send_command(struct net_device *dev, byte cmd)
 {
 	de620_ready(dev);
 	if (cmd == W_DUMMY)
@@ -289,7 +289,7 @@
 }
 
 static inline void
-de620_put_byte(struct device *dev, byte value)
+de620_put_byte(struct net_device *dev, byte value)
 {
 	/* The de620_ready() makes 7 loops, on the average, on a DX2/66 */
 	de620_ready(dev);
@@ -298,7 +298,7 @@
 }
 
 static inline byte
-de620_read_byte(struct device *dev)
+de620_read_byte(struct net_device *dev)
 {
 	byte value;
 
@@ -310,7 +310,7 @@
 }
 
 static inline void
-de620_write_block(struct device *dev, byte *buffer, int count)
+de620_write_block(struct net_device *dev, byte *buffer, int count)
 {
 #ifndef LOWSPEED
 	byte uflip = NIC_Cmd ^ (DS0 | DS1);
@@ -346,7 +346,7 @@
 }
 
 static inline void
-de620_read_block(struct device *dev, byte *data, int count)
+de620_read_block(struct net_device *dev, byte *data, int count)
 {
 #ifndef LOWSPEED
 	byte value;
@@ -381,7 +381,7 @@
 }
 
 static inline void
-de620_set_delay(struct device *dev)
+de620_set_delay(struct net_device *dev)
 {
 	de620_ready(dev);
 	outb(W_DFR, DATA_PORT);
@@ -405,7 +405,7 @@
 }
 
 static inline void
-de620_set_register(struct device *dev, byte reg, byte value)
+de620_set_register(struct net_device *dev, byte reg, byte value)
 {
 	de620_ready(dev);
 	outb(reg, DATA_PORT);
@@ -415,7 +415,7 @@
 }
 
 static inline byte
-de620_get_register(struct device *dev, byte reg)
+de620_get_register(struct net_device *dev, byte reg)
 {
 	byte value;
 
@@ -436,7 +436,7 @@
  *
  */
 static int
-de620_open(struct device *dev)
+de620_open(struct net_device *dev)
 {
 	if (request_irq(dev->irq, de620_interrupt, 0, "de620", dev)) {
 		printk ("%s: unable to get IRQ %d\n", dev->name, dev->irq);
@@ -457,7 +457,7 @@
  *
  */
 static int
-de620_close(struct device *dev)
+de620_close(struct net_device *dev)
 {
 	/* disable recv */
 	de620_set_register(dev, W_TCR, RXOFF);
@@ -474,7 +474,7 @@
  * Return current statistics
  *
  */
-static struct net_device_stats *get_stats(struct device *dev)
+static struct net_device_stats *get_stats(struct net_device *dev)
 {
 	return (struct net_device_stats *)(dev->priv);
 }
@@ -486,7 +486,7 @@
  *
  */
 
-static void de620_set_multicast_list(struct device *dev)
+static void de620_set_multicast_list(struct net_device *dev)
 {
 	if (dev->mc_count || dev->flags&(IFF_ALLMULTI|IFF_PROMISC))
 	{ /* Enable promiscuous mode */
@@ -511,7 +511,7 @@
  * Start sending.
  */
 static int
-de620_start_xmit(struct sk_buff *skb, struct device *dev)
+de620_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	unsigned long flags;
 	int len;
@@ -592,7 +592,7 @@
 static void
 de620_interrupt(int irq_in, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	byte irq_status;
 	int bogus_count = 0;
 	int again = 0;
@@ -634,7 +634,7 @@
  *
  */
 static int
-de620_rx_intr(struct device *dev)
+de620_rx_intr(struct net_device *dev)
 {
 	struct header_buf {
 		byte		status;
@@ -733,7 +733,7 @@
  *
  */
 static int
-adapter_init(struct device *dev)
+adapter_init(struct net_device *dev)
 {
 	int i;
 	static int was_down = 0;
@@ -821,7 +821,7 @@
  * Check if there is a DE-620 connected
  */
 int __init 
-de620_probe(struct device *dev)
+de620_probe(struct net_device *dev)
 {
 	static struct net_device_stats de620_netstats;
 	int i;
@@ -914,7 +914,7 @@
 #define sendit(dev,data) de620_set_register(dev, W_EIP, data | EIPRegister);
 
 static unsigned short __init 
-ReadAWord(struct device *dev, int from)
+ReadAWord(struct net_device *dev, int from)
 {
 	unsigned short data;
 	int nbits;
@@ -957,7 +957,7 @@
 }
 
 static int __init 
-read_eeprom(struct device *dev)
+read_eeprom(struct net_device *dev)
 {
 	unsigned short wrd;
 
@@ -1000,7 +1000,7 @@
  */
 #ifdef MODULE
 static char nullname[8] = "";
-static struct device de620_dev = {
+static struct net_device de620_dev = {
 	nullname, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, de620_probe };
 
 int
diff -u --recursive --new-file v2.3.13/linux/drivers/net/declance.c linux/drivers/net/declance.c
--- v2.3.13/linux/drivers/net/declance.c	Wed Jun 30 13:38:20 1999
+++ linux/drivers/net/declance.c	Wed Aug 18 11:36:41 1999
@@ -262,7 +262,7 @@
 
 	unsigned short busmaster_regval;
 
-	struct device *dev;	/* Backpointer        */
+	struct net_device *dev;	/* Backpointer        */
 	struct lance_private *next_module;
 
 	/* Pointers to the ring buffers as seen from the CPU */
@@ -441,7 +441,7 @@
 
 /* Setup the Lance Rx and Tx rings */
 /* Sets dev->tbusy */
-static void lance_init_ring(struct device *dev)
+static void lance_init_ring(struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_init_block *ib;
@@ -544,7 +544,7 @@
 	return 0;
 }
 
-static int lance_rx(struct device *dev)
+static int lance_rx(struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_init_block *ib;
@@ -626,7 +626,7 @@
 	return 0;
 }
 
-static int lance_tx(struct device *dev)
+static int lance_tx(struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_init_block *ib;
@@ -703,7 +703,7 @@
 
 static void lance_interrupt(const int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev = (struct device *) dev_id;
+	struct net_device *dev = (struct net_device *) dev_id;
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_regs *ll = lp->ll;
 	int csr0;
@@ -765,9 +765,9 @@
 	dev->interrupt = 0;
 }
 
-struct device *last_dev = 0;
+struct net_device *last_dev = 0;
 
-static int lance_open(struct device *dev)
+static int lance_open(struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_regs *ll = lp->ll;
@@ -801,7 +801,7 @@
 	return status;
 }
 
-static int lance_close(struct device *dev)
+static int lance_close(struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_regs *ll = lp->ll;
@@ -820,7 +820,7 @@
 	return 0;
 }
 
-static inline int lance_reset(struct device *dev)
+static inline int lance_reset(struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_regs *ll = lp->ll;
@@ -843,7 +843,7 @@
 	return status;
 }
 
-static int lance_start_xmit(struct sk_buff *skb, struct device *dev)
+static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_regs *ll = lp->ll;
@@ -912,14 +912,14 @@
 	return status;
 }
 
-static struct net_device_stats *lance_get_stats(struct device *dev)
+static struct net_device_stats *lance_get_stats(struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 
 	return &lp->stats;
 }
 
-static void lance_load_multicast(struct device *dev)
+static void lance_load_multicast(struct net_device *dev)
 {
 	volatile struct lance_init_block *ib = (struct lance_init_block *) (dev->mem_start);
 	volatile u16 *mcast_table = (u16 *) & ib->filter;
@@ -970,7 +970,7 @@
 	return;
 }
 
-static void lance_set_multicast(struct device *dev)
+static void lance_set_multicast(struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_init_block *ib;
@@ -1000,7 +1000,7 @@
 	dev->tbusy = 0;
 }
 
-__initfunc(static int dec_lance_init(struct device *dev, const int type))
+__initfunc(static int dec_lance_init(struct net_device *dev, const int type))
 {
 	static unsigned version_printed = 0;
 	struct lance_private *lp;
@@ -1194,7 +1194,7 @@
 
 
 /* Find all the lance cards on the system and initialize them */
-__initfunc(int dec_lance_probe(struct device *dev))
+__initfunc(int dec_lance_probe(struct net_device *dev))
 {
 	static int called = 0;
 
diff -u --recursive --new-file v2.3.13/linux/drivers/net/defxx.c linux/drivers/net/defxx.c
--- v2.3.13/linux/drivers/net/defxx.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/defxx.c	Wed Aug 18 11:36:41 1999
@@ -236,29 +236,29 @@
 
 /* Define global routines */
 
-int	dfx_probe(struct device *dev);
+int	dfx_probe(struct net_device *dev);
 
 /* Define module-wide (static) routines */
 
-static struct	device *dfx_alloc_device(struct device *dev, u16 iobase);
+static struct net_device *dfx_alloc_device(struct net_device *dev, u16 iobase);
 
-static void		dfx_bus_init(struct device *dev);
+static void		dfx_bus_init(struct net_device *dev);
 static void		dfx_bus_config_check(DFX_board_t *bp);
 
-static int		dfx_driver_init(struct device *dev);
+static int		dfx_driver_init(struct net_device *dev);
 static int		dfx_adap_init(DFX_board_t *bp);
 
-static int		dfx_open(struct device *dev);
-static int		dfx_close(struct device *dev);
+static int		dfx_open(struct net_device *dev);
+static int		dfx_close(struct net_device *dev);
 
 static void		dfx_int_pr_halt_id(DFX_board_t *bp);
 static void		dfx_int_type_0_process(DFX_board_t *bp);
 static void		dfx_int_common(DFX_board_t *bp);
 static void		dfx_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 
-static struct		net_device_stats *dfx_ctl_get_stats(struct device *dev);
-static void		dfx_ctl_set_multicast_list(struct device *dev);
-static int		dfx_ctl_set_mac_address(struct device *dev, void *addr);
+static struct		net_device_stats *dfx_ctl_get_stats(struct net_device *dev);
+static void		dfx_ctl_set_multicast_list(struct net_device *dev);
+static int		dfx_ctl_set_mac_address(struct net_device *dev, void *addr);
 static int		dfx_ctl_update_cam(DFX_board_t *bp);
 static int		dfx_ctl_update_filters(DFX_board_t *bp);
 
@@ -271,7 +271,7 @@
 static void		dfx_rcv_init(DFX_board_t *bp);
 static void		dfx_rcv_queue_process(DFX_board_t *bp);
 
-static int		dfx_xmt_queue_pkt(struct sk_buff *skb, struct device *dev);
+static int		dfx_xmt_queue_pkt(struct sk_buff *skb, struct net_device *dev);
 static void		dfx_xmt_done(DFX_board_t *bp);
 static void		dfx_xmt_flush(DFX_board_t *bp);
 
@@ -446,7 +446,7 @@
  *   the device structure.
  */
 
-int __init dfx_probe(struct device *dev)
+int __init dfx_probe(struct net_device *dev)
 {
 	int				i;				/* used in for loops */
 	int				version_disp;	/* was version info string already displayed? */
@@ -638,9 +638,9 @@
  *   None
  */
 
-struct device __init *dfx_alloc_device( struct device *dev, u16 iobase)
+struct net_device __init *dfx_alloc_device( struct net_device *dev, u16 iobase)
 {
-	struct device *tmp_dev;		/* pointer to a device structure */
+	struct net_device *tmp_dev;		/* pointer to a device structure */
 
 	DBG_printk("In dfx_alloc_device...\n");
 
@@ -729,7 +729,7 @@
  *   enabled yet.
  */
 
-void __init dfx_bus_init(struct device *dev)
+void __init dfx_bus_init(struct net_device *dev)
 {
 	DFX_board_t *bp = (DFX_board_t *)dev->priv;
 	u8			val;	/* used for I/O read/writes */
@@ -962,7 +962,7 @@
  *   returning from this routine.
  */
 
-int __init dfx_driver_init(struct device *dev)
+int __init dfx_driver_init(struct net_device *dev)
 {
 	DFX_board_t *bp = (DFX_board_t *)dev->priv;
 	int			alloc_size;			/* total buffer size needed */
@@ -1370,7 +1370,7 @@
  */
 
 int dfx_open(
-	struct device *dev
+	struct net_device *dev
 	)
 
 	{
@@ -1462,7 +1462,7 @@
  */
 
 int dfx_close(
-	struct device *dev
+	struct net_device *dev
 	)
 
 	{
@@ -1882,7 +1882,7 @@
 	)
 
 	{
-	struct device	*dev = (struct device *) dev_id;
+	struct net_device	*dev = (struct net_device *) dev_id;
 	DFX_board_t		*bp;	/* private board structure pointer */
 	u8				tmp;	/* used for disabling/enabling ints */
 
@@ -1990,7 +1990,7 @@
  */
 
 struct net_device_stats *dfx_ctl_get_stats(
-	struct device *dev
+	struct net_device *dev
 	)
 
 	{
@@ -2178,7 +2178,7 @@
  */
 
 void dfx_ctl_set_multicast_list(
-	struct device *dev
+	struct net_device *dev
 	)
 
 	{
@@ -2296,7 +2296,7 @@
  */
 
 int dfx_ctl_set_mac_address(
-	struct device	*dev,
+	struct net_device	*dev,
 	void			*addr
 	)
 
@@ -3188,7 +3188,7 @@
 
 int dfx_xmt_queue_pkt(
 	struct sk_buff	*skb,
-	struct device	*dev
+	struct net_device	*dev
 	)
 
 	{
diff -u --recursive --new-file v2.3.13/linux/drivers/net/defxx.h linux/drivers/net/defxx.h
--- v2.3.13/linux/drivers/net/defxx.h	Fri Apr 16 13:58:46 1999
+++ linux/drivers/net/defxx.h	Wed Aug 18 11:36:45 1999
@@ -1755,7 +1755,7 @@
 
 	/* Store device, bus-specific, and parameter information for this adapter */
 
-	struct device			*dev;							/* pointer to device structure */
+	struct net_device			*dev;							/* pointer to device structure */
 	u32						bus_type;						/* bus type (0 == PCI, 1 == EISA) */
 	u16						base_addr;						/* base I/O address (same as dev->base_addr) */
 	struct pci_dev *				pci_dev;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/depca.c linux/drivers/net/depca.c
--- v2.3.13/linux/drivers/net/depca.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/depca.c	Wed Aug 18 11:36:41 1999
@@ -416,39 +416,39 @@
 /*
 ** Public Functions
 */
-static int    depca_open(struct device *dev);
-static int    depca_start_xmit(struct sk_buff *skb, struct device *dev);
+static int    depca_open(struct net_device *dev);
+static int    depca_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static void   depca_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static int    depca_close(struct device *dev);
-static int    depca_ioctl(struct device *dev, struct ifreq *rq, int cmd);
-static struct net_device_stats *depca_get_stats(struct device *dev);
-static void   set_multicast_list(struct device *dev);
+static int    depca_close(struct net_device *dev);
+static int    depca_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static struct net_device_stats *depca_get_stats(struct net_device *dev);
+static void   set_multicast_list(struct net_device *dev);
 
 /*
 ** Private functions
 */
-static int    depca_hw_init(struct device *dev, u_long ioaddr, int mca_slot);
-static void   depca_init_ring(struct device *dev);
-static int    depca_rx(struct device *dev);
-static int    depca_tx(struct device *dev);
+static int    depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot);
+static void   depca_init_ring(struct net_device *dev);
+static int    depca_rx(struct net_device *dev);
+static int    depca_tx(struct net_device *dev);
 
-static void   LoadCSRs(struct device *dev);
-static int    InitRestartDepca(struct device *dev);
+static void   LoadCSRs(struct net_device *dev);
+static int    InitRestartDepca(struct net_device *dev);
 static void   DepcaSignature(char *name, u_long paddr);
 static int    DevicePresent(u_long ioaddr);
-static int    get_hw_addr(struct device *dev);
+static int    get_hw_addr(struct net_device *dev);
 static int    EISA_signature(char *name, s32 eisa_id);
-static void   SetMulticastFilter(struct device *dev);
-static void   isa_probe(struct device *dev, u_long iobase);
-static void   eisa_probe(struct device *dev, u_long iobase);
+static void   SetMulticastFilter(struct net_device *dev);
+static void   isa_probe(struct net_device *dev, u_long iobase);
+static void   eisa_probe(struct net_device *dev, u_long iobase);
 #ifdef CONFIG_MCA      
-static void   mca_probe(struct device *dev, u_long iobase);
+static void   mca_probe(struct net_device *dev, u_long iobase);
 #endif
-static struct device *alloc_device(struct device *dev, u_long iobase);
+static struct net_device *alloc_device(struct net_device *dev, u_long iobase);
 static int    depca_dev_index(char *s);
-static struct device *insert_device(struct device *dev, u_long iobase, int (*init)(struct device *));
-static int    load_packet(struct device *dev, struct sk_buff *skb);
-static void   depca_dbg_open(struct device *dev);
+static struct net_device *insert_device(struct net_device *dev, u_long iobase, int (*init)(struct net_device *));
+static int    load_packet(struct net_device *dev, struct sk_buff *skb);
+static void   depca_dbg_open(struct net_device *dev);
 
 #ifdef MODULE
 int           init_module(void);
@@ -477,7 +477,7 @@
     outw(STOP, DEPCA_DATA)
 
 int __init 
-depca_probe(struct device *dev)
+depca_probe(struct net_device *dev)
 {
   int tmp = num_depcas, status = -ENODEV;
   u_long iobase = dev->base_addr;
@@ -511,7 +511,7 @@
 }
 
 static int __init 
-depca_hw_init(struct device *dev, u_long ioaddr, int mca_slot)
+depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot)
 {
   struct depca_private *lp;
   int i, j, offset, netRAM, mem_len, status=0;
@@ -723,7 +723,7 @@
 
 
 static int
-depca_open(struct device *dev)
+depca_open(struct net_device *dev)
 {
   struct depca_private *lp = (struct depca_private *)dev->priv;
   u_long ioaddr = dev->base_addr;
@@ -774,7 +774,7 @@
 
 /* Initialize the lance Rx and Tx descriptor rings. */
 static void
-depca_init_ring(struct device *dev)
+depca_init_ring(struct net_device *dev)
 {
   struct depca_private *lp = (struct depca_private *)dev->priv;
   u_int i;
@@ -817,7 +817,7 @@
 ** Writes a socket buffer to TX descriptor ring and starts transmission 
 */
 static int
-depca_start_xmit(struct sk_buff *skb, struct device *dev)
+depca_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
   struct depca_private *lp = (struct depca_private *)dev->priv;
   u_long ioaddr = dev->base_addr;
@@ -877,7 +877,7 @@
 static void
 depca_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-  struct device *dev = dev_id;
+  struct net_device *dev = dev_id;
   struct depca_private *lp;
   s16 csr0, nicsr;
   u_long ioaddr;
@@ -926,7 +926,7 @@
 }
 
 static int
-depca_rx(struct device *dev)
+depca_rx(struct net_device *dev)
 {
   struct depca_private *lp = (struct depca_private *)dev->priv;
   int i, entry;
@@ -1026,7 +1026,7 @@
 ** Buffer sent - check for buffer errors.
 */
 static int
-depca_tx(struct device *dev)
+depca_tx(struct net_device *dev)
 {
   struct depca_private *lp = (struct depca_private *)dev->priv;
   int entry;
@@ -1064,7 +1064,7 @@
 }
 
 static int
-depca_close(struct device *dev)
+depca_close(struct net_device *dev)
 {
   struct depca_private *lp = (struct depca_private *)dev->priv;
   s16 nicsr;
@@ -1105,7 +1105,7 @@
   return 0;
 }
 
-static void LoadCSRs(struct device *dev)
+static void LoadCSRs(struct net_device *dev)
 {
   struct depca_private *lp = (struct depca_private *)dev->priv;
   u_long ioaddr = dev->base_addr;
@@ -1122,7 +1122,7 @@
   return;
 }
 
-static int InitRestartDepca(struct device *dev)
+static int InitRestartDepca(struct net_device *dev)
 {
   struct depca_private *lp = (struct depca_private *)dev->priv;
   u_long ioaddr = dev->base_addr;
@@ -1154,7 +1154,7 @@
 }
 
 static struct net_device_stats *
-depca_get_stats(struct device *dev)
+depca_get_stats(struct net_device *dev)
 {
     struct depca_private *lp = (struct depca_private *)dev->priv;
 
@@ -1167,7 +1167,7 @@
 ** Set or clear the multicast filter for this adaptor.
 */
 static void
-set_multicast_list(struct device *dev)
+set_multicast_list(struct net_device *dev)
 {
   struct depca_private *lp = (struct depca_private *)dev->priv;
   u_long ioaddr = dev->base_addr;
@@ -1199,7 +1199,7 @@
 ** Big endian crc one liner is mine, all mine, ha ha ha ha!
 ** LANCE calculates its hash codes big endian.
 */
-static void SetMulticastFilter(struct device *dev)
+static void SetMulticastFilter(struct net_device *dev)
 {
   struct depca_private *lp = (struct depca_private *)dev->priv;
   struct dev_mc_list *dmi=dev->mc_list;
@@ -1249,7 +1249,7 @@
 ** Microchannel bus I/O device probe
 */
 static void __init 
-mca_probe(struct device *dev, u_long ioaddr)
+mca_probe(struct net_device *dev, u_long ioaddr)
 {
     unsigned char pos[2];
     unsigned char where;
@@ -1398,7 +1398,7 @@
 ** ISA bus I/O device probe
 */
 static void __init 
-isa_probe(struct device *dev, u_long ioaddr)
+isa_probe(struct net_device *dev, u_long ioaddr)
 {
   int i = num_depcas, maxSlots;
   s32 ports[] = DEPCA_IO_PORTS;
@@ -1437,7 +1437,7 @@
 ** the motherboard. Upto 15 EISA devices are supported.
 */
 static void __init 
-eisa_probe(struct device *dev, u_long ioaddr)
+eisa_probe(struct net_device *dev, u_long ioaddr)
 {
   int i, maxSlots;
   u_long iobase;
@@ -1483,10 +1483,10 @@
 ** are not available then insert a new device structure at the end of
 ** the current list.
 */
-static struct device * __init 
-alloc_device(struct device *dev, u_long iobase)
+static struct net_device * __init 
+alloc_device(struct net_device *dev, u_long iobase)
 {
-    struct device *adev = NULL;
+    struct net_device *adev = NULL;
     int fixed = 0, new_dev = 0;
 
     num_eth = depca_dev_index(dev->name);
@@ -1528,12 +1528,12 @@
 ** If at end of eth device list and can't use current entry, malloc
 ** one up. If memory could not be allocated, print an error message.
 */
-static struct device * __init 
-insert_device(struct device *dev, u_long iobase, int (*init)(struct device *))
+static struct net_device * __init 
+insert_device(struct net_device *dev, u_long iobase, int (*init)(struct net_device *))
 {
-    struct device *new;
+    struct net_device *new;
 
-    new = (struct device *)kmalloc(sizeof(struct device)+8, GFP_KERNEL);
+    new = (struct net_device *)kmalloc(sizeof(struct net_device)+8, GFP_KERNEL);
     if (new == NULL) {
 	printk("eth%d: Device not initialised, insufficient memory\n",num_eth);
 	return NULL;
@@ -1681,7 +1681,7 @@
 ** with x=1.
 */
 static int __init 
-get_hw_addr(struct device *dev)
+get_hw_addr(struct net_device *dev)
 {
   u_long ioaddr = dev->base_addr;
   int i, k, tmp, status = 0;
@@ -1712,7 +1712,7 @@
 /*
 ** Load a packet into the shared memory
 */
-static int load_packet(struct device *dev, struct sk_buff *skb)
+static int load_packet(struct net_device *dev, struct sk_buff *skb)
 {
   struct depca_private *lp = (struct depca_private *)dev->priv;
   int i, entry, end, len, status = 0;
@@ -1801,7 +1801,7 @@
   return status;
 }
 
-static void depca_dbg_open(struct device *dev)
+static void depca_dbg_open(struct net_device *dev)
 {
   struct depca_private *lp = (struct depca_private *)dev->priv;
   u_long ioaddr = dev->base_addr;
@@ -1880,7 +1880,7 @@
 ** effective uid is checked in those cases.
 ** All multicast IOCTLs will not work here and are for testing purposes only.
 */
-static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd)
+static int depca_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
   struct depca_private *lp = (struct depca_private *)dev->priv;
   struct depca_ioctl *ioc = (struct depca_ioctl *) &rq->ifr_data;
@@ -2015,7 +2015,7 @@
 
 #ifdef MODULE
 static char devicename[9] = {0,};
-static struct device thisDepca = {
+static struct net_device thisDepca = {
   devicename,  /* device name is inserted by /linux/drivers/net/net_init.c */
   0, 0, 0, 0,
   0x200, 7,    /* I/O address, IRQ */
diff -u --recursive --new-file v2.3.13/linux/drivers/net/dgrs.c linux/drivers/net/dgrs.c
--- v2.3.13/linux/drivers/net/dgrs.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/dgrs.c	Wed Aug 18 11:36:41 1999
@@ -183,7 +183,7 @@
  *	Chain of device structures
  */
 #ifdef MODULE
-	static struct device *dgrs_root_dev = NULL;
+	static struct net_device *dgrs_root_dev = NULL;
 #endif
 
 /*
@@ -195,7 +195,7 @@
 	 *	Stuff for generic ethercard I/F
 	 */
 	char			devname[8];	/* "ethN" string */
-	struct device		*next_dev;
+	struct net_device		*next_dev;
 	struct net_device_stats	stats;
 
 	/*
@@ -240,7 +240,7 @@
 	 */
 	int		nports;		/* Number of physical ports (4 or 6) */
 	int		chan;		/* Channel # (1-6) for this device */
-	struct device	*devtbl[6];	/* Ptrs to N device structs */
+	struct net_device	*devtbl[6];	/* Ptrs to N device structs */
 
 } DGRS_PRIV;
 
@@ -249,7 +249,7 @@
  *	reset or un-reset the IDT processor
  */
 static void
-proc_reset(struct device *dev0, int reset)
+proc_reset(struct net_device *dev0, int reset)
 {
 	DGRS_PRIV	*priv0 = (DGRS_PRIV *) dev0->priv;
 
@@ -273,7 +273,7 @@
  *	See if the board supports bus master DMA
  */
 static int
-check_board_dma(struct device *dev0)
+check_board_dma(struct net_device *dev0)
 {
 	DGRS_PRIV	*priv0 = (DGRS_PRIV *) dev0->priv;
 	ulong	x;
@@ -347,7 +347,7 @@
  */
 static int
 do_plx_dma(
-	struct device *dev,
+	struct net_device *dev,
 	ulong pciaddr,
 	ulong lcladdr,
 	int len,
@@ -453,7 +453,7 @@
  */
 void
 dgrs_rcv_frame(
-	struct device	*dev0,
+	struct net_device	*dev0,
 	DGRS_PRIV	*priv0,
 	I596_CB		*cbp
 )
@@ -463,7 +463,7 @@
 	struct sk_buff	*skb;
 	uchar		*putp;
 	uchar		*p;
-	struct device	*devN;
+	struct net_device	*devN;
 	DGRS_PRIV	*privN;
 
 	/*
@@ -689,10 +689,10 @@
  *	end of the traditional 82596 RFD structure.
  */
 
-static int dgrs_start_xmit(struct sk_buff *skb, struct device *devN)
+static int dgrs_start_xmit(struct sk_buff *skb, struct net_device *devN)
 {
 	DGRS_PRIV	*privN = (DGRS_PRIV *) devN->priv;
-	struct device	*dev0;
+	struct net_device	*dev0;
 	DGRS_PRIV	*priv0;
 	I596_RBD	*rbdp;
 	int		count;
@@ -788,7 +788,7 @@
  *	Open the interface
  */
 static int
-dgrs_open( struct device *dev )
+dgrs_open( struct net_device *dev )
 {
 	dev->tbusy = 0;
 	dev->interrupt = 0;
@@ -804,7 +804,7 @@
 /*
  *	Close the interface
  */
-static int dgrs_close( struct device *dev )
+static int dgrs_close( struct net_device *dev )
 {
 	dev->start = 0;
 	dev->tbusy = 1;
@@ -819,7 +819,7 @@
 /*
  *	Get statistics
  */
-static struct net_device_stats *dgrs_get_stats( struct device *dev )
+static struct net_device_stats *dgrs_get_stats( struct net_device *dev )
 {
 	DGRS_PRIV	*priv = (DGRS_PRIV *) dev->priv;
 
@@ -830,7 +830,7 @@
  *	Set multicast list and/or promiscuous mode
  */
 
-static void dgrs_set_multicast_list( struct device *dev)
+static void dgrs_set_multicast_list( struct net_device *dev)
 {
 	DGRS_PRIV	*priv = (DGRS_PRIV *) dev->priv;
 
@@ -840,7 +840,7 @@
 /*
  *	Unique ioctl's
  */
-static int dgrs_ioctl(struct device *devN, struct ifreq *ifr, int cmd)
+static int dgrs_ioctl(struct net_device *devN, struct ifreq *ifr, int cmd)
 {
 	DGRS_PRIV	*privN = (DGRS_PRIV *) devN->priv;
 	DGRS_IOCTL	ioc;
@@ -905,7 +905,7 @@
 
 static void dgrs_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device	*dev0 = (struct device *) dev_id;
+	struct net_device	*dev0 = (struct net_device *) dev_id;
 	DGRS_PRIV	*priv0 = (DGRS_PRIV *) dev0->priv;
 	I596_CB		*cbp;
 	int		cmd;
@@ -992,7 +992,7 @@
  *	Download the board firmware
  */
 static int __init 
-dgrs_download(struct device *dev0)
+dgrs_download(struct net_device *dev0)
 {
 	DGRS_PRIV	*priv0 = (DGRS_PRIV *) dev0->priv;
 	int		is;
@@ -1151,7 +1151,7 @@
  *	Probe (init) a board
  */
 int __init 
-dgrs_probe1(struct device *dev)
+dgrs_probe1(struct net_device *dev)
 {
 	DGRS_PRIV	*priv = (DGRS_PRIV *) dev->priv;
 	int		i;
@@ -1225,7 +1225,7 @@
 }
 
 int __init 
-dgrs_initclone(struct device *dev)
+dgrs_initclone(struct net_device *dev)
 {
 	DGRS_PRIV	*priv = (DGRS_PRIV *) dev->priv;
 	int		i;
@@ -1241,7 +1241,7 @@
 
 static int __init 
 dgrs_found_device(
-	struct device	*dev,
+	struct net_device	*dev,
 	int		io,
 	ulong		mem,
 	int		irq,
@@ -1254,12 +1254,12 @@
 	#ifdef MODULE
 	{
 		/* Allocate and fill new device structure. */
-		int dev_size = sizeof(struct device) + sizeof(DGRS_PRIV);
+		int dev_size = sizeof(struct net_device) + sizeof(DGRS_PRIV);
 		int i;
 
-		dev = (struct device *) kmalloc(dev_size, GFP_KERNEL);
+		dev = (struct net_device *) kmalloc(dev_size, GFP_KERNEL);
 		memset(dev, 0, dev_size);
-		dev->priv = ((void *)dev) + sizeof(struct device);
+		dev->priv = ((void *)dev) + sizeof(struct net_device);
 		priv = (DGRS_PRIV *)dev->priv;
 
 		dev->name = priv->devname; /* An empty string. */
@@ -1291,15 +1291,15 @@
 		priv->nports = priv->bcomm->bc_nports;
 		for (i = 1; i < priv->nports; ++i)
 		{
-			struct device	*devN;
+			struct net_device	*devN;
 			DGRS_PRIV	*privN;
 
 			/* Allocate new dev and priv structures */
-			devN = (struct device *) kmalloc(dev_size, GFP_KERNEL);
+			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 device);
+			devN->priv = ((void *)devN) + sizeof(struct net_device);
 			privN = (DGRS_PRIV *)devN->priv;
 
 			/* ... but seset devname to a NULL string */
@@ -1361,7 +1361,7 @@
 static int is2iv[8] __initdata = { 0, 3, 5, 7, 10, 11, 12, 15 };
 
 static int __init 
-dgrs_scan(struct device *dev)
+dgrs_scan(struct net_device *dev)
 {
 	int	cards_found = 0;
 	uint	io;
@@ -1574,7 +1574,7 @@
 {
         while (dgrs_root_dev)
 	{
-		struct device	*next_dev;
+		struct net_device	*next_dev;
 		DGRS_PRIV	*priv;
 
 		priv = (DGRS_PRIV *) dgrs_root_dev->priv;
@@ -1601,7 +1601,7 @@
 #else
 
 int __init 
-dgrs_probe(struct device *dev)
+dgrs_probe(struct net_device *dev)
 {
 	int	cards_found;
 
diff -u --recursive --new-file v2.3.13/linux/drivers/net/dlci.c linux/drivers/net/dlci.c
--- v2.3.13/linux/drivers/net/dlci.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/dlci.c	Wed Aug 18 11:36:42 1999
@@ -60,11 +60,11 @@
 static const char *devname = "dlci";
 static const char *version = "DLCI driver v0.35, 4 Jan 1997, mike.mclagan@linux.org";
 
-static struct device *open_dev[CONFIG_DLCI_COUNT];
+static struct net_device *open_dev[CONFIG_DLCI_COUNT];
 
 static char *basename[16];
 
-int dlci_init(struct device *dev);
+int dlci_init(struct net_device *dev);
 
 /* allow FRAD's to register their name as a valid FRAD */
 int register_frad(const char *name)
@@ -122,7 +122,7 @@
  * the upper network layers 
  */
 
-static int dlci_header(struct sk_buff *skb, struct device *dev, 
+static int dlci_header(struct sk_buff *skb, struct net_device *dev, 
                            unsigned short type, void *daddr, void *saddr, 
                            unsigned len)
 {
@@ -161,7 +161,7 @@
 	return(hlen);
 }
 
-static void dlci_receive(struct sk_buff *skb, struct device *dev)
+static void dlci_receive(struct sk_buff *skb, struct net_device *dev)
 {
 	struct dlci_local *dlp;
 	struct frhdr		*hdr;
@@ -234,7 +234,7 @@
 		dev_kfree_skb(skb);
 }
 
-static int dlci_transmit(struct sk_buff *skb, struct device *dev)
+static int dlci_transmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct dlci_local *dlp;
 	int					ret;
@@ -284,7 +284,7 @@
 	return(ret);
 }
 
-int dlci_config(struct device *dev, struct dlci_conf *conf, int get)
+int dlci_config(struct net_device *dev, struct dlci_conf *conf, int get)
 {
 	struct dlci_conf	config;
 	struct dlci_local	*dlp;
@@ -318,7 +318,7 @@
 	return(0);
 }
 
-int dlci_dev_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
+int dlci_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	struct dlci_local *dlp;
 
@@ -350,7 +350,7 @@
 	return(0);
 }
 
-static int dlci_change_mtu(struct device *dev, int new_mtu)
+static int dlci_change_mtu(struct net_device *dev, int new_mtu)
 {
 	struct dlci_local *dlp;
 
@@ -359,7 +359,7 @@
 	return((*dlp->slave->change_mtu)(dlp->slave, new_mtu));
 }
 
-static int dlci_open(struct device *dev)
+static int dlci_open(struct net_device *dev)
 {
 	struct dlci_local	*dlp;
 	struct frad_local	*flp;
@@ -386,7 +386,7 @@
 	return 0;
 }
 
-static int dlci_close(struct device *dev)
+static int dlci_close(struct net_device *dev)
 {
 	struct dlci_local	*dlp;
 	struct frad_local	*flp;
@@ -403,7 +403,7 @@
 	return 0;
 }
 
-static struct net_device_stats *dlci_get_stats(struct device *dev)
+static struct net_device_stats *dlci_get_stats(struct net_device *dev)
 {
 	struct dlci_local *dlp;
 
@@ -414,7 +414,7 @@
 
 int dlci_add(struct dlci_add *dlci)
 {
-	struct device		*master, *slave;
+	struct net_device		*master, *slave;
 	struct dlci_local	*dlp;
 	struct frad_local	*flp;
 	int			err, i;
@@ -500,7 +500,7 @@
 {
 	struct dlci_local	*dlp;
 	struct frad_local	*flp;
-	struct device		*master, *slave;
+	struct net_device		*master, *slave;
 	int			i, err;
 
 	/* validate slave device */
@@ -569,7 +569,7 @@
 	return(err);
 }
 
-int dlci_init(struct device *dev)
+int dlci_init(struct net_device *dev)
 {
 	struct dlci_local *dlp;
 
diff -u --recursive --new-file v2.3.13/linux/drivers/net/dummy.c linux/drivers/net/dummy.c
--- v2.3.13/linux/drivers/net/dummy.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/dummy.c	Wed Aug 18 11:36:42 1999
@@ -53,34 +53,34 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 
-static int dummy_xmit(struct sk_buff *skb, struct device *dev);
-static struct net_device_stats *dummy_get_stats(struct device *dev);
+static int dummy_xmit(struct sk_buff *skb, struct net_device *dev);
+static struct net_device_stats *dummy_get_stats(struct net_device *dev);
 
-static int dummy_open(struct device *dev)
+static int dummy_open(struct net_device *dev)
 {
 	MOD_INC_USE_COUNT;
 	return 0;
 }
 
-static int dummy_close(struct device *dev)
+static int dummy_close(struct net_device *dev)
 {
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
 /* fake multicast ability */
-static void set_multicast_list(struct device *dev)
+static void set_multicast_list(struct net_device *dev)
 {
 }
 
 #ifdef CONFIG_NET_FASTROUTE
-static int dummy_accept_fastpath(struct device *dev, struct dst_entry *dst)
+static int dummy_accept_fastpath(struct net_device *dev, struct dst_entry *dst)
 {
 	return -1;
 }
 #endif
 
-int __init dummy_init(struct device *dev)
+int __init dummy_init(struct net_device *dev)
 {
 	/* Initialize the device structure. */
 	dev->hard_start_xmit	= dummy_xmit;
@@ -107,7 +107,7 @@
 	return 0;
 }
 
-static int dummy_xmit(struct sk_buff *skb, struct device *dev)
+static int dummy_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct net_device_stats *stats;
 	dev_kfree_skb(skb);
@@ -119,7 +119,7 @@
 	return 0;
 }
 
-static struct net_device_stats *dummy_get_stats(struct device *dev)
+static struct net_device_stats *dummy_get_stats(struct net_device *dev)
 {
 	struct net_device_stats *stats = (struct net_device_stats *) dev->priv;
 	return stats;
@@ -127,7 +127,7 @@
 
 #ifdef MODULE
 
-static int __init dummy_probe(struct device *dev)
+static int __init dummy_probe(struct net_device *dev)
 {
 	dummy_init(dev);
 	return 0;
@@ -135,7 +135,7 @@
 
 static char dummy_name[16];
 
-static struct device dev_dummy = {
+static struct net_device dev_dummy = {
 		dummy_name, 	/* Needs to be writeable */
 		0, 0, 0, 0,
 	 	0x0, 0,
diff -u --recursive --new-file v2.3.13/linux/drivers/net/e2100.c linux/drivers/net/e2100.c
--- v2.3.13/linux/drivers/net/e2100.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/e2100.c	Wed Aug 18 11:36:42 1999
@@ -95,19 +95,19 @@
 #define E21_BIG_RX_STOP_PG	0xF0	/* Last page +1 of RX ring */
 #define E21_TX_START_PG		E21_RX_STOP_PG	/* First page of TX buffer */
 
-int e2100_probe(struct device *dev);
-int e21_probe1(struct device *dev, int ioaddr);
+int e2100_probe(struct net_device *dev);
+int e21_probe1(struct net_device *dev, int ioaddr);
 
-static int e21_open(struct device *dev);
-static void e21_reset_8390(struct device *dev);
-static void e21_block_input(struct device *dev, int count,
+static int e21_open(struct net_device *dev);
+static void e21_reset_8390(struct net_device *dev);
+static void e21_block_input(struct net_device *dev, int count,
 						   struct sk_buff *skb, int ring_offset);
-static void e21_block_output(struct device *dev, int count,
+static void e21_block_output(struct net_device *dev, int count,
 							 const unsigned char *buf, int start_page);
-static void e21_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
+static void e21_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
 							int ring_page);
 
-static int e21_close(struct device *dev);
+static int e21_close(struct net_device *dev);
 
 
 /*  Probe for the E2100 series ethercards.  These cards have an 8390 at the
@@ -117,7 +117,7 @@
 	station address).
  */
 
-int  __init e2100_probe(struct device *dev)
+int  __init e2100_probe(struct net_device *dev)
 {
 	int *port;
 	int base_addr = dev->base_addr;
@@ -137,7 +137,7 @@
 	return ENODEV;
 }
 
-int __init e21_probe1(struct device *dev, int ioaddr)
+int __init e21_probe1(struct net_device *dev, int ioaddr)
 {
 	int i, status;
 	unsigned char *station_addr = dev->dev_addr;
@@ -254,7 +254,7 @@
 }
 
 static int
-e21_open(struct device *dev)
+e21_open(struct net_device *dev)
 {
 	short ioaddr = dev->base_addr;
 
@@ -277,7 +277,7 @@
 }
 
 static void
-e21_reset_8390(struct device *dev)
+e21_reset_8390(struct net_device *dev)
 {
 	short ioaddr = dev->base_addr;
 
@@ -295,7 +295,7 @@
    appears at the start of the shared memory. */
 
 static void
-e21_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+e21_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 {
 
 	short ioaddr = dev->base_addr;
@@ -319,7 +319,7 @@
 	The E21xx makes block_input() especially easy by wrapping the top
 	ring buffer to the bottom automatically. */
 static void
-e21_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
+e21_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
 {
 	short ioaddr = dev->base_addr;
 	char *shared_mem = (char *)dev->mem_start;
@@ -333,7 +333,7 @@
 }
 
 static void
-e21_block_output(struct device *dev, int count, const unsigned char *buf,
+e21_block_output(struct net_device *dev, int count, const unsigned char *buf,
 				 int start_page)
 {
 	short ioaddr = dev->base_addr;
@@ -349,7 +349,7 @@
 }
 
 static int
-e21_close(struct device *dev)
+e21_close(struct net_device *dev)
 {
 	short ioaddr = dev->base_addr;
 
@@ -386,7 +386,7 @@
 #define MAX_E21_CARDS	4	/* Max number of E21 cards per module */
 #define NAMELEN		8	/* # of chars for storing dev->name */
 static char namelist[NAMELEN * MAX_E21_CARDS] = { 0, };
-static struct device dev_e21[MAX_E21_CARDS] = {
+static struct net_device dev_e21[MAX_E21_CARDS] = {
 	{
 		NULL,		/* assign a chunk of namelist[] below */
 		0, 0, 0, 0,
@@ -413,7 +413,7 @@
 	int this_dev, found = 0;
 
 	for (this_dev = 0; this_dev < MAX_E21_CARDS; this_dev++) {
-		struct device *dev = &dev_e21[this_dev];
+		struct net_device *dev = &dev_e21[this_dev];
 		dev->name = namelist+(NAMELEN*this_dev);
 		dev->irq = irq[this_dev];
 		dev->base_addr = io[this_dev];
@@ -444,7 +444,7 @@
 	int this_dev;
 
 	for (this_dev = 0; this_dev < MAX_E21_CARDS; this_dev++) {
-		struct device *dev = &dev_e21[this_dev];
+		struct net_device *dev = &dev_e21[this_dev];
 		if (dev->priv != NULL) {
 			void *priv = dev->priv;
 			/* NB: e21_close() handles free_irq */
diff -u --recursive --new-file v2.3.13/linux/drivers/net/eepro.c linux/drivers/net/eepro.c
--- v2.3.13/linux/drivers/net/eepro.c	Thu Jan  7 08:47:54 1999
+++ linux/drivers/net/eepro.c	Wed Aug 18 11:36:42 1999
@@ -303,21 +303,21 @@
 
 /* Index to functions, as function prototypes. */
 
-extern int eepro_probe(struct device *dev);
+extern int eepro_probe(struct net_device *dev);
 
-static int	eepro_probe1(struct device *dev, short ioaddr);
-static int	eepro_open(struct device *dev);
-static int	eepro_send_packet(struct sk_buff *skb, struct device *dev);
+static int	eepro_probe1(struct net_device *dev, short ioaddr);
+static int	eepro_open(struct net_device *dev);
+static int	eepro_send_packet(struct sk_buff *skb, struct net_device *dev);
 static void	eepro_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void 	eepro_rx(struct device *dev);
-static void 	eepro_transmit_interrupt(struct device *dev);
-static int	eepro_close(struct device *dev);
-static struct enet_statistics *eepro_get_stats(struct device *dev);
-static void     set_multicast_list(struct device *dev);
+static void 	eepro_rx(struct net_device *dev);
+static void 	eepro_transmit_interrupt(struct net_device *dev);
+static int	eepro_close(struct net_device *dev);
+static struct enet_statistics *eepro_get_stats(struct net_device *dev);
+static void     set_multicast_list(struct net_device *dev);
 
 static int read_eeprom(int ioaddr, int location);
-static void hardware_send_packet(struct device *dev, void *buf, short length);
-static int	eepro_grab_irq(struct device *dev);
+static void hardware_send_packet(struct net_device *dev, void *buf, short length);
+static int	eepro_grab_irq(struct net_device *dev);
 
 /*
 			Details of the i82595.
@@ -461,7 +461,7 @@
 struct netdev_entry netcard_drv =
 {"eepro", eepro_probe1, EEPRO_IO_EXTENT, eepro_portlist};
 #else
-compat_init_func(int eepro_probe(struct device *dev))
+compat_init_func(int eepro_probe(struct net_device *dev))
 {
 	int i;
 	int base_addr = dev ? dev->base_addr : 0;
@@ -575,7 +575,7 @@
    probes on the ISA bus.  A good device probe avoids doing writes, and
    verifies that the correct device exists and functions.  */
 
-int eepro_probe1(struct device *dev, short ioaddr)
+int eepro_probe1(struct net_device *dev, short ioaddr)
 {
 	unsigned short station_addr[6], id, counter;
 	int i,j, irqMask;
@@ -746,7 +746,7 @@
 
 static char irqrmap[] = {-1,-1,0,1,-1,2,-1,-1,-1,0,3,4,-1,-1,-1,-1};
 static char irqrmap2[] = {-1,-1,4,0,1,2,-1,3,-1,4,5,6,7,-1,-1,-1};
-static int	eepro_grab_irq(struct device *dev)
+static int	eepro_grab_irq(struct net_device *dev)
 {
 	int irqlist[] = { 3, 4, 5, 7, 9, 10, 11, 12 };
 	int *irqp = irqlist, temp_reg, ioaddr = dev->base_addr;
@@ -804,7 +804,7 @@
 	return dev->irq;
 }
 
-static int eepro_open(struct device *dev)
+static int eepro_open(struct net_device *dev)
 {
 	unsigned short temp_reg, old8, old9;
 	int irqMask;
@@ -984,7 +984,7 @@
 	return 0;
 }
 
-static int eepro_send_packet(struct sk_buff *skb, struct device *dev)
+static int eepro_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
 	struct eepro_local *lp = (struct eepro_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -1087,8 +1087,8 @@
 static void
 eepro_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
-	struct device *dev =  (struct device *)dev_id;
-	                      /* (struct device *)(irq2dev_map[irq]);*/
+	struct net_device *dev =  (struct net_device *)dev_id;
+	                      /* (struct net_device *)(irq2dev_map[irq]);*/
 	struct eepro_local *lp = (struct eepro_local *)dev->priv;
 	int ioaddr, status, boguscount = 20;
 
@@ -1155,7 +1155,7 @@
 	return;
 }
 
-static int eepro_close(struct device *dev)
+static int eepro_close(struct net_device *dev)
 {
 	struct eepro_local *lp = (struct eepro_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -1207,7 +1207,7 @@
 /* Get the current statistics.	This may be called with the card open or
    closed. */
 static struct enet_statistics *
-eepro_get_stats(struct device *dev)
+eepro_get_stats(struct net_device *dev)
 {
 	struct eepro_local *lp = (struct eepro_local *)dev->priv;
 
@@ -1217,7 +1217,7 @@
 /* Set or clear the multicast filter for this adaptor.
  */
 static void
-set_multicast_list(struct device *dev)
+set_multicast_list(struct net_device *dev)
 {
 	struct eepro_local *lp = (struct eepro_local *)dev->priv;
 	short ioaddr = dev->base_addr;
@@ -1386,7 +1386,7 @@
 }
 
 static void
-hardware_send_packet(struct device *dev, void *buf, short length)
+hardware_send_packet(struct net_device *dev, void *buf, short length)
 {
 	struct eepro_local *lp = (struct eepro_local *)dev->priv;
 	short ioaddr = dev->base_addr;
@@ -1503,7 +1503,7 @@
 }
 
 static void
-eepro_rx(struct device *dev)
+eepro_rx(struct net_device *dev)
 {
 	struct eepro_local *lp = (struct eepro_local *)dev->priv;
 	short ioaddr = dev->base_addr, rcv_ram = dev->mem_end;
@@ -1597,7 +1597,7 @@
 }
 
 static void
-eepro_transmit_interrupt(struct device *dev)
+eepro_transmit_interrupt(struct net_device *dev)
 {
 	struct eepro_local *lp = (struct eepro_local *)dev->priv;
 	short ioaddr = dev->base_addr;
@@ -1655,7 +1655,7 @@
 
 #define MAX_EEPRO 8
 static char devicename[MAX_EEPRO][9];
-static struct device dev_eepro[MAX_EEPRO];
+static struct net_device dev_eepro[MAX_EEPRO];
 
 static int io[MAX_EEPRO] = {
 #ifdef PnPWakeup
@@ -1693,7 +1693,7 @@
 		printk("eepro_init_module: You should not use auto-probing with insmod!\n");
 
 	while (n_eepro < MAX_EEPRO && io[n_eepro] >= 0) {
-		struct device *d = &dev_eepro[n_eepro];
+		struct net_device *d = &dev_eepro[n_eepro];
 		d->name		= devicename[n_eepro]; /* inserted by drivers/net/net_init.c */
 		d->mem_end	= mem[n_eepro];
 		d->base_addr	= io[n_eepro];
@@ -1713,7 +1713,7 @@
 	int i;
 	
 	for (i=0; i<n_eepro; i++) {
-		struct device *d = &dev_eepro[i];
+		struct net_device *d = &dev_eepro[i];
 		unregister_netdev(d);
 
 		kfree_s(d->priv,sizeof(struct eepro_local));
diff -u --recursive --new-file v2.3.13/linux/drivers/net/eepro100.c linux/drivers/net/eepro100.c
--- v2.3.13/linux/drivers/net/eepro100.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/eepro100.c	Wed Aug 18 11:36:42 1999
@@ -79,9 +79,6 @@
 #include <linux/modversions.h>
 #endif
 
-#if LINUX_VERSION_CODE < 0x20200  &&  defined(MODVERSIONS)
-#include <linux/modversions.h>
-#endif
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/timer.h>
@@ -287,8 +284,8 @@
 */
 
 /* This table drives the PCI probe routines. */
-static struct device *
-speedo_found1(int pci_bus, int pci_devfn, struct device *dev,
+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);
 
 #ifdef USE_IO
@@ -315,7 +312,7 @@
 	const char *name;
 	u16	vendor_id, device_id, device_id_mask, flags;
 	int io_size;
-	struct device *(*probe1)(int pci_bus, int pci_devfn, struct device *dev,
+	struct net_device *(*probe1)(int pci_bus, int pci_devfn, struct net_device *dev,
 							 long ioaddr, int irq, int chip_idx, int fnd_cnt);
 } static pci_tbl[] = {
 	{ "Intel PCI EtherExpress Pro100",
@@ -458,7 +455,7 @@
 	unsigned int cur_rx, dirty_rx;		/* The next free ring entry */
 	long last_rx_time;			/* Last Rx, in jiffies, to handle Rx hang. */
 	const char *product_name;
-	struct device *next_module;
+	struct net_device *next_module;
 	void *priv_addr;					/* Unaligned address for kfree */
 	struct enet_statistics stats;
 	struct speedo_stats lstats;
@@ -511,18 +508,18 @@
 static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len);
 static int mdio_read(long ioaddr, int phy_id, int location);
 static int mdio_write(long ioaddr, int phy_id, int location, int value);
-static int speedo_open(struct device *dev);
-static void speedo_resume(struct device *dev);
+static int speedo_open(struct net_device *dev);
+static void speedo_resume(struct net_device *dev);
 static void speedo_timer(unsigned long data);
-static void speedo_init_rx_ring(struct device *dev);
-static void speedo_tx_timeout(struct device *dev);
-static int speedo_start_xmit(struct sk_buff *skb, struct device *dev);
-static int speedo_rx(struct device *dev);
+static void speedo_init_rx_ring(struct net_device *dev);
+static void speedo_tx_timeout(struct net_device *dev);
+static int speedo_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int speedo_rx(struct net_device *dev);
 static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
-static int speedo_close(struct device *dev);
-static struct enet_statistics *speedo_get_stats(struct device *dev);
-static int speedo_ioctl(struct device *dev, struct ifreq *rq, int cmd);
-static void set_rx_mode(struct device *dev);
+static int speedo_close(struct net_device *dev);
+static struct enet_statistics *speedo_get_stats(struct net_device *dev);
+static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static void set_rx_mode(struct net_device *dev);
 
 
 
@@ -534,10 +531,10 @@
 #endif
 
 /* A list of all installed Speedo devices, for removing the driver module. */
-static struct device *root_speedo_dev = NULL;
+static struct net_device *root_speedo_dev = NULL;
 
 #if ! defined(HAS_PCI_NETIF)
-int eepro100_init(struct device *dev)
+int eepro100_init(struct net_device *dev)
 {
 	int cards_found = 0;
 	static int pci_index = 0;
@@ -628,8 +625,8 @@
 }
 #endif
 
-static struct device *
-speedo_found1(int pci_bus, int pci_devfn, struct device *dev,
+static struct net_device *
+speedo_found1(int pci_bus, int pci_devfn, struct net_device *dev,
 			  long ioaddr, int irq, int chip_idx, int card_idx)
 {
 	struct speedo_private *sp;
@@ -899,7 +896,7 @@
 
 
 static int
-speedo_open(struct device *dev)
+speedo_open(struct net_device *dev)
 {
 	struct speedo_private *sp = (struct speedo_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -987,7 +984,7 @@
 }
 
 /* Start the chip hardware after a full reset. */
-static void speedo_resume(struct device *dev)
+static void speedo_resume(struct net_device *dev)
 {
 	struct speedo_private *sp = (struct speedo_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -1043,7 +1040,7 @@
 /* Media monitoring and control. */
 static void speedo_timer(unsigned long data)
 {
-	struct device *dev = (struct device *)data;
+	struct net_device *dev = (struct net_device *)data;
 	struct speedo_private *sp = (struct speedo_private *)dev->priv;
 	long ioaddr = dev->base_addr;
 	int phy_num = sp->phy[0] & 0x1f;
@@ -1090,7 +1087,7 @@
 	add_timer(&sp->timer);
 }
 
-static void speedo_show_state(struct device *dev)
+static void speedo_show_state(struct net_device *dev)
 {
 	struct speedo_private *sp = (struct speedo_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -1125,7 +1122,7 @@
 
 /* Initialize the Rx and Tx rings, along with various 'dev' bits. */
 static void
-speedo_init_rx_ring(struct device *dev)
+speedo_init_rx_ring(struct net_device *dev)
 {
 	struct speedo_private *sp = (struct speedo_private *)dev->priv;
 	struct RxFD *rxf, *last_rxf = NULL;
@@ -1162,7 +1159,7 @@
 	sp->last_rxf = last_rxf;
 }
 
-static void speedo_tx_timeout(struct device *dev)
+static void speedo_tx_timeout(struct net_device *dev)
 {
 	struct speedo_private *sp = (struct speedo_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -1210,7 +1207,7 @@
 }
 
 static int
-speedo_start_xmit(struct sk_buff *skb, struct device *dev)
+speedo_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct speedo_private *sp = (struct speedo_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -1281,7 +1278,7 @@
    after the Tx thread. */
 static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 {
-	struct device *dev = (struct device *)dev_instance;
+	struct net_device *dev = (struct net_device *)dev_instance;
 	struct speedo_private *sp;
 	long ioaddr, boguscnt = max_interrupt_work;
 	unsigned short status;
@@ -1404,7 +1401,7 @@
 }
 
 static int
-speedo_rx(struct device *dev)
+speedo_rx(struct net_device *dev)
 {
 	struct speedo_private *sp = (struct speedo_private *)dev->priv;
 	int entry = sp->cur_rx % RX_RING_SIZE;
@@ -1515,7 +1512,7 @@
 }
 
 static int
-speedo_close(struct device *dev)
+speedo_close(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
 	struct speedo_private *sp = (struct speedo_private *)dev->priv;
@@ -1588,7 +1585,7 @@
    Oh, and incoming frames are dropped while executing dump-stats!
    */
 static struct enet_statistics *
-speedo_get_stats(struct device *dev)
+speedo_get_stats(struct net_device *dev)
 {
 	struct speedo_private *sp = (struct speedo_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -1615,7 +1612,7 @@
 	return &sp->stats;
 }
 
-static int speedo_ioctl(struct device *dev, struct ifreq *rq, int cmd)
+static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct speedo_private *sp = (struct speedo_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -1662,7 +1659,7 @@
    loaded the link -- we convert the current command block, normally a Tx
    command, into a no-op and link it to the new command.
 */
-static void set_rx_mode(struct device *dev)
+static void set_rx_mode(struct net_device *dev)
 {
 	struct speedo_private *sp = (struct speedo_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -1856,7 +1853,7 @@
 
 void cleanup_module(void)
 {
-	struct device *next_dev;
+	struct net_device *next_dev;
 
 	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
 	while (root_speedo_dev) {
@@ -1880,7 +1877,7 @@
 
 #else   /* not MODULE */
 
-int eepro100_probe(struct device *dev)
+int eepro100_probe(struct net_device *dev)
 {
 	int cards_found = 0;
 
diff -u --recursive --new-file v2.3.13/linux/drivers/net/eexpress.c linux/drivers/net/eexpress.c
--- v2.3.13/linux/drivers/net/eexpress.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/eexpress.c	Wed Aug 18 11:36:42 1999
@@ -236,34 +236,34 @@
  * Prototypes for Linux interface
  */
 
-extern int express_probe(struct device *dev);
-static int eexp_open(struct device *dev);
-static int eexp_close(struct device *dev);
-static struct net_device_stats *eexp_stats(struct device *dev);
-static int eexp_xmit(struct sk_buff *buf, struct device *dev);
+extern int express_probe(struct net_device *dev);
+static int eexp_open(struct net_device *dev);
+static int eexp_close(struct net_device *dev);
+static struct net_device_stats *eexp_stats(struct net_device *dev);
+static int eexp_xmit(struct sk_buff *buf, struct net_device *dev);
 
 static void eexp_irq(int irq, void *dev_addr, struct pt_regs *regs);
-static void eexp_set_multicast(struct device *dev);
+static void eexp_set_multicast(struct net_device *dev);
 
 /*
  * Prototypes for hardware access functions
  */
 
-static void eexp_hw_rx_pio(struct device *dev);
-static void eexp_hw_tx_pio(struct device *dev, unsigned short *buf,
+static void eexp_hw_rx_pio(struct net_device *dev);
+static void eexp_hw_tx_pio(struct net_device *dev, unsigned short *buf,
 		       unsigned short len);
-static int eexp_hw_probe(struct device *dev,unsigned short ioaddr);
+static int eexp_hw_probe(struct net_device *dev,unsigned short ioaddr);
 static unsigned short eexp_hw_readeeprom(unsigned short ioaddr,
 					 unsigned char location);
 
-static unsigned short eexp_hw_lasttxstat(struct device *dev);
-static void eexp_hw_txrestart(struct device *dev);
+static unsigned short eexp_hw_lasttxstat(struct net_device *dev);
+static void eexp_hw_txrestart(struct net_device *dev);
 
-static void eexp_hw_txinit    (struct device *dev);
-static void eexp_hw_rxinit    (struct device *dev);
+static void eexp_hw_txinit    (struct net_device *dev);
+static void eexp_hw_rxinit    (struct net_device *dev);
 
-static void eexp_hw_init586   (struct device *dev);
-static void eexp_setup_filter (struct device *dev);
+static void eexp_hw_init586   (struct net_device *dev);
+static void eexp_setup_filter (struct net_device *dev);
 
 static char *eexp_ifmap[]={"AUI", "BNC", "RJ45"};
 enum eexp_iftype {AUI=0, BNC=1, TPE=2};
@@ -275,37 +275,37 @@
  * Primitive hardware access functions.
  */
 
-static inline unsigned short scb_status(struct device *dev)
+static inline unsigned short scb_status(struct net_device *dev)
 {
 	return inw(dev->base_addr + 0xc008);
 }
 
-static inline unsigned short scb_rdcmd(struct device *dev)
+static inline unsigned short scb_rdcmd(struct net_device *dev)
 {
 	return inw(dev->base_addr + 0xc00a);
 }
 
-static inline void scb_command(struct device *dev, unsigned short cmd)
+static inline void scb_command(struct net_device *dev, unsigned short cmd)
 {
 	outw(cmd, dev->base_addr + 0xc00a);
 }
 
-static inline void scb_wrcbl(struct device *dev, unsigned short val)
+static inline void scb_wrcbl(struct net_device *dev, unsigned short val)
 {
 	outw(val, dev->base_addr + 0xc00c);
 }
 
-static inline void scb_wrrfa(struct device *dev, unsigned short val)
+static inline void scb_wrrfa(struct net_device *dev, unsigned short val)
 {
 	outw(val, dev->base_addr + 0xc00e);
 }
 
-static inline void set_loopback(struct device *dev)
+static inline void set_loopback(struct net_device *dev)
 {
 	outb(inb(dev->base_addr + Config) | 2, dev->base_addr + Config);
 }
 
-static inline void clear_loopback(struct device *dev)
+static inline void clear_loopback(struct net_device *dev)
 {
 	outb(inb(dev->base_addr + Config) & ~2, dev->base_addr + Config);
 }
@@ -325,7 +325,7 @@
  * checks for presence of EtherExpress card
  */
 
-int __init express_probe(struct device *dev)
+int __init express_probe(struct net_device *dev)
 {
 	unsigned short *port;
 	static unsigned short ports[] = { 0x300,0x310,0x270,0x320,0x340,0 };
@@ -356,7 +356,7 @@
  * open and initialize the adapter, ready for use
  */
 
-static int eexp_open(struct device *dev)
+static int eexp_open(struct net_device *dev)
 {
 	int irq = dev->irq;
 	unsigned short ioaddr = dev->base_addr;
@@ -397,7 +397,7 @@
  * close and disable the interface, leaving the 586 in reset.
  */
 
-static int eexp_close(struct device *dev)
+static int eexp_close(struct net_device *dev)
 {
 	unsigned short ioaddr = dev->base_addr;
 	struct net_local *lp = dev->priv;
@@ -426,7 +426,7 @@
  * Return interface stats
  */
 
-static struct net_device_stats *eexp_stats(struct device *dev)
+static struct net_device_stats *eexp_stats(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 
@@ -438,7 +438,7 @@
  * nothing has become jammed in the CU.
  */
 
-static void unstick_cu(struct device *dev)
+static void unstick_cu(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	unsigned short ioaddr = dev->base_addr;
@@ -519,7 +519,7 @@
  * Called to transmit a packet, or to allow us to right ourselves
  * if the kernel thinks we've died.
  */
-static int eexp_xmit(struct sk_buff *buf, struct device *dev)
+static int eexp_xmit(struct sk_buff *buf, struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	unsigned long flags;
@@ -601,7 +601,7 @@
  * check to make sure we've not become wedged.
  */
 
-static unsigned short eexp_start_irq(struct device *dev,
+static unsigned short eexp_start_irq(struct net_device *dev,
 				     unsigned short status)
 {
 	unsigned short ack_cmd = SCB_ack(status);
@@ -659,7 +659,7 @@
 	return ack_cmd;
 }
 
-static void eexp_cmd_clear(struct device *dev)
+static void eexp_cmd_clear(struct net_device *dev)
 {
 	unsigned long int oldtime = jiffies;
 	while (scb_rdcmd(dev) && ((jiffies-oldtime)<10));
@@ -670,7 +670,7 @@
 	
 static void eexp_irq(int irq, void *dev_info, struct pt_regs *regs)
 {
-	struct device *dev = dev_info;
+	struct net_device *dev = dev_info;
 	struct net_local *lp;
 	unsigned short ioaddr,status,ack_cmd;
 	unsigned short old_read_ptr, old_write_ptr;
@@ -781,7 +781,7 @@
  * Set the cable type to use.
  */
 
-static void eexp_hw_set_interface(struct device *dev)
+static void eexp_hw_set_interface(struct net_device *dev)
 {
 	unsigned char oldval = inb(dev->base_addr + 0x300e);
 	oldval &= ~0x82;
@@ -802,7 +802,7 @@
  * descriptor, though we don't bother trying to fix broken ones.
  */
 
-static void eexp_hw_rx_pio(struct device *dev)
+static void eexp_hw_rx_pio(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	unsigned short rx_block = lp->rx_ptr;
@@ -897,7 +897,7 @@
  * buffer region.
  */
 
-static void eexp_hw_tx_pio(struct device *dev, unsigned short *buf,
+static void eexp_hw_tx_pio(struct net_device *dev, unsigned short *buf,
 		       unsigned short len)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
@@ -961,7 +961,7 @@
  * than one card in a machine.
  */
 
-static int __init eexp_hw_probe(struct device *dev, unsigned short ioaddr)
+static int __init eexp_hw_probe(struct net_device *dev, unsigned short ioaddr)
 {
 	unsigned short hw_addr[3];
 	unsigned char buswidth;
@@ -1134,7 +1134,7 @@
  * again
  */
 
-static unsigned short eexp_hw_lasttxstat(struct device *dev)
+static unsigned short eexp_hw_lasttxstat(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	unsigned short tx_block = lp->tx_reap;
@@ -1205,7 +1205,7 @@
  * we were working on, or the idle loop if we had finished for the time.
  */
 
-static void eexp_hw_txrestart(struct device *dev)
+static void eexp_hw_txrestart(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	unsigned short ioaddr = dev->base_addr;
@@ -1251,7 +1251,7 @@
  * the 586 command unit is continuously active.
  */
 
-static void eexp_hw_txinit(struct device *dev)
+static void eexp_hw_txinit(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	unsigned short tx_block = TX_BUF_START;
@@ -1293,7 +1293,7 @@
  * "out of resources" messages).
  */
 
-static void eexp_hw_rxinit(struct device *dev)
+static void eexp_hw_rxinit(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	unsigned short rx_block = lp->rx_buf_start;
@@ -1352,7 +1352,7 @@
  * the hardware is configured correctly.
  */
 
-static void eexp_hw_init586(struct device *dev)
+static void eexp_hw_init586(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	unsigned short ioaddr = dev->base_addr;
@@ -1475,7 +1475,7 @@
 	return;
 }
 
-static void eexp_setup_filter(struct device *dev)
+static void eexp_setup_filter(struct net_device *dev)
 {
 	struct dev_mc_list *dmi = dev->mc_list;
 	unsigned short ioaddr = dev->base_addr;
@@ -1512,7 +1512,7 @@
  * Set or clear the multicast filter for this adaptor.
  */
 static void
-eexp_set_multicast(struct device *dev)
+eexp_set_multicast(struct net_device *dev)
 {
         unsigned short ioaddr = dev->base_addr;
         struct net_local *lp = (struct net_local *)dev->priv;
@@ -1564,7 +1564,7 @@
 
 static char namelist[NAMELEN * EEXP_MAX_CARDS] = { 0, };
 
-static struct device dev_eexp[EEXP_MAX_CARDS] =
+static struct net_device dev_eexp[EEXP_MAX_CARDS] =
 {
         { NULL,         /* will allocate dynamically */
 	  0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, express_probe },
@@ -1585,7 +1585,7 @@
 	int this_dev, found = 0;
 
 	for (this_dev = 0; this_dev < EEXP_MAX_CARDS; this_dev++) {
-		struct device *dev = &dev_eexp[this_dev];
+		struct net_device *dev = &dev_eexp[this_dev];
 		dev->name = namelist + (NAMELEN*this_dev);
 		dev->irq = irq[this_dev];
 		dev->base_addr = io[this_dev];
@@ -1608,7 +1608,7 @@
 	int this_dev;
 
 	for (this_dev = 0; this_dev < EEXP_MAX_CARDS; this_dev++) {
-		struct device *dev = &dev_eexp[this_dev];
+		struct net_device *dev = &dev_eexp[this_dev];
 		if (dev->priv != NULL) {
 			unregister_netdev(dev);
 			kfree(dev->priv);
diff -u --recursive --new-file v2.3.13/linux/drivers/net/epic100.c linux/drivers/net/epic100.c
--- v2.3.13/linux/drivers/net/epic100.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/epic100.c	Wed Aug 18 11:36:42 1999
@@ -151,8 +151,8 @@
 
 /* The rest of these values should never change. */
 
-static struct device *epic_probe1(int pci_bus, int pci_devfn,
-								  struct device *dev, long ioaddr, int irq,
+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);
 
 enum pci_flags_bit {
@@ -164,7 +164,7 @@
 	const char *name;
 	u16	vendor_id, device_id, device_id_mask, pci_flags;
 	int io_size, min_latency;
-	struct device *(*probe1)(int pci_bus, int pci_devfn, struct device *dev,
+	struct net_device *(*probe1)(int pci_bus, int pci_devfn, struct net_device *dev,
 							 long ioaddr, int irq, int chip_idx, int fnd_cnt);
 } chip_tbl[] = {
 	{"SMSC EPIC/100 83c170", 0x10B8, 0x0005, 0x7fff,
@@ -217,7 +217,7 @@
 struct epic_private {
 	char devname[8];			/* Used only for kernel debugging. */
 	const char *product_name;
-	struct device *next_module;
+	struct net_device *next_module;
 
 	/* Tx and Rx rings here so that they remain paragraph aligned. */
 	struct epic_rx_desc rx_ring[RX_RING_SIZE];
@@ -253,28 +253,28 @@
 static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
 static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
 
-static int epic_open(struct device *dev);
+static int epic_open(struct net_device *dev);
 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);
-static void epic_restart(struct device *dev);
+static void epic_restart(struct net_device *dev);
 static void epic_timer(unsigned long data);
-static void epic_tx_timeout(struct device *dev);
-static void epic_init_ring(struct device *dev);
-static int epic_start_xmit(struct sk_buff *skb, struct device *dev);
-static int epic_rx(struct device *dev);
+static void epic_tx_timeout(struct net_device *dev);
+static void epic_init_ring(struct net_device *dev);
+static int epic_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int epic_rx(struct net_device *dev);
 static void epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
-static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd);
-static int epic_close(struct device *dev);
-static struct net_device_stats *epic_get_stats(struct device *dev);
-static void set_rx_mode(struct device *dev);
+static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static int epic_close(struct net_device *dev);
+static struct net_device_stats *epic_get_stats(struct net_device *dev);
+static void set_rx_mode(struct net_device *dev);
 
 
 /* A list of all installed EPIC devices, for removing the driver module. */
-static struct device *root_epic_dev = NULL;
+static struct net_device *root_epic_dev = NULL;
 
 #ifndef CARDBUS
-int epic100_probe(struct device *dev)
+int epic100_probe(struct net_device *dev)
 {
 	int cards_found = 0;
 	int chip_idx, irq;
@@ -381,8 +381,8 @@
 }
 #endif  /* not CARDBUS */
 
-static struct device *epic_probe1(int pci_bus, int pci_devfn,
-								  struct device *dev, long ioaddr, int irq,
+static struct net_device *epic_probe1(int pci_bus, int pci_devfn,
+								  struct net_device *dev, long ioaddr, int irq,
 								  int chip_idx, int card_idx)
 {
 	struct epic_private *ep;
@@ -589,7 +589,7 @@
 
 
 static int
-epic_open(struct device *dev)
+epic_open(struct net_device *dev)
 {
 	struct epic_private *ep = (struct epic_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -680,7 +680,7 @@
 
 /* Reset the chip to recover from a PCI transaction error.
    This may occur at interrupt time. */
-static void epic_pause(struct device *dev)
+static void epic_pause(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
 	struct epic_private *ep = (struct epic_private *)dev->priv;
@@ -701,7 +701,7 @@
 	epic_rx(dev);
 }
 
-static void epic_restart(struct device *dev)
+static void epic_restart(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
 	struct epic_private *ep = (struct epic_private *)dev->priv;
@@ -752,7 +752,7 @@
 
 static void epic_timer(unsigned long data)
 {
-	struct device *dev = (struct device *)data;
+	struct net_device *dev = (struct net_device *)data;
 	struct epic_private *ep = (struct epic_private *)dev->priv;
 	long ioaddr = dev->base_addr;
 	int next_tick = 0;
@@ -784,7 +784,7 @@
 	}
 }
 
-static void epic_tx_timeout(struct device *dev)
+static void epic_tx_timeout(struct net_device *dev)
 {
 	struct epic_private *ep = (struct epic_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -815,7 +815,7 @@
 
 /* Initialize the Rx and Tx rings, along with various 'dev' bits. */
 static void
-epic_init_ring(struct device *dev)
+epic_init_ring(struct net_device *dev)
 {
 	struct epic_private *ep = (struct epic_private *)dev->priv;
 	int i;
@@ -856,7 +856,7 @@
 }
 
 static int
-epic_start_xmit(struct sk_buff *skb, struct device *dev)
+epic_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct epic_private *ep = (struct epic_private *)dev->priv;
 	int entry;
@@ -920,7 +920,7 @@
    after the Tx thread. */
 static void epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 {
-	struct device *dev = (struct device *)dev_instance;
+	struct net_device *dev = (struct net_device *)dev_instance;
 	struct epic_private *ep = (struct epic_private *)dev->priv;
 	long ioaddr = dev->base_addr;
 	int status, boguscnt = max_interrupt_work;
@@ -1063,7 +1063,7 @@
 	return;
 }
 
-static int epic_rx(struct device *dev)
+static int epic_rx(struct net_device *dev)
 {
 	struct epic_private *ep = (struct epic_private *)dev->priv;
 	int entry = ep->cur_rx % RX_RING_SIZE;
@@ -1139,7 +1139,7 @@
 	return work_done;
 }
 
-static int epic_close(struct device *dev)
+static int epic_close(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
 	struct epic_private *ep = (struct epic_private *)dev->priv;
@@ -1195,7 +1195,7 @@
 	return 0;
 }
 
-static struct net_device_stats *epic_get_stats(struct device *dev)
+static struct net_device_stats *epic_get_stats(struct net_device *dev)
 {
 	struct epic_private *ep = (struct epic_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -1237,7 +1237,7 @@
 }
 
 
-static void set_rx_mode(struct device *dev)
+static void set_rx_mode(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
 	struct epic_private *ep = (struct epic_private *)dev->priv;
@@ -1276,7 +1276,7 @@
 	return;
 }
 
-static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd)
+static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	long ioaddr = dev->base_addr;
 	u16 *data = (u16 *)&rq->ifr_data;
@@ -1325,7 +1325,7 @@
 
 static dev_node_t *epic_attach(dev_locator_t *loc)
 {
-	struct device *dev;
+	struct net_device *dev;
 	u16 dev_id;
 	u32 io;
 	u8 bus, devfn, irq;
@@ -1357,7 +1357,7 @@
 
 static void epic_suspend(dev_node_t *node)
 {
-	struct device **devp, **next;
+	struct net_device **devp, **next;
 	printk(KERN_INFO "epic_suspend(%s)\n", node->dev_name);
 	for (devp = &root_epic_dev; *devp; devp = next) {
 		next = &((struct epic_private *)(*devp)->priv)->next_module;
@@ -1372,7 +1372,7 @@
 }
 static void epic_resume(dev_node_t *node)
 {
-	struct device **devp, **next;
+	struct net_device **devp, **next;
 	printk(KERN_INFO "epic_resume(%s)\n", node->dev_name);
 	for (devp = &root_epic_dev; *devp; devp = next) {
 		next = &((struct epic_private *)(*devp)->priv)->next_module;
@@ -1384,7 +1384,7 @@
 }
 static void epic_detach(dev_node_t *node)
 {
-	struct device **devp, **next;
+	struct net_device **devp, **next;
 	printk(KERN_INFO "epic_detach(%s)\n", node->dev_name);
 	for (devp = &root_epic_dev; *devp; devp = next) {
 		next = &((struct epic_private *)(*devp)->priv)->next_module;
@@ -1423,7 +1423,7 @@
 
 void cleanup_module(void)
 {
-	struct device *next_dev;
+	struct net_device *next_dev;
 
 #ifdef CARDBUS
 	unregister_driver(&epic_ops);
diff -u --recursive --new-file v2.3.13/linux/drivers/net/eql.c linux/drivers/net/eql.c
--- v2.3.13/linux/drivers/net/eql.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/eql.c	Wed Aug 18 11:36:42 1999
@@ -150,27 +150,27 @@
 #endif
 static unsigned int eql_debug = EQL_DEBUG;
 
-int        eql_init(struct device *dev); /*  */
-static int eql_open(struct device *dev); /*  */
-static int eql_close(struct device *dev); /*  */
-static int eql_ioctl(struct device *dev, struct ifreq *ifr, int cmd); /*  */
-static int eql_slave_xmit(struct sk_buff *skb, struct device *dev); /*  */
+int        eql_init(struct net_device *dev); /*  */
+static int eql_open(struct net_device *dev); /*  */
+static int eql_close(struct net_device *dev); /*  */
+static int eql_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); /*  */
+static int eql_slave_xmit(struct sk_buff *skb, struct net_device *dev); /*  */
 
-static struct net_device_stats *eql_get_stats(struct device *dev); /*  */
+static struct net_device_stats *eql_get_stats(struct net_device *dev); /*  */
 
 /* ioctl() handlers
    ---------------- */
-static int eql_enslave(struct device *dev,  slaving_request_t *srq); /*  */
-static int eql_emancipate(struct device *dev, slaving_request_t *srq); /*  */
+static int eql_enslave(struct net_device *dev,  slaving_request_t *srq); /*  */
+static int eql_emancipate(struct net_device *dev, slaving_request_t *srq); /*  */
 
-static int eql_g_slave_cfg(struct device *dev, slave_config_t *sc); /*  */
-static int eql_s_slave_cfg(struct device *dev, slave_config_t *sc); /*  */
+static int eql_g_slave_cfg(struct net_device *dev, slave_config_t *sc); /*  */
+static int eql_s_slave_cfg(struct net_device *dev, slave_config_t *sc); /*  */
 
-static int eql_g_master_cfg(struct device *dev, master_config_t *mc); /*  */
-static int eql_s_master_cfg(struct device *dev, master_config_t *mc); /*  */
+static int eql_g_master_cfg(struct net_device *dev, master_config_t *mc); /*  */
+static int eql_s_master_cfg(struct net_device *dev, master_config_t *mc); /*  */
 
-static inline int eql_is_slave(struct device *dev); /*  */
-static inline int eql_is_master(struct device *dev); /*  */
+static inline int eql_is_slave(struct net_device *dev); /*  */
+static inline int eql_is_master(struct net_device *dev); /*  */
 
 static slave_t *eql_new_slave(void); /*  */
 static void eql_delete_slave(slave_t *slave); /*  */
@@ -181,16 +181,16 @@
 static inline int eql_is_empty(slave_queue_t *queue); /*  */
 static inline int eql_is_full(slave_queue_t *queue); /*  */
 
-static slave_queue_t *eql_new_slave_queue(struct device *dev); /*  */
+static slave_queue_t *eql_new_slave_queue(struct net_device *dev); /*  */
 static void eql_delete_slave_queue(slave_queue_t *queue); /*  */
 
 static int eql_insert_slave(slave_queue_t *queue, slave_t *slave); /*  */
 static slave_t *eql_remove_slave(slave_queue_t *queue, slave_t *slave); /*  */
 
-/* static int eql_insert_slave_dev(slave_queue_t *queue, struct device *dev); -*  */
-static int eql_remove_slave_dev(slave_queue_t *queue, struct device *dev); /*  */
+/* static int eql_insert_slave_dev(slave_queue_t *queue, struct net_device *dev); -*  */
+static int eql_remove_slave_dev(slave_queue_t *queue, struct net_device *dev); /*  */
 
-static inline struct device *eql_best_slave_dev(slave_queue_t *queue); /*  */
+static inline struct net_device *eql_best_slave_dev(slave_queue_t *queue); /*  */
 static inline slave_t *eql_best_slave(slave_queue_t *queue); /*  */
 static inline slave_t *eql_first_slave(slave_queue_t *queue); /*  */
 static inline slave_t *eql_next_slave(slave_queue_t *queue, slave_t *slave); /*  */
@@ -198,18 +198,18 @@
 static inline void eql_set_best_slave(slave_queue_t *queue, slave_t *slave); /*  */
 static inline void eql_schedule_slaves(slave_queue_t *queue); /*  */
 
-static slave_t *eql_find_slave_dev(slave_queue_t *queue, struct device *dev); /*  */
+static slave_t *eql_find_slave_dev(slave_queue_t *queue, struct net_device *dev); /*  */
 
 /* static inline eql_lock_slave_queue(slave_queue_t *queue); -*  */
 /* static inline eql_unlock_slave_queue(slave_queue_t *queue); -*  */
 
 static void eql_timer(unsigned long param);	/*  */
 
-/* struct device * interface functions 
+/* struct net_device * interface functions 
    ---------------------------------------------------------
    */
 
-int __init eql_init(struct device *dev)
+int __init eql_init(struct net_device *dev)
 {
 	static unsigned version_printed = 0;
 	/* static unsigned num_masters     = 0; */
@@ -268,7 +268,7 @@
 	return 0;
 }
 
-static int eql_open(struct device *dev)
+static int eql_open(struct net_device *dev)
 {
 	equalizer_t *eql = (equalizer_t *) dev->priv;
 	slave_queue_t *new_queue;
@@ -301,7 +301,7 @@
 }
 
 
-static int eql_close(struct device *dev)
+static int eql_close(struct net_device *dev)
 {
 	equalizer_t *eql = (equalizer_t *) dev->priv;
 
@@ -327,7 +327,7 @@
 }
 
 
-static int eql_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
+static int eql_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {  
 	if(cmd!=EQL_GETMASTRCFG && cmd!=EQL_GETSLAVECFG && 
 	   !capable(CAP_NET_ADMIN))
@@ -352,10 +352,10 @@
 }
 
 
-static int eql_slave_xmit(struct sk_buff *skb, struct device *dev)
+static int eql_slave_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	equalizer_t *eql = (equalizer_t *) dev->priv;
-	struct device *slave_dev = 0;
+	struct net_device *slave_dev = 0;
 	slave_t *slave;
 
 	if (skb == NULL)
@@ -394,7 +394,7 @@
 }
 
 
-static struct net_device_stats * eql_get_stats(struct device *dev)
+static struct net_device_stats * eql_get_stats(struct net_device *dev)
 {
 	equalizer_t *eql = (equalizer_t *) dev->priv;
 	return eql->stats;
@@ -404,10 +404,10 @@
  *	Private ioctl functions
  */
 
-static int eql_enslave(struct device *dev, slaving_request_t *srqp)
+static int eql_enslave(struct net_device *dev, slaving_request_t *srqp)
 {
-	struct device *master_dev;
-	struct device *slave_dev;
+	struct net_device *master_dev;
+	struct net_device *slave_dev;
 	slaving_request_t srq;
 	int err;
 
@@ -465,10 +465,10 @@
 	return -EINVAL;
 }
 
-static int eql_emancipate(struct device *dev, slaving_request_t *srqp)
+static int eql_emancipate(struct net_device *dev, slaving_request_t *srqp)
 {
-	struct device *master_dev;
-	struct device *slave_dev;
+	struct net_device *master_dev;
+	struct net_device *slave_dev;
 	slaving_request_t srq;
 	int err;
 
@@ -494,11 +494,11 @@
 }
 
 
-static int eql_g_slave_cfg(struct device *dev, slave_config_t *scp)
+static int eql_g_slave_cfg(struct net_device *dev, slave_config_t *scp)
 {
 	slave_t *slave;
 	equalizer_t *eql;
-	struct device *slave_dev;
+	struct net_device *slave_dev;
 	slave_config_t sc;
 	int err;
 
@@ -530,11 +530,11 @@
 }
 
 
-static int eql_s_slave_cfg(struct device *dev, slave_config_t *scp)
+static int eql_s_slave_cfg(struct net_device *dev, slave_config_t *scp)
 {
 	slave_t *slave;
 	equalizer_t *eql;
-	struct device *slave_dev;
+	struct net_device *slave_dev;
 	slave_config_t sc;
 	int err;
 
@@ -566,7 +566,7 @@
 }
 
 
-static int eql_g_master_cfg(struct device *dev, master_config_t *mcp)
+static int eql_g_master_cfg(struct net_device *dev, master_config_t *mcp)
 {
 	equalizer_t *eql;
 	master_config_t mc;
@@ -591,7 +591,7 @@
 }
 
 
-static int eql_s_master_cfg(struct device *dev, master_config_t *mcp)
+static int eql_s_master_cfg(struct net_device *dev, master_config_t *mcp)
 {
 	equalizer_t *eql;
 	master_config_t mc;
@@ -618,7 +618,7 @@
  *	Private device support functions
  */
 
-static inline int eql_is_slave(struct device *dev)
+static inline int eql_is_slave(struct net_device *dev)
 {
 	if (dev)
 	{
@@ -629,7 +629,7 @@
 }
 
 
-static inline int eql_is_master(struct device *dev)
+static inline int eql_is_master(struct net_device *dev)
 {
 	if (dev)
 	{
@@ -695,7 +695,7 @@
 	return 0;
 }
 
-static slave_queue_t *eql_new_slave_queue(struct device *dev)
+static slave_queue_t *eql_new_slave_queue(struct net_device *dev)
 {
 	slave_queue_t *queue;
 	slave_t *head_slave;
@@ -804,7 +804,7 @@
 }
 
 
-static int eql_remove_slave_dev(slave_queue_t *queue, struct device *dev)
+static int eql_remove_slave_dev(slave_queue_t *queue, struct net_device *dev)
 {
 	slave_t *prev;
 	slave_t *curr;
@@ -832,7 +832,7 @@
 }
 
 
-static inline struct device *eql_best_slave_dev(slave_queue_t *queue)
+static inline struct net_device *eql_best_slave_dev(slave_queue_t *queue)
 {
 	if (queue->best_slave != 0)
 	{
@@ -853,7 +853,7 @@
 
 static inline void eql_schedule_slaves(slave_queue_t *queue)
 {
-	struct device *master_dev = queue->master_dev;
+	struct net_device *master_dev = queue->master_dev;
 	slave_t *best_slave = 0;
 	slave_t *slave_corpse = 0;
 
@@ -937,7 +937,7 @@
 }
 
 
-static slave_t * eql_find_slave_dev(slave_queue_t *queue, struct device *dev)
+static slave_t * eql_find_slave_dev(slave_queue_t *queue, struct net_device *dev)
 {
 	slave_t *slave = 0;
 	slave = eql_first_slave(queue);
@@ -1014,7 +1014,7 @@
 }
 
 #ifdef MODULE
-static struct device dev_eql = 
+static struct net_device dev_eql = 
 {
 	"eql", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, eql_init 
 };
diff -u --recursive --new-file v2.3.13/linux/drivers/net/es3210.c linux/drivers/net/es3210.c
--- v2.3.13/linux/drivers/net/es3210.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/es3210.c	Wed Aug 18 11:36:42 1999
@@ -61,17 +61,17 @@
 #include <linux/etherdevice.h>
 #include "8390.h"
 
-int es_probe(struct device *dev);
-int es_probe1(struct device *dev, int ioaddr);
+int es_probe(struct net_device *dev);
+int es_probe1(struct net_device *dev, int ioaddr);
 
-static int es_open(struct device *dev);
-static int es_close(struct device *dev);
+static int es_open(struct net_device *dev);
+static int es_close(struct net_device *dev);
 
-static void es_reset_8390(struct device *dev);
+static void es_reset_8390(struct net_device *dev);
 
-static void es_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page);
-static void es_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset);
-static void es_block_output(struct device *dev, int count, const unsigned char *buf, int start_page);
+static void es_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page);
+static void es_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset);
+static void es_block_output(struct net_device *dev, int count, const unsigned char *buf, int start_page);
 
 #define ES_START_PG	0x00    /* First page of TX buffer		*/
 #define ES_STOP_PG	0x40    /* Last page +1 of RX ring		*/
@@ -124,7 +124,7 @@
  *	PROM for a match against the Racal-Interlan assigned value.
  */
 
-int __init es_probe(struct device *dev)
+int __init es_probe(struct net_device *dev)
 {
 	unsigned short ioaddr = dev->base_addr;
 
@@ -151,7 +151,7 @@
 	return ENODEV;
 }
 
-int __init es_probe1(struct device *dev, int ioaddr)
+int __init es_probe1(struct net_device *dev, int ioaddr)
 {
 	int i;
 	unsigned long eisa_id;
@@ -284,7 +284,7 @@
  *	file, this just toggles the "Board Enable" bits (bit 2 and 0).
  */
 
-static void es_reset_8390(struct device *dev)
+static void es_reset_8390(struct net_device *dev)
 {
 	unsigned short ioaddr = dev->base_addr;
 	unsigned long end;
@@ -318,7 +318,7 @@
  */
 
 static void
-es_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+es_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 {
 	unsigned long hdr_start = dev->mem_start + ((ring_page - ES_START_PG)<<8);
 	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
@@ -331,7 +331,7 @@
  *	be rounded up to a doubleword value via es_get_8390_hdr() above.
  */
 
-static void es_block_input(struct device *dev, int count, struct sk_buff *skb,
+static void es_block_input(struct net_device *dev, int count, struct sk_buff *skb,
 						  int ring_offset)
 {
 	unsigned long xfer_start = dev->mem_start + ring_offset - (ES_START_PG<<8);
@@ -348,7 +348,7 @@
 	}
 }
 
-static void es_block_output(struct device *dev, int count,
+static void es_block_output(struct net_device *dev, int count,
 				const unsigned char *buf, int start_page)
 {
 	unsigned long shmem = dev->mem_start + ((start_page - ES_START_PG)<<8);
@@ -357,7 +357,7 @@
 	memcpy_toio(shmem, buf, count);
 }
 
-static int es_open(struct device *dev)
+static int es_open(struct net_device *dev)
 {
 	ei_open(dev);
 
@@ -366,7 +366,7 @@
 	return 0;
 }
 
-static int es_close(struct device *dev)
+static int es_close(struct net_device *dev)
 {
 
 	if (ei_debug > 1)
@@ -383,7 +383,7 @@
 #define MAX_ES_CARDS	4	/* Max number of ES3210 cards per module */
 #define NAMELEN		8	/* # of chars for storing dev->name */
 static char namelist[NAMELEN * MAX_ES_CARDS] = { 0, };
-static struct device dev_es3210[MAX_ES_CARDS] = {
+static struct net_device dev_es3210[MAX_ES_CARDS] = {
 	{
 		NULL,		/* assign a chunk of namelist[] below */
 		0, 0, 0, 0,
@@ -406,7 +406,7 @@
 	int this_dev, found = 0;
 
 	for (this_dev = 0; this_dev < MAX_ES_CARDS; this_dev++) {
-		struct device *dev = &dev_es3210[this_dev];
+		struct net_device *dev = &dev_es3210[this_dev];
 		dev->name = namelist+(NAMELEN*this_dev);
 		dev->irq = irq[this_dev];
 		dev->base_addr = io[this_dev];
@@ -434,7 +434,7 @@
 	int this_dev;
 
 	for (this_dev = 0; this_dev < MAX_ES_CARDS; this_dev++) {
-		struct device *dev = &dev_es3210[this_dev];
+		struct net_device *dev = &dev_es3210[this_dev];
 		if (dev->priv != NULL) {
 			void *priv = dev->priv;
 			free_irq(dev->irq, dev);
diff -u --recursive --new-file v2.3.13/linux/drivers/net/eth16i.c linux/drivers/net/eth16i.c
--- v2.3.13/linux/drivers/net/eth16i.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/eth16i.c	Wed Aug 18 11:36:42 1999
@@ -407,9 +407,9 @@
 
 /* Function prototypes */
 
-extern int     eth16i_probe(struct device *dev);
+extern int     eth16i_probe(struct net_device *dev);
 
-static int     eth16i_probe1(struct device *dev, int ioaddr);
+static int     eth16i_probe1(struct net_device *dev, int ioaddr);
 static int     eth16i_check_signature(int ioaddr);
 static int     eth16i_probe_port(int ioaddr);
 static void    eth16i_set_port(int ioaddr, int porttype);
@@ -419,26 +419,26 @@
 static int     eth16i_read_eeprom(int ioaddr, int offset);
 static int     eth16i_read_eeprom_word(int ioaddr);
 static void    eth16i_eeprom_cmd(int ioaddr, unsigned char command);
-static int     eth16i_open(struct device *dev);
-static int     eth16i_close(struct device *dev);
-static int     eth16i_tx(struct sk_buff *skb, struct device *dev);
-static void    eth16i_rx(struct device *dev);
+static int     eth16i_open(struct net_device *dev);
+static int     eth16i_close(struct net_device *dev);
+static int     eth16i_tx(struct sk_buff *skb, struct net_device *dev);
+static void    eth16i_rx(struct net_device *dev);
 static void    eth16i_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void    eth16i_reset(struct device *dev);
-static void    eth16i_skip_packet(struct device *dev);
-static void    eth16i_multicast(struct device *dev); 
+static void    eth16i_reset(struct net_device *dev);
+static void    eth16i_skip_packet(struct net_device *dev);
+static void    eth16i_multicast(struct net_device *dev); 
 static void    eth16i_select_regbank(unsigned char regbank, int ioaddr);
-static void    eth16i_initialize(struct device *dev);
+static void    eth16i_initialize(struct net_device *dev);
 
 #if 0
-static int     eth16i_set_irq(struct device *dev);
+static int     eth16i_set_irq(struct net_device *dev);
 #endif
 
 #ifdef MODULE
 static ushort  eth16i_parse_mediatype(const char* s);
 #endif
 
-static struct enet_statistics *eth16i_get_stats(struct device *dev);
+static struct enet_statistics *eth16i_get_stats(struct net_device *dev);
 
 static char *cardname = "ICL EtherTeam 16i/32";
 
@@ -450,7 +450,7 @@
 
 #else  /* Not HAVE_DEVLIST */
 
-int __init eth16i_probe(struct device *dev)
+int __init eth16i_probe(struct net_device *dev)
 {
 	int i;
 	int ioaddr;
@@ -484,7 +484,7 @@
 }
 #endif  /* Not HAVE_DEVLIST */
 
-static int __init eth16i_probe1(struct device *dev, int ioaddr)
+static int __init eth16i_probe1(struct net_device *dev, int ioaddr)
 {
 	static unsigned version_printed = 0;
 	boot = 1;  /* To inform initilization that we are in boot probe */
@@ -593,7 +593,7 @@
 }
 
 
-static void eth16i_initialize(struct device *dev)
+static void eth16i_initialize(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr;
 	int i, node_w = 0;
@@ -824,7 +824,7 @@
 }
 
 #if 0
-static int eth16i_set_irq(struct device* dev)
+static int eth16i_set_irq(struct net_device* dev)
 {
 	const int ioaddr = dev->base_addr;
 	const int irq = dev->irq;
@@ -966,7 +966,7 @@
 	} 
 }
 
-static int eth16i_open(struct device *dev)
+static int eth16i_open(struct net_device *dev)
 {
 	struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -1007,7 +1007,7 @@
 	return 0;
 }
 
-static int eth16i_close(struct device *dev)
+static int eth16i_close(struct net_device *dev)
 {
 	struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -1036,7 +1036,7 @@
 	return 0;
 }
 
-static int eth16i_tx(struct sk_buff *skb, struct device *dev)
+static int eth16i_tx(struct sk_buff *skb, struct net_device *dev)
 {
 	struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -1185,7 +1185,7 @@
 	return status;
 }
 
-static void eth16i_rx(struct device *dev)
+static void eth16i_rx(struct net_device *dev)
 {
 	struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -1300,7 +1300,7 @@
 
 static void eth16i_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	struct eth16i_local *lp;
 	int ioaddr = 0,
 		status;
@@ -1406,7 +1406,7 @@
 	return;
 }
 
-static void eth16i_skip_packet(struct device *dev)
+static void eth16i_skip_packet(struct net_device *dev)
 {	 
 	int ioaddr = dev->base_addr;
 
@@ -1418,7 +1418,7 @@
 	while( inb( ioaddr + FILTER_SELF_RX_REG ) != 0);
 }
 
-static void eth16i_reset(struct device *dev)
+static void eth16i_reset(struct net_device *dev)
 {
 	struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -1441,7 +1441,7 @@
 	BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
 }
 
-static void eth16i_multicast(struct device *dev)
+static void eth16i_multicast(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr;
   
@@ -1454,7 +1454,7 @@
 	}
 }
 
-static struct enet_statistics *eth16i_get_stats(struct device *dev)
+static struct enet_statistics *eth16i_get_stats(struct net_device *dev)
 {
 	struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
 
@@ -1492,7 +1492,7 @@
 #define NAMELEN          8  /* number of chars for storing dev->name */
 
 static char namelist[NAMELEN * MAX_ETH16I_CARDS] = { 0, };
-static struct device dev_eth16i[MAX_ETH16I_CARDS] = {
+static struct net_device dev_eth16i[MAX_ETH16I_CARDS] = {
 	{
 		NULL,
 		0, 0, 0, 0,
@@ -1533,7 +1533,7 @@
 
 	for(this_dev = 0; this_dev < MAX_ETH16I_CARDS; this_dev++)
 	{
-		struct device *dev = &dev_eth16i[this_dev];
+		struct net_device *dev = &dev_eth16i[this_dev];
 	
 		dev->name = namelist + (NAMELEN*this_dev);
 		dev->irq = 0; /* irq[this_dev]; */
@@ -1575,7 +1575,7 @@
 
 	for(this_dev = 0; this_dev < MAX_ETH16I_CARDS; this_dev++)
 	{
-		struct device* dev = &dev_eth16i[this_dev];
+		struct net_device* dev = &dev_eth16i[this_dev];
 		
 		if(dev->priv != NULL)
 		{
diff -u --recursive --new-file v2.3.13/linux/drivers/net/ethertap.c linux/drivers/net/ethertap.c
--- v2.3.13/linux/drivers/net/ethertap.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/ethertap.c	Wed Aug 18 11:36:42 1999
@@ -33,19 +33,19 @@
  *	Index to functions.
  */
 
-int	    ethertap_probe(struct device *dev);
-static int  ethertap_open(struct device *dev);
-static int  ethertap_start_xmit(struct sk_buff *skb, struct device *dev);
-static int  ethertap_close(struct device *dev);
-static struct net_device_stats *ethertap_get_stats(struct device *dev);
+int	    ethertap_probe(struct net_device *dev);
+static int  ethertap_open(struct net_device *dev);
+static int  ethertap_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int  ethertap_close(struct net_device *dev);
+static struct net_device_stats *ethertap_get_stats(struct net_device *dev);
 static void ethertap_rx(struct sock *sk, int len);
 #ifdef CONFIG_ETHERTAP_MC
-static void set_multicast_list(struct device *dev);
+static void set_multicast_list(struct net_device *dev);
 #endif
 
 static int ethertap_debug = 0;
 
-static struct device *tap_map[32];	/* Returns the tap device for a given netlink */
+static struct net_device *tap_map[32];	/* Returns the tap device for a given netlink */
 
 /*
  *	Board-specific info in dev->priv.
@@ -65,7 +65,7 @@
  *	hardware it would have to check what was present.
  */
  
-int __init ethertap_probe(struct device *dev)
+int __init ethertap_probe(struct net_device *dev)
 {
 	memcpy(dev->dev_addr, "\xFE\xFD\x00\x00\x00\x00", 6);
 	if (dev->mem_start & 0xf)
@@ -109,7 +109,7 @@
  *	Open/initialize the board.
  */
 
-static int ethertap_open(struct device *dev)
+static int ethertap_open(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local*)dev->priv;
 
@@ -142,7 +142,7 @@
 	return 1U << (idx&0x1F);
 }
 
-static void set_multicast_list(struct device *dev)
+static void set_multicast_list(struct net_device *dev)
 {
 	unsigned groups = ~0;
 	struct net_local *lp = (struct net_local *)dev->priv;
@@ -169,7 +169,7 @@
  *	it for 2.0 so that we dev_kfree_skb() the locked original.
  */
  
-static int ethertap_start_xmit(struct sk_buff *skb, struct device *dev)
+static int ethertap_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 #ifdef CONFIG_ETHERTAP_MC
@@ -227,7 +227,7 @@
 	return 0;
 }
 
-static __inline__ int ethertap_rx_skb(struct sk_buff *skb, struct device *dev)
+static __inline__ int ethertap_rx_skb(struct sk_buff *skb, struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 #ifdef CONFIG_ETHERTAP_MC
@@ -295,7 +295,7 @@
 
 static void ethertap_rx(struct sock *sk, int len)
 {
-	struct device *dev = tap_map[sk->protocol];
+	struct net_device *dev = tap_map[sk->protocol];
 	struct sk_buff *skb;
 
 	if (dev==NULL) {
@@ -311,7 +311,7 @@
 		ethertap_rx_skb(skb, dev);
 }
 
-static int ethertap_close(struct device *dev)
+static int ethertap_close(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	struct sock *sk = lp->nl;
@@ -331,7 +331,7 @@
 	return 0;
 }
 
-static struct net_device_stats *ethertap_get_stats(struct device *dev)
+static struct net_device_stats *ethertap_get_stats(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	return &lp->stats;
@@ -344,7 +344,7 @@
 
 static char devicename[9] = { 0, };
 
-static struct device dev_ethertap =
+static struct net_device dev_ethertap =
 {
 	devicename,
 	0, 0, 0, 0,
diff -u --recursive --new-file v2.3.13/linux/drivers/net/ewrk3.c linux/drivers/net/ewrk3.c
--- v2.3.13/linux/drivers/net/ewrk3.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/ewrk3.c	Wed Aug 18 11:36:42 1999
@@ -288,36 +288,36 @@
 /*
    ** Public Functions
  */
-static int ewrk3_open(struct device *dev);
-static int ewrk3_queue_pkt(struct sk_buff *skb, struct device *dev);
+static int ewrk3_open(struct net_device *dev);
+static int ewrk3_queue_pkt(struct sk_buff *skb, struct net_device *dev);
 static void ewrk3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static int ewrk3_close(struct device *dev);
-static struct net_device_stats *ewrk3_get_stats(struct device *dev);
-static void set_multicast_list(struct device *dev);
-static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd);
+static int ewrk3_close(struct net_device *dev);
+static struct net_device_stats *ewrk3_get_stats(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
+static int ewrk3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 
 /*
    ** Private functions
  */
-static int ewrk3_hw_init(struct device *dev, u_long iobase);
-static void ewrk3_init(struct device *dev);
-static int ewrk3_rx(struct device *dev);
-static int ewrk3_tx(struct device *dev);
+static int ewrk3_hw_init(struct net_device *dev, u_long iobase);
+static void ewrk3_init(struct net_device *dev);
+static int ewrk3_rx(struct net_device *dev);
+static int ewrk3_tx(struct net_device *dev);
 
 static void EthwrkSignature(char *name, char *eeprom_image);
 static int DevicePresent(u_long iobase);
-static void SetMulticastFilter(struct device *dev);
+static void SetMulticastFilter(struct net_device *dev);
 static int EISA_signature(char *name, s32 eisa_id);
 
 static int Read_EEPROM(u_long iobase, u_char eaddr);
 static int Write_EEPROM(short data, u_long iobase, u_char eaddr);
-static u_char get_hw_addr(struct device *dev, u_char * eeprom_image, char chipType);
+static u_char get_hw_addr(struct net_device *dev, u_char * eeprom_image, char chipType);
 
-static void isa_probe(struct device *dev, u_long iobase);
-static void eisa_probe(struct device *dev, u_long iobase);
-static struct device *alloc_device(struct device *dev, u_long iobase);
+static void isa_probe(struct net_device *dev, u_long iobase);
+static void eisa_probe(struct net_device *dev, u_long iobase);
+static struct net_device *alloc_device(struct net_device *dev, u_long iobase);
 static int ewrk3_dev_index(char *s);
-static struct device *insert_device(struct device *dev, u_long iobase, int (*init) (struct device *));
+static struct net_device *insert_device(struct net_device *dev, u_long iobase, int (*init) (struct net_device *));
 
 
 #ifdef MODULE
@@ -343,7 +343,7 @@
     mdelay(1);\
 }
 
-int __init ewrk3_probe(struct device *dev)
+int __init ewrk3_probe(struct net_device *dev)
 {
 	int tmp = num_ewrk3s, status = -ENODEV;
 	u_long iobase = dev->base_addr;
@@ -376,7 +376,7 @@
 }
 
 static int __init 
-ewrk3_hw_init(struct device *dev, u_long iobase)
+ewrk3_hw_init(struct net_device *dev, u_long iobase)
 {
 	struct ewrk3_private *lp;
 	int i, status = 0;
@@ -621,7 +621,7 @@
 }
 
 
-static int ewrk3_open(struct device *dev)
+static int ewrk3_open(struct net_device *dev)
 {
 	struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
 	u_long iobase = dev->base_addr;
@@ -690,7 +690,7 @@
 /*
    ** Initialize the EtherWORKS 3 operating conditions
  */
-static void ewrk3_init(struct device *dev)
+static void ewrk3_init(struct net_device *dev)
 {
 	struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
 	u_char csr, page;
@@ -724,7 +724,7 @@
 /*
    ** Writes a socket buffer to the free page queue
  */
-static int ewrk3_queue_pkt(struct sk_buff *skb, struct device *dev)
+static int ewrk3_queue_pkt(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
 	u_long iobase = dev->base_addr;
@@ -873,7 +873,7 @@
  */
 static void ewrk3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	struct ewrk3_private *lp;
 	u_long iobase;
 	u_char icr, cr, csr;
@@ -934,7 +934,7 @@
 	return;
 }
 
-static int ewrk3_rx(struct device *dev)
+static int ewrk3_rx(struct net_device *dev)
 {
 	struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
 	u_long iobase = dev->base_addr;
@@ -1078,7 +1078,7 @@
 /*
    ** Buffer sent - check for TX buffer errors.
  */
-static int ewrk3_tx(struct device *dev)
+static int ewrk3_tx(struct net_device *dev)
 {
 	struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
 	u_long iobase = dev->base_addr;
@@ -1114,7 +1114,7 @@
 	return 0;
 }
 
-static int ewrk3_close(struct device *dev)
+static int ewrk3_close(struct net_device *dev)
 {
 	struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
 	u_long iobase = dev->base_addr;
@@ -1152,7 +1152,7 @@
 	return 0;
 }
 
-static struct net_device_stats *ewrk3_get_stats(struct device *dev)
+static struct net_device_stats *ewrk3_get_stats(struct net_device *dev)
 {
 	struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
 
@@ -1163,7 +1163,7 @@
 /*
    ** Set or clear the multicast filter for this adapter.
  */
-static void set_multicast_list(struct device *dev)
+static void set_multicast_list(struct net_device *dev)
 {
 	struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
 	u_long iobase = dev->base_addr;
@@ -1196,7 +1196,7 @@
    ** Note that when clearing the table, the broadcast bit must remain asserted
    ** to receive broadcast messages.
  */
-static void SetMulticastFilter(struct device *dev)
+static void SetMulticastFilter(struct net_device *dev)
 {
 	struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
 	struct dev_mc_list *dmi = dev->mc_list;
@@ -1282,7 +1282,7 @@
 /*
    ** ISA bus I/O device probe
  */
-static void __init isa_probe(struct device *dev, u_long ioaddr)
+static void __init isa_probe(struct net_device *dev, u_long ioaddr)
 {
 	int i = num_ewrk3s, maxSlots;
 	u_long iobase;
@@ -1322,7 +1322,7 @@
    ** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually
    ** the motherboard.
  */
-static void __init eisa_probe(struct device *dev, u_long ioaddr)
+static void __init eisa_probe(struct net_device *dev, u_long ioaddr)
 {
 	int i, maxSlots;
 	u_long iobase;
@@ -1369,10 +1369,10 @@
    ** are not available then insert a new device structure at the end of
    ** the current list.
  */
-static struct device * __init 
-alloc_device(struct device *dev, u_long iobase)
+static struct net_device * __init 
+alloc_device(struct net_device *dev, u_long iobase)
 {
-	struct device *adev = NULL;
+	struct net_device *adev = NULL;
 	int fixed = 0, new_dev = 0;
 
 	num_eth = ewrk3_dev_index(dev->name);
@@ -1414,12 +1414,12 @@
    ** If at end of eth device list and can't use current entry, malloc
    ** one up. If memory could not be allocated, print an error message.
  */
-static __init struct device *
-insert_device(struct device *dev, u_long iobase, int (*init) (struct device *))
+static __init struct net_device *
+insert_device(struct net_device *dev, u_long iobase, int (*init) (struct net_device *))
 {
-	struct device *new;
+	struct net_device *new;
 
-	new = (struct device *) kmalloc(sizeof(struct device) + 8, GFP_KERNEL);
+	new = (struct net_device *) kmalloc(sizeof(struct net_device) + 8, GFP_KERNEL);
 	if (new == NULL) {
 		printk("eth%d: Device not initialised, insufficient memory\n", num_eth);
 		return NULL;
@@ -1570,7 +1570,7 @@
 	return status;
 }
 
-static u_char __init get_hw_addr(struct device *dev, u_char * eeprom_image, char chipType)
+static u_char __init get_hw_addr(struct net_device *dev, u_char * eeprom_image, char chipType)
 {
 	int i, j, k;
 	u_short chksum;
@@ -1658,7 +1658,7 @@
    ** Perform IOCTL call functions here. Some are privileged operations and the
    ** effective uid is checked in those cases.
  */
-static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
+static int ewrk3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
 	struct ewrk3_ioctl *ioc = (struct ewrk3_ioctl *) &rq->ifr_data;
@@ -1879,7 +1879,7 @@
 #ifdef MODULE
 static char devicename[9] =
 {0,};
-static struct device thisEthwrk =
+static struct net_device thisEthwrk =
 {
 	devicename,		/* device name is inserted by /linux/drivers/net/net_init.c */
 	0, 0, 0, 0,
diff -u --recursive --new-file v2.3.13/linux/drivers/net/fmv18x.c linux/drivers/net/fmv18x.c
--- v2.3.13/linux/drivers/net/fmv18x.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/fmv18x.c	Wed Aug 18 11:36:42 1999
@@ -108,16 +108,16 @@
 
 /* Index to functions, as function prototypes. */
 
-extern int fmv18x_probe(struct device *dev);
+extern int fmv18x_probe(struct net_device *dev);
 
-static int fmv18x_probe1(struct device *dev, short ioaddr);
-static int net_open(struct device *dev);
-static int	net_send_packet(struct sk_buff *skb, struct device *dev);
+static int fmv18x_probe1(struct net_device *dev, short ioaddr);
+static int net_open(struct net_device *dev);
+static int	net_send_packet(struct sk_buff *skb, struct net_device *dev);
 static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void net_rx(struct device *dev);
-static int net_close(struct device *dev);
-static struct net_device_stats *net_get_stats(struct device *dev);
-static void set_multicast_list(struct device *dev);
+static void net_rx(struct net_device *dev);
+static int net_close(struct net_device *dev);
+static struct net_device_stats *net_get_stats(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
 
 
 /* Check for a network adaptor of this type, and return '0' iff one exists.
@@ -133,7 +133,7 @@
 {"fmv18x", fmv18x_probe1, FMV18X_IO_EXTENT, fmv18x_probe_list};
 #else
 int __init 
-fmv18x_probe(struct device *dev)
+fmv18x_probe(struct net_device *dev)
 {
 	int i;
 	int base_addr = dev ? dev->base_addr : 0;
@@ -163,7 +163,7 @@
    that can be done is checking a few bits and then diving right into MAC
    address check. */
 
-int __init fmv18x_probe1(struct device *dev, short ioaddr)
+int __init fmv18x_probe1(struct net_device *dev, short ioaddr)
 {
 	char irqmap[4] = {3, 7, 10, 15};
 	char irqmap_pnp[8] = {3, 4, 5, 7, 9, 10, 11, 15};
@@ -287,7 +287,7 @@
 }
 
 
-static int net_open(struct device *dev)
+static int net_open(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -326,7 +326,7 @@
 }
 
 static int
-net_send_packet(struct sk_buff *skb, struct device *dev)
+net_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -420,7 +420,7 @@
 static void
 net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	struct net_local *lp;
 	int ioaddr, status;
 
@@ -483,7 +483,7 @@
 
 /* We have a good packet(s), get it/them out of the buffers. */
 static void
-net_rx(struct device *dev)
+net_rx(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -572,7 +572,7 @@
 }
 
 /* The inverse routine to net_open(). */
-static int net_close(struct device *dev)
+static int net_close(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr;
 
@@ -599,7 +599,7 @@
 
 /* Get the current statistics.	This may be called with the card open or
    closed. */
-static struct net_device_stats *net_get_stats(struct device *dev)
+static struct net_device_stats *net_get_stats(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 
@@ -617,7 +617,7 @@
 			best-effort filtering.
  */
  
-static void set_multicast_list(struct device *dev)
+static void set_multicast_list(struct net_device *dev)
 {
 	short ioaddr = dev->base_addr;
 	if (dev->mc_count || dev->flags&(IFF_PROMISC|IFF_ALLMULTI))
@@ -637,7 +637,7 @@
 
 #ifdef MODULE
 static char devicename[9] = { 0, };
-static struct device dev_fmv18x = {
+static struct net_device dev_fmv18x = {
 	devicename, /* device name is inserted by linux/drivers/net/net_init.c */
 	0, 0, 0, 0,
 	0, 0,
diff -u --recursive --new-file v2.3.13/linux/drivers/net/hamradio/6pack.c linux/drivers/net/hamradio/6pack.c
--- v2.3.13/linux/drivers/net/hamradio/6pack.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/hamradio/6pack.c	Wed Aug 18 11:38:51 1999
@@ -53,7 +53,7 @@
 typedef struct sixpack_ctrl {
 	char		if_name[8];	/* "sp0\0" .. "sp99999\0"	*/
 	struct sixpack	ctrl;		/* 6pack things			*/
-	struct device	dev;		/* the device			*/
+	struct net_device	dev;		/* the device			*/
 } sixpack_ctrl_t;
 static sixpack_ctrl_t	**sixpack_ctrls = NULL;
 int sixpack_maxdev = SIXP_NRUNIT;	/* Can be overridden with insmod! */
@@ -327,7 +327,7 @@
 /* Encapsulate an IP datagram and kick it into a TTY queue. */
 
 static int
-sp_xmit(struct sk_buff *skb, struct device *dev)
+sp_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct sixpack *sp = (struct sixpack*)(dev->priv);
 
@@ -382,7 +382,7 @@
 /* #if defined(CONFIG_6PACK) || defined(CONFIG_6PACK_MODULE) */
 
 /* Return the frame type ID */
-static int sp_header(struct sk_buff *skb, struct device *dev, unsigned short type,
+static int sp_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
 	  void *daddr, void *saddr, unsigned len)
 {
 #ifdef CONFIG_INET
@@ -406,7 +406,7 @@
 
 /* Open the low-level part of the 6pack channel. */
 static int
-sp_open(struct device *dev)
+sp_open(struct net_device *dev)
 {
 	struct sixpack *sp = (struct sixpack*)(dev->priv);
 	unsigned long len;
@@ -469,7 +469,7 @@
 
 /* Close the low-level part of the 6pack channel. */
 static int
-sp_close(struct device *dev)
+sp_close(struct net_device *dev)
 {
 	struct sixpack *sp = (struct sixpack*)(dev->priv);
 
@@ -612,7 +612,7 @@
 
 
 static struct net_device_stats *
-sp_get_stats(struct device *dev)
+sp_get_stats(struct net_device *dev)
 {
 	static struct net_device_stats stats;
 	struct sixpack *sp = (struct sixpack*)(dev->priv);
@@ -633,7 +633,7 @@
 
 
 int
-sp_set_mac_address(struct device *dev, void *addr)
+sp_set_mac_address(struct net_device *dev, void *addr)
 {
 	int err;
 
@@ -648,7 +648,7 @@
 }
 
 static int
-sp_set_dev_mac_address(struct device *dev, void *addr)
+sp_set_dev_mac_address(struct net_device *dev, void *addr)
 {
 	struct sockaddr *sa=addr;
 	memcpy(dev->dev_addr, sa->sa_data, AX25_ADDR_LEN);
@@ -713,7 +713,7 @@
 	}
 }
 
-static int sp_open_dev(struct device *dev)
+static int sp_open_dev(struct net_device *dev)
 {
 	struct sixpack *sp = (struct sixpack*)(dev->priv);
 	if(sp->tty==NULL)
@@ -726,7 +726,7 @@
 #ifdef MODULE
 static int sixpack_init_ctrl_dev(void)
 #else	/* !MODULE */
-int __init sixpack_init_ctrl_dev(struct device *dummy)
+int __init sixpack_init_ctrl_dev(struct net_device *dummy)
 #endif	/* !MODULE */
 {
 	int status;
@@ -778,7 +778,7 @@
 
 /* Initialize the 6pack driver.  Called by DDI. */
 int
-sixpack_init(struct device *dev)
+sixpack_init(struct net_device *dev)
 {
 	struct sixpack *sp = (struct sixpack*)(dev->priv);
 
diff -u --recursive --new-file v2.3.13/linux/drivers/net/hamradio/6pack.h linux/drivers/net/hamradio/6pack.h
--- v2.3.13/linux/drivers/net/hamradio/6pack.h	Wed Apr  8 17:31:27 1998
+++ linux/drivers/net/hamradio/6pack.h	Wed Aug 18 11:38:51 1999
@@ -70,7 +70,7 @@
 
   /* Various fields. */
   struct tty_struct	*tty;		/* ptr to TTY structure		*/
-  struct device		*dev;		/* easy for intr handling	*/
+  struct net_device		*dev;		/* easy for intr handling	*/
 
   /* These are pointers to the malloc()ed frame buffers. */
   unsigned char		*rbuff;		/* receiver buffer		*/
@@ -128,7 +128,7 @@
 #define AX25_6PACK_HEADER_LEN 0
 #define SIXPACK_MAGIC 0x5304
 
-extern int sixpack_init(struct device *dev);
+extern int sixpack_init(struct net_device *dev);
 
 #endif
 
diff -u --recursive --new-file v2.3.13/linux/drivers/net/hamradio/Config.in linux/drivers/net/hamradio/Config.in
--- v2.3.13/linux/drivers/net/hamradio/Config.in	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/hamradio/Config.in	Thu Aug 12 12:18:32 1999
@@ -11,12 +11,13 @@
   bool '   support for TRX that feedback the tx signal to rx' CONFIG_SCC_TRXECHO
 fi
     
-tristate 'BAYCOM ser12 fullduplex driver for AX.25' CONFIG_BAYCOM_SER_FDX
-tristate 'BAYCOM ser12 halfduplex driver for AX.25' CONFIG_BAYCOM_SER_HDX
-dep_tristate 'BAYCOM picpar and par96 driver for AX.25' CONFIG_BAYCOM_PAR $CONFIG_PARPORT
-dep_tristate 'BAYCOM epp driver for AX.25' CONFIG_BAYCOM_EPP $CONFIG_PARPORT
+dep_tristate 'BAYCOM ser12 fullduplex driver for AX.25' CONFIG_BAYCOM_SER_FDX $CONFIG_AX25
+dep_tristate 'BAYCOM ser12 halfduplex driver for AX.25' CONFIG_BAYCOM_SER_HDX $CONFIG_AX25
+dep_tristate 'BAYCOM picpar and par96 driver for AX.25' CONFIG_BAYCOM_PAR $CONFIG_PARPORT $CONFIG_AX25
+dep_tristate 'BAYCOM epp driver for AX.25' CONFIG_BAYCOM_EPP $CONFIG_PARPORT $CONFIG_AX25
+dep_tristate 'BAYCOM eppflex driver for AX.25' CONFIG_BAYCOM_EPPFLEX $CONFIG_PARPORT $CONFIG_AX25
 
-dep_tristate 'Soundcard modem driver' CONFIG_SOUNDMODEM $CONFIG_PARPORT
+dep_tristate 'Soundcard modem driver' CONFIG_SOUNDMODEM $CONFIG_PARPORT $CONFIG_AX25
 if [ "$CONFIG_SOUNDMODEM" != "n" ]; then
   bool '   soundmodem support for Soundblaster and compatible cards' CONFIG_SOUNDMODEM_SBC
   bool '   soundmodem support for WSS and Crystal cards' CONFIG_SOUNDMODEM_WSS
diff -u --recursive --new-file v2.3.13/linux/drivers/net/hamradio/Makefile linux/drivers/net/hamradio/Makefile
--- v2.3.13/linux/drivers/net/hamradio/Makefile	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/hamradio/Makefile	Thu Aug 12 12:19:41 1999
@@ -11,8 +11,8 @@
 MOD_SUB_DIRS := $(SUB_DIRS)
 ALL_SUB_DIRS := $(SUB_DIRS)
 
-L_TARGET := hamradio.a
-L_OBJS   := 
+O_TARGET := hamradio.o
+O_OBJS   := 
 M_OBJS   :=
 MOD_LIST_NAME := HAM_MODULES
 
@@ -22,7 +22,7 @@
 CONFIG_HDLCDRV_MODULE  :=
 
 ifeq ($(CONFIG_DMASCC),y)
-L_OBJS += dmascc.o
+O_OBJS += dmascc.o
 else
   ifeq ($(CONFIG_DMASCC),m)
   M_OBJS += dmascc.o
@@ -30,7 +30,7 @@
 endif
 
 ifeq ($(CONFIG_SCC),y)
-L_OBJS += scc.o
+O_OBJS += scc.o
 else
   ifeq ($(CONFIG_SCC),m)
   M_OBJS += scc.o
@@ -38,7 +38,7 @@
 endif
 
 ifeq ($(CONFIG_MKISS),y)
-L_OBJS += mkiss.o
+O_OBJS += mkiss.o
 else
   ifeq ($(CONFIG_MKISS),m)
   M_OBJS += mkiss.o
@@ -46,7 +46,7 @@
 endif
 
 ifeq ($(CONFIG_6PACK),y)
-L_OBJS += 6pack.o
+O_OBJS += 6pack.o
 else
   ifeq ($(CONFIG_6PACK),m)
   M_OBJS += 6pack.o
@@ -54,7 +54,7 @@
 endif
 
 ifeq ($(CONFIG_YAM),y)
-L_OBJS += yam.o
+O_OBJS += yam.o
 else
   ifeq ($(CONFIG_YAM),m)
   M_OBJS += yam.o
@@ -62,7 +62,7 @@
 endif
 
 ifeq ($(CONFIG_PI),y)
-L_OBJS += pi2.o
+O_OBJS += pi2.o
 else
   ifeq ($(CONFIG_PI),m)
   M_OBJS += pi2.o
@@ -70,7 +70,7 @@
 endif
 
 ifeq ($(CONFIG_PT),y)
-L_OBJS += pt.o
+O_OBJS += pt.o
 else
   ifeq ($(CONFIG_PT),m)
   M_OBJS += pt.o
@@ -78,7 +78,7 @@
 endif
 
 ifeq ($(CONFIG_BPQETHER),y)
-L_OBJS += bpqether.o
+O_OBJS += bpqether.o
 else
   ifeq ($(CONFIG_BPQETHER),m)
   M_OBJS += bpqether.o
@@ -86,7 +86,7 @@
 endif
 
 ifeq ($(CONFIG_BAYCOM_SER_FDX),y)
-L_OBJS += baycom_ser_fdx.o
+O_OBJS += baycom_ser_fdx.o
 CONFIG_HDLCDRV_BUILTIN = y
 else
   ifeq ($(CONFIG_BAYCOM_SER_FDX),m)
@@ -96,7 +96,7 @@
 endif
 
 ifeq ($(CONFIG_BAYCOM_SER_HDX),y)
-L_OBJS += baycom_ser_hdx.o
+O_OBJS += baycom_ser_hdx.o
 CONFIG_HDLCDRV_BUILTIN = y
 else
   ifeq ($(CONFIG_BAYCOM_SER_HDX),m)
@@ -106,7 +106,7 @@
 endif
 
 ifeq ($(CONFIG_BAYCOM_PAR),y)
-L_OBJS += baycom_par.o
+O_OBJS += baycom_par.o
 CONFIG_HDLCDRV_BUILTIN = y
 else
   ifeq ($(CONFIG_BAYCOM_PAR),m)
@@ -116,7 +116,7 @@
 endif
 
 ifeq ($(CONFIG_BAYCOM_EPP),y)
-L_OBJS += baycom_epp.o
+O_OBJS += baycom_epp.o
 CONFIG_HDLCDRV_BUILTIN = y
 else
   ifeq ($(CONFIG_BAYCOM_EPP),m)
@@ -128,7 +128,7 @@
 ifeq ($(CONFIG_SOUNDMODEM),y)
 ALL_SUB_DIRS += soundmodem
 SUB_DIRS += soundmodem
-L_OBJS += soundmodem/soundmodem.o
+O_OBJS += soundmodem/soundmodem.o
 CONFIG_HDLCDRV_BUILTIN = y
 else
   ifeq ($(CONFIG_SOUNDMODEM),m)
@@ -141,7 +141,7 @@
 # If anything built-in uses the hdlcdrv, then build it into the kernel also.
 # If not, but a module uses it, build as a module.
 ifdef CONFIG_HDLCDRV_BUILTIN
-LX_OBJS += hdlcdrv.o
+OX_OBJS += hdlcdrv.o
 else
   ifdef CONFIG_HDLCDRV_MODULE
   MX_OBJS += hdlcdrv.o
diff -u --recursive --new-file v2.3.13/linux/drivers/net/hamradio/baycom_epp.c linux/drivers/net/hamradio/baycom_epp.c
--- v2.3.13/linux/drivers/net/hamradio/baycom_epp.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/hamradio/baycom_epp.c	Wed Aug 18 11:38:51 1999
@@ -95,7 +95,7 @@
 
 #define NR_PORTS 4
 
-static struct device baycom_device[NR_PORTS];
+static struct net_device baycom_device[NR_PORTS];
 
 /* --------------------------------------------------------------------- */
 
@@ -698,7 +698,7 @@
 
 /* ---------------------------------------------------------------------- */
 
-static void do_rxpacket(struct device *dev)
+static void do_rxpacket(struct net_device *dev)
 {
 	struct baycom_state *bc = (struct baycom_state *)dev->priv;
 	struct sk_buff *skb;
@@ -756,7 +756,7 @@
         goto enditer##j;                                                               \
 })
         
-static int receive(struct device *dev, int cnt)
+static int receive(struct net_device *dev, int cnt)
 {
 	struct baycom_state *bc = (struct baycom_state *)dev->priv;
 	struct parport *pp = bc->pdev->port;
@@ -832,7 +832,7 @@
 #define GETTICK(x)
 #endif /* __i386__ */
 
-static void epp_bh(struct device *dev)
+static void epp_bh(struct net_device *dev)
 {
 	struct baycom_state *bc;
 	struct parport *pp;
@@ -953,7 +953,7 @@
  * ===================== network driver interface =========================
  */
 
-static int baycom_send_packet(struct sk_buff *skb, struct device *dev)
+static int baycom_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
 	struct baycom_state *bc;
 
@@ -966,7 +966,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int baycom_set_mac_address(struct device *dev, void *addr)
+static int baycom_set_mac_address(struct net_device *dev, void *addr)
 {
 	struct sockaddr *sa = (struct sockaddr *)addr;
 
@@ -977,7 +977,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static struct net_device_stats *baycom_get_stats(struct device *dev)
+static struct net_device_stats *baycom_get_stats(struct net_device *dev)
 {
 	struct baycom_state *bc;
 
@@ -994,7 +994,7 @@
 
 static void epp_wakeup(void *handle)
 {
-        struct device *dev = (struct device *)handle;
+        struct net_device *dev = (struct net_device *)handle;
         struct baycom_state *bc;
 
 	baycom_paranoia_check_void(dev, "epp_wakeup");
@@ -1015,7 +1015,7 @@
  * there is non-reboot way to recover if something goes wrong.
  */
 
-static int epp_open(struct device *dev)
+static int epp_open(struct net_device *dev)
 {
 	struct baycom_state *bc;
         struct parport *pp;
@@ -1141,7 +1141,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int epp_close(struct device *dev)
+static int epp_close(struct net_device *dev)
 {
 	struct baycom_state *bc;
 	struct parport *pp;
@@ -1209,7 +1209,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int baycom_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
+static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	struct baycom_state *bc;
 	struct baycom_ioctl bi;
@@ -1348,7 +1348,7 @@
  * If dev->base_addr == 2, allocate space for the device and return success
  * (detachable devices only).
  */
-static int baycom_probe(struct device *dev)
+static int baycom_probe(struct net_device *dev)
 {
 	static char ax25_bcast[AX25_ADDR_LEN] = {
 		'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1
@@ -1425,7 +1425,7 @@
 #endif
 int __init init_module(void)
 {
-	struct device *dev;
+	struct net_device *dev;
 	int i, found = 0;
 	char set_hw = 1;
 	struct baycom_state *bc;
@@ -1440,7 +1440,7 @@
 			set_hw = 0;
 		if (!set_hw)
 			iobase[i] = 0;
-		memset(dev, 0, sizeof(struct device));
+		memset(dev, 0, sizeof(struct net_device));
 		if (!(bc = dev->priv = kmalloc(sizeof(struct baycom_state), GFP_KERNEL)))
 			return -ENOMEM;
 		/*
@@ -1490,7 +1490,7 @@
 
 void cleanup_module(void)
 {
-	struct device *dev;
+	struct net_device *dev;
 	struct baycom_state *bc;
 	int i;
 
diff -u --recursive --new-file v2.3.13/linux/drivers/net/hamradio/baycom_par.c linux/drivers/net/hamradio/baycom_par.c
--- v2.3.13/linux/drivers/net/hamradio/baycom_par.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/hamradio/baycom_par.c	Wed Aug 18 11:38:50 1999
@@ -105,7 +105,7 @@
 
 #define NR_PORTS 4
 
-static struct device baycom_device[NR_PORTS];
+static struct net_device baycom_device[NR_PORTS];
 
 /* --------------------------------------------------------------------- */
 
@@ -202,7 +202,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static __inline__ void par96_tx(struct device *dev, struct baycom_state *bc)
+static __inline__ void par96_tx(struct net_device *dev, struct baycom_state *bc)
 {
 	int i;
 	unsigned int data = hdlcdrv_getbits(&bc->hdrv);
@@ -225,7 +225,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static __inline__ void par96_rx(struct device *dev, struct baycom_state *bc)
+static __inline__ void par96_rx(struct net_device *dev, struct baycom_state *bc)
 {
 	int i;
 	unsigned int data, mask, mask2, descx;
@@ -279,7 +279,7 @@
 
 static void par96_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev = (struct device *)dev_id;
+	struct net_device *dev = (struct net_device *)dev_id;
 	struct baycom_state *bc = (struct baycom_state *)dev->priv;
 
 	if (!dev || !bc || bc->hdrv.magic != HDLCDRV_MAGIC)
@@ -309,7 +309,7 @@
 
 static void par96_wakeup(void *handle)
 {
-        struct device *dev = (struct device *)handle;
+        struct net_device *dev = (struct net_device *)handle;
 	struct baycom_state *bc = (struct baycom_state *)dev->priv;
 
 	printk(KERN_DEBUG "baycom_par: %s: why am I being woken up?\n", dev->name);
@@ -319,7 +319,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int par96_open(struct device *dev)
+static int par96_open(struct net_device *dev)
 {
 	struct baycom_state *bc = (struct baycom_state *)dev->priv;
 	struct parport *pp = parport_enumerate();
@@ -363,7 +363,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int par96_close(struct device *dev)
+static int par96_close(struct net_device *dev)
 {
 	struct baycom_state *bc = (struct baycom_state *)dev->priv;
 
@@ -387,7 +387,7 @@
  * ===================== hdlcdrv driver interface =========================
  */
 
-static int baycom_ioctl(struct device *dev, struct ifreq *ifr,
+static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr,
 			struct hdlcdrv_ioctl *hi, int cmd);
 
 /* --------------------------------------------------------------------- */
@@ -415,7 +415,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int baycom_ioctl(struct device *dev, struct ifreq *ifr,
+static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr,
 			struct hdlcdrv_ioctl *hi, int cmd)
 {
 	struct baycom_state *bc;
@@ -506,7 +506,7 @@
 	 * register net devices
 	 */
 	for (i = 0; i < NR_PORTS; i++) {
-		struct device *dev = baycom_device+i;
+		struct net_device *dev = baycom_device+i;
 		sprintf(ifname, "bcp%d", i);
 
 		if (!mode[i])
@@ -547,7 +547,7 @@
 	int i;
 
 	for(i = 0; i < NR_PORTS; i++) {
-		struct device *dev = baycom_device+i;
+		struct net_device *dev = baycom_device+i;
 		struct baycom_state *bc = (struct baycom_state *)dev->priv;
 
 		if (bc) {
diff -u --recursive --new-file v2.3.13/linux/drivers/net/hamradio/baycom_ser_fdx.c linux/drivers/net/hamradio/baycom_ser_fdx.c
--- v2.3.13/linux/drivers/net/hamradio/baycom_ser_fdx.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/hamradio/baycom_ser_fdx.c	Wed Aug 18 11:38:50 1999
@@ -94,7 +94,7 @@
 
 #define NR_PORTS 4
 
-static struct device baycom_device[NR_PORTS];
+static struct net_device baycom_device[NR_PORTS];
 
 /* --------------------------------------------------------------------- */
 
@@ -181,7 +181,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static inline void ser12_set_divisor(struct device *dev,
+static inline void ser12_set_divisor(struct net_device *dev,
                                      unsigned int divisor)
 {
         outb(0x81, LCR(dev->base_addr));        /* DLAB = 1 */
@@ -228,7 +228,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static __inline__ void ser12_rx(struct device *dev, struct baycom_state *bc, struct timeval *tv, unsigned char curs)
+static __inline__ void ser12_rx(struct net_device *dev, struct baycom_state *bc, struct timeval *tv, unsigned char curs)
 {
 	int timediff;
 	int bdus8 = bc->baud_us >> 3;
@@ -285,7 +285,7 @@
 
 static void ser12_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev = (struct device *)dev_id;
+	struct net_device *dev = (struct net_device *)dev_id;
 	struct baycom_state *bc = (struct baycom_state *)dev->priv;
 	struct timeval tv;
 	unsigned char iir, msr;
@@ -409,7 +409,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int ser12_open(struct device *dev)
+static int ser12_open(struct net_device *dev)
 {
 	struct baycom_state *bc = (struct baycom_state *)dev->priv;
 	enum uart u;
@@ -464,7 +464,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int ser12_close(struct device *dev)
+static int ser12_close(struct net_device *dev)
 {
 	struct baycom_state *bc = (struct baycom_state *)dev->priv;
 
@@ -490,7 +490,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int baycom_ioctl(struct device *dev, struct ifreq *ifr,
+static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr,
 			struct hdlcdrv_ioctl *hi, int cmd);
 
 /* --------------------------------------------------------------------- */
@@ -520,7 +520,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int baycom_ioctl(struct device *dev, struct ifreq *ifr,
+static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr,
 			struct hdlcdrv_ioctl *hi, int cmd)
 {
 	struct baycom_state *bc;
@@ -616,7 +616,7 @@
 	 * register net devices
 	 */
 	for (i = 0; i < NR_PORTS; i++) {
-		struct device *dev = baycom_device+i;
+		struct net_device *dev = baycom_device+i;
 		sprintf(ifname, "bcsf%d", i);
 
 		if (!mode[i])
@@ -662,7 +662,7 @@
 	int i;
 
 	for(i = 0; i < NR_PORTS; i++) {
-		struct device *dev = baycom_device+i;
+		struct net_device *dev = baycom_device+i;
 		struct baycom_state *bc = (struct baycom_state *)dev->priv;
 
 		if (bc) {
diff -u --recursive --new-file v2.3.13/linux/drivers/net/hamradio/baycom_ser_hdx.c linux/drivers/net/hamradio/baycom_ser_hdx.c
--- v2.3.13/linux/drivers/net/hamradio/baycom_ser_hdx.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/hamradio/baycom_ser_hdx.c	Wed Aug 18 11:38:50 1999
@@ -83,7 +83,7 @@
 
 #define NR_PORTS 4
 
-static struct device baycom_device[NR_PORTS];
+static struct net_device baycom_device[NR_PORTS];
 
 /* --------------------------------------------------------------------- */
 
@@ -169,7 +169,7 @@
  * ===================== SER12 specific routines =========================
  */
 
-static void inline ser12_set_divisor(struct device *dev,
+static void inline ser12_set_divisor(struct net_device *dev,
 				     unsigned char divisor)
 {
 	outb(0x81, LCR(dev->base_addr));	/* DLAB = 1 */
@@ -200,7 +200,7 @@
 #define SER12_DCD_INTERVAL(bc) ((bc->options & BAYCOM_OPTIONS_SOFTDCD) ? \
 				240 : 12)
 
-static inline void ser12_tx(struct device *dev, struct baycom_state *bc)
+static inline void ser12_tx(struct net_device *dev, struct baycom_state *bc)
 {
 	/* one interrupt per channel bit */
 	ser12_set_divisor(dev, 12);
@@ -218,7 +218,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static inline void ser12_rx(struct device *dev, struct baycom_state *bc)
+static inline void ser12_rx(struct net_device *dev, struct baycom_state *bc)
 {
 	unsigned char cur_s;
 	/*
@@ -376,7 +376,7 @@
 
 static void ser12_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev = (struct device *)dev_id;
+	struct net_device *dev = (struct net_device *)dev_id;
 	struct baycom_state *bc = (struct baycom_state *)dev->priv;
 	unsigned char iir;
 
@@ -467,7 +467,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int ser12_open(struct device *dev)
+static int ser12_open(struct net_device *dev)
 {
 	struct baycom_state *bc = (struct baycom_state *)dev->priv;
 	enum uart u;
@@ -509,7 +509,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int ser12_close(struct device *dev)
+static int ser12_close(struct net_device *dev)
 {
 	struct baycom_state *bc = (struct baycom_state *)dev->priv;
 
@@ -535,7 +535,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int baycom_ioctl(struct device *dev, struct ifreq *ifr,
+static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr,
 			struct hdlcdrv_ioctl *hi, int cmd);
 
 /* --------------------------------------------------------------------- */
@@ -558,7 +558,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int baycom_ioctl(struct device *dev, struct ifreq *ifr,
+static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr,
 			struct hdlcdrv_ioctl *hi, int cmd)
 {
 	struct baycom_state *bc;
@@ -653,7 +653,7 @@
 	 * register net devices
 	 */
 	for (i = 0; i < NR_PORTS; i++) {
-		struct device *dev = baycom_device+i;
+		struct net_device *dev = baycom_device+i;
 		sprintf(ifname, "bcsh%d", i);
 
 		if (!mode[i])
@@ -696,7 +696,7 @@
 	int i;
 
 	for(i = 0; i < NR_PORTS; i++) {
-		struct device *dev = baycom_device+i;
+		struct net_device *dev = baycom_device+i;
 		struct baycom_state *bc = (struct baycom_state *)dev->priv;
 
 		if (bc) {
diff -u --recursive --new-file v2.3.13/linux/drivers/net/hamradio/bpqether.c linux/drivers/net/hamradio/bpqether.c
--- v2.3.13/linux/drivers/net/hamradio/bpqether.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/hamradio/bpqether.c	Wed Aug 18 11:38:50 1999
@@ -95,7 +95,7 @@
 
 static char bpq_eth_addr[6];
 
-static int bpq_rcv(struct sk_buff *, struct device *, struct packet_type *);
+static int bpq_rcv(struct sk_buff *, struct net_device *, struct packet_type *);
 static int bpq_device_event(struct notifier_block *, unsigned long, void *);
 static char *bpq_print_ethaddr(unsigned char *);
 
@@ -118,8 +118,8 @@
 static struct bpqdev {
 	struct bpqdev *next;
 	char   ethname[14];		/* ether device name */
-	struct device *ethdev;		/* link to ethernet device */
-	struct device axdev;		/* bpq device (bpq#) */
+	struct net_device *ethdev;		/* link to ethernet device */
+	struct net_device axdev;		/* bpq device (bpq#) */
 	struct net_device_stats stats;	/* some statistics */
 	char   dest_addr[6];		/* ether destination address */
 	char   acpt_addr[6];		/* accept ether frames from this address only */
@@ -132,7 +132,7 @@
 /*
  *	Get the ethernet device for a BPQ device
  */
-static __inline__ struct device *bpq_get_ether_dev(struct device *dev)
+static __inline__ struct net_device *bpq_get_ether_dev(struct net_device *dev)
 {
 	struct bpqdev *bpq;
 
@@ -144,7 +144,7 @@
 /*
  *	Get the BPQ device for the ethernet device
  */
-static __inline__ struct device *bpq_get_ax25_dev(struct device *dev)
+static __inline__ struct net_device *bpq_get_ax25_dev(struct net_device *dev)
 {
 	struct bpqdev *bpq;
 
@@ -155,7 +155,7 @@
 	return NULL;
 }
 
-static __inline__ int dev_is_ethdev(struct device *dev)
+static __inline__ int dev_is_ethdev(struct net_device *dev)
 {
 	return (
 			dev->type == ARPHRD_ETHER
@@ -167,7 +167,7 @@
  *	Sanity check: remove all devices that ceased to exists and
  *	return '1' if the given BPQ device was affected.
  */
-static int bpq_check_devices(struct device *dev)
+static int bpq_check_devices(struct net_device *dev)
 {
 	struct bpqdev *bpq, *bpq_prev;
 	int result = 0;
@@ -211,7 +211,7 @@
 /*
  *	Receive an AX.25 frame via an ethernet interface.
  */
-static int bpq_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *ptype)
+static int bpq_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype)
 {
 	int len;
 	char * ptr;
@@ -264,7 +264,7 @@
 /*
  * 	Send an AX.25 frame via an ethernet interface
  */
-static int bpq_xmit(struct sk_buff *skb, struct device *dev)
+static int bpq_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct sk_buff *newskb;
 	unsigned char *ptr;
@@ -331,7 +331,7 @@
 /*
  *	Statistics
  */
-static struct net_device_stats *bpq_get_stats(struct device *dev)
+static struct net_device_stats *bpq_get_stats(struct net_device *dev)
 {
 	struct bpqdev *bpq;
 
@@ -343,7 +343,7 @@
 /*
  *	Set AX.25 callsign
  */
-static int bpq_set_mac_address(struct device *dev, void *addr)
+static int bpq_set_mac_address(struct net_device *dev, void *addr)
 {
     struct sockaddr *sa = (struct sockaddr *)addr;
 
@@ -359,7 +359,7 @@
  *					source ethernet address (broadcast
  *					or multicast: accept all)
  */
-static int bpq_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
+static int bpq_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	int err;
 	struct bpq_ethaddr *ethaddr = (struct bpq_ethaddr *)ifr->ifr_data;
@@ -403,7 +403,7 @@
 /*
  * open/close a device
  */
-static int bpq_open(struct device *dev)
+static int bpq_open(struct net_device *dev)
 {
 	if (bpq_check_devices(dev))
 		return -ENODEV;		/* oops, it's gone */
@@ -416,7 +416,7 @@
 	return 0;
 }
 
-static int bpq_close(struct device *dev)
+static int bpq_close(struct net_device *dev)
 {
 	dev->tbusy = 1;
 	dev->start = 0;
@@ -429,7 +429,7 @@
 /*
  * currently unused
  */
-static int bpq_dev_init(struct device *dev)
+static int bpq_dev_init(struct net_device *dev)
 {
 	return 0;
 }
@@ -498,7 +498,7 @@
 /*
  *	Setup a new device.
  */
-static int bpq_new_device(struct device *dev)
+static int bpq_new_device(struct net_device *dev)
 {
 	int k;
 	unsigned char *buf;
@@ -521,7 +521,7 @@
 	buf = kmalloc(14, GFP_KERNEL);
 
 	for (k = 0; k < MAXBPQDEV; k++) {
-		struct device *odev;
+		struct net_device *odev;
 
 		sprintf(buf, "bpq%d", k);
 
@@ -589,7 +589,7 @@
  */
 static int bpq_device_event(struct notifier_block *this,unsigned long event, void *ptr)
 {
-	struct device *dev = (struct device *)ptr;
+	struct net_device *dev = (struct net_device *)ptr;
 
 	if (!dev_is_ethdev(dev))
 		return NOTIFY_DONE;
@@ -623,7 +623,7 @@
  */
 int __init bpq_init(void)
 {
-	struct device *dev;
+	struct net_device *dev;
 
 	bpq_packet_type.type  = htons(ETH_P_BPQ);
 	dev_add_pack(&bpq_packet_type);
diff -u --recursive --new-file v2.3.13/linux/drivers/net/hamradio/dmascc.c linux/drivers/net/hamradio/dmascc.c
--- v2.3.13/linux/drivers/net/hamradio/dmascc.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/hamradio/dmascc.c	Wed Aug 18 11:38:51 1999
@@ -71,12 +71,12 @@
 #define RXFIFOH 0x08
 #define TXFIFOE 0x20
 
-static int dmascc_dev_init(struct device *dev)
+static int dmascc_dev_init(struct net_device *dev)
 {
   return 0;
 }
 
-static void dev_init_buffers(struct device *dev)
+static void dev_init_buffers(struct net_device *dev)
 {
   int i;
 
@@ -239,7 +239,7 @@
   int scc_base;
   int tmr_base;
   int twin_serial_cfg;
-  struct device dev[2];
+  struct net_device dev[2];
   struct scc_priv priv[2];
   struct scc_info *next;
 };
@@ -252,21 +252,21 @@
 
 static inline void write_scc(int ctl, int reg, int val);
 static inline int read_scc(int ctl, int reg);
-static int scc_open(struct device *dev);
-static int scc_close(struct device *dev);
-static int scc_ioctl(struct device *dev, struct ifreq *ifr, int cmd);
-static int scc_send_packet(struct sk_buff *skb, struct device *dev);
-static struct enet_statistics *scc_get_stats(struct device *dev);
-static int scc_set_mac_address(struct device *dev, void *sa);
+static int scc_open(struct net_device *dev);
+static int scc_close(struct net_device *dev);
+static int scc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
+static int scc_send_packet(struct sk_buff *skb, struct net_device *dev);
+static struct enet_statistics *scc_get_stats(struct net_device *dev);
+static int scc_set_mac_address(struct net_device *dev, void *sa);
 static void scc_isr(int irq, void *dev_id, struct pt_regs * regs);
 static inline void z8530_isr(struct scc_info *info);
-static void rx_isr(struct device *dev);
-static void special_condition(struct device *dev, int rc);
+static void rx_isr(struct net_device *dev);
+static void special_condition(struct net_device *dev, int rc);
 static void rx_bh(void *arg);
-static void tx_isr(struct device *dev);
-static void es_isr(struct device *dev);
-static void tm_isr(struct device *dev);
-static inline void delay(struct device *dev, int t);
+static void tx_isr(struct net_device *dev);
+static void es_isr(struct net_device *dev);
+static void tm_isr(struct net_device *dev);
+static inline void delay(struct net_device *dev, int t);
 static inline unsigned char random(void);
 
 
@@ -457,7 +457,7 @@
 {
   int i, irq, chip;
   struct scc_info *info;
-  struct device *dev;
+  struct net_device *dev;
   struct scc_priv *priv;
   unsigned long time;
   unsigned int irqs;
@@ -623,7 +623,7 @@
 }
 
 
-static int scc_open(struct device *dev)
+static int scc_open(struct net_device *dev)
 {
   struct scc_priv *priv = dev->priv;
   struct scc_info *info = priv->info;
@@ -740,7 +740,7 @@
 }
 
 
-static int scc_close(struct device *dev)
+static int scc_close(struct net_device *dev)
 {
   struct scc_priv *priv = dev->priv;
   struct scc_info *info = priv->info;
@@ -772,7 +772,7 @@
 }
 
 
-static int scc_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
+static int scc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
   int rc;
   struct scc_priv *priv = dev->priv;
@@ -797,7 +797,7 @@
 }
 
 
-static int scc_send_packet(struct sk_buff *skb, struct device *dev)
+static int scc_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
   struct scc_priv *priv = dev->priv;
   struct scc_info *info = priv->info;
@@ -851,7 +851,7 @@
 }
 
 
-static struct enet_statistics *scc_get_stats(struct device *dev)
+static struct enet_statistics *scc_get_stats(struct net_device *dev)
 {
   struct scc_priv *priv = dev->priv;
 
@@ -859,7 +859,7 @@
 }
 
 
-static int scc_set_mac_address(struct device *dev, void *sa)
+static int scc_set_mac_address(struct net_device *dev, void *sa)
 {
   memcpy(dev->dev_addr, ((struct sockaddr *)sa)->sa_data, dev->addr_len);
   return 0;
@@ -934,7 +934,7 @@
 }
 
 
-static void rx_isr(struct device *dev)
+static void rx_isr(struct net_device *dev)
 {
   struct scc_priv *priv = dev->priv;
   int cmd = priv->cmd;
@@ -961,7 +961,7 @@
 }
 
 
-static void special_condition(struct device *dev, int rc)
+static void special_condition(struct net_device *dev, int rc)
 {
   struct scc_priv *priv = dev->priv;
   int cb, cmd = priv->cmd;
@@ -1032,7 +1032,7 @@
 
 static void rx_bh(void *arg)
 {
-  struct device *dev = arg;
+  struct net_device *dev = arg;
   struct scc_priv *priv = dev->priv;
   struct scc_info *info = priv->info;
   int cmd = priv->cmd;
@@ -1081,7 +1081,7 @@
 }
 
 
-static void tx_isr(struct device *dev)
+static void tx_isr(struct net_device *dev)
 {
   struct scc_priv *priv = dev->priv;
   int cmd = priv->cmd;
@@ -1103,7 +1103,7 @@
 }
 
 
-static void es_isr(struct device *dev)
+static void es_isr(struct net_device *dev)
 {
   struct scc_priv *priv = dev->priv;
   struct scc_info *info = priv->info;
@@ -1261,7 +1261,7 @@
 }
 
 
-static void tm_isr(struct device *dev)
+static void tm_isr(struct net_device *dev)
 {
   struct scc_priv *priv = dev->priv;
   struct scc_info *info = priv->info;
@@ -1326,7 +1326,7 @@
 }
 
 
-static inline void delay(struct device *dev, int t)
+static inline void delay(struct net_device *dev, int t)
 {
   struct scc_priv *priv = dev->priv;
   int tmr = priv->tmr;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/hamradio/hdlcdrv.c linux/drivers/net/hamradio/hdlcdrv.c
--- v2.3.13/linux/drivers/net/hamradio/hdlcdrv.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/hamradio/hdlcdrv.c	Wed Aug 18 11:38:50 1999
@@ -204,7 +204,7 @@
 	return added;
 }
 
-static void hdlc_rx_flag(struct device *dev, struct hdlcdrv_state *s)
+static void hdlc_rx_flag(struct net_device *dev, struct hdlcdrv_state *s)
 {
 	struct sk_buff *skb;
 	int pkt_len;
@@ -231,7 +231,7 @@
 	s->stats.rx_packets++;
 }
 
-void hdlcdrv_receiver(struct device *dev, struct hdlcdrv_state *s)
+void hdlcdrv_receiver(struct net_device *dev, struct hdlcdrv_state *s)
 {
 	int i;
 	unsigned int mask1, mask2, mask3, mask4, mask5, mask6, word;
@@ -328,7 +328,7 @@
 
 /* ---------------------------------------------------------------------- */
 
-void hdlcdrv_transmitter(struct device *dev, struct hdlcdrv_state *s)
+void hdlcdrv_transmitter(struct net_device *dev, struct hdlcdrv_state *s)
 {
 	unsigned int mask1, mask2, mask3;
 	int i;
@@ -430,7 +430,7 @@
 
 /* ---------------------------------------------------------------------- */
 
-static void start_tx(struct device *dev, struct hdlcdrv_state *s)
+static void start_tx(struct net_device *dev, struct hdlcdrv_state *s)
 {
 	s->hdlctx.tx_state = 0;
 	s->hdlctx.numflags = tenms_to_2flags(s, s->ch_params.tx_delay);
@@ -452,7 +452,7 @@
 
 /* ---------------------------------------------------------------------- */
 
-void hdlcdrv_arbitrate(struct device *dev, struct hdlcdrv_state *s)
+void hdlcdrv_arbitrate(struct net_device *dev, struct hdlcdrv_state *s)
 {
 	if (!s || s->magic != HDLCDRV_MAGIC || s->hdlctx.ptt || 
 	    skb_queue_empty(&s->send_queue)) 
@@ -478,7 +478,7 @@
  * ===================== network driver interface =========================
  */
 
-static inline int hdlcdrv_paranoia_check(struct device *dev,
+static inline int hdlcdrv_paranoia_check(struct net_device *dev,
 					const char *routine)
 {
 	if (!dev || !dev->priv || 
@@ -492,7 +492,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int hdlcdrv_send_packet(struct sk_buff *skb, struct device *dev)
+static int hdlcdrv_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
 	struct hdlcdrv_state *sm;
 
@@ -506,7 +506,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int hdlcdrv_set_mac_address(struct device *dev, void *addr)
+static int hdlcdrv_set_mac_address(struct net_device *dev, void *addr)
 {
 	struct sockaddr *sa = (struct sockaddr *)addr;
 
@@ -517,7 +517,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static struct net_device_stats *hdlcdrv_get_stats(struct device *dev)
+static struct net_device_stats *hdlcdrv_get_stats(struct net_device *dev)
 {
 	struct hdlcdrv_state *sm;
 
@@ -541,7 +541,7 @@
  * there is non-reboot way to recover if something goes wrong.
  */
 
-static int hdlcdrv_open(struct device *dev)
+static int hdlcdrv_open(struct net_device *dev)
 {
 	struct hdlcdrv_state *s;
 	int i;
@@ -589,7 +589,7 @@
  * The inverse routine to hdlcdrv_open(). 
  */
 
-static int hdlcdrv_close(struct device *dev)
+static int hdlcdrv_close(struct net_device *dev)
 {
 	struct hdlcdrv_state *s;
 	struct sk_buff *skb;
@@ -614,7 +614,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int hdlcdrv_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
+static int hdlcdrv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	struct hdlcdrv_state *s;
 	struct hdlcdrv_ioctl bi;
@@ -749,7 +749,7 @@
  * If dev->base_addr == 2, allocate space for the device and return success
  * (detachable devices only).
  */
-static int hdlcdrv_probe(struct device *dev)
+static int hdlcdrv_probe(struct net_device *dev)
 {
 	const struct hdlcdrv_channel_params dflt_ch_params = { 
 		20, 2, 10, 40, 0 
@@ -830,7 +830,7 @@
 
 /* --------------------------------------------------------------------- */
 
-int hdlcdrv_register_hdlcdrv(struct device *dev, const struct hdlcdrv_ops *ops,
+int hdlcdrv_register_hdlcdrv(struct net_device *dev, const struct hdlcdrv_ops *ops,
 			     unsigned int privsize, char *ifname,
 			     unsigned int baseaddr, unsigned int irq, 
 			     unsigned int dma) 
@@ -841,7 +841,7 @@
 		return -EACCES;
 	if (privsize < sizeof(struct hdlcdrv_state))
 		privsize = sizeof(struct hdlcdrv_state);
-	memset(dev, 0, sizeof(struct device));
+	memset(dev, 0, sizeof(struct net_device));
 	if (!(s = dev->priv = kmalloc(privsize, GFP_KERNEL)))
 		return -ENOMEM;
 	/*
@@ -874,7 +874,7 @@
 
 /* --------------------------------------------------------------------- */
 
-int hdlcdrv_unregister_hdlcdrv(struct device *dev) 
+int hdlcdrv_unregister_hdlcdrv(struct net_device *dev) 
 {
 	struct hdlcdrv_state *s;
 
diff -u --recursive --new-file v2.3.13/linux/drivers/net/hamradio/mkiss.c linux/drivers/net/hamradio/mkiss.c
--- v2.3.13/linux/drivers/net/hamradio/mkiss.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/hamradio/mkiss.c	Wed Aug 18 11:38:50 1999
@@ -75,7 +75,7 @@
 typedef struct ax25_ctrl {
 	char if_name[8];	/* "ax0\0" .. "ax99999\0"	*/
 	struct ax_disp ctrl;	/* 				*/
-	struct device  dev;	/* the device			*/
+	struct net_device  dev;	/* the device			*/
 } ax25_ctrl_t;
 
 static ax25_ctrl_t **ax25_ctrls = NULL;
@@ -90,7 +90,7 @@
 static struct termios *mkiss_termios_locked[NR_MKISS];
 struct mkiss_channel MKISS_Info[NR_MKISS];
 
-static int ax25_init(struct device *);
+static int ax25_init(struct net_device *);
 static int mkiss_init(void);
 static int mkiss_write(struct tty_struct *, int, const unsigned char *, int);
 static int kiss_esc(unsigned char *, unsigned char *, int);
@@ -247,7 +247,7 @@
 
 static void ax_changedmtu(struct ax_disp *ax)
 {
-	struct device *dev = ax->dev;
+	struct net_device *dev = ax->dev;
 	unsigned char *xbuff, *rbuff, *oxbuff, *orbuff;
 	int len;
 	unsigned long flags;
@@ -460,7 +460,7 @@
 }
 
 /* Encapsulate an AX.25 packet and kick it into a TTY queue. */
-static int ax_xmit(struct sk_buff *skb, struct device *dev)
+static int ax_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ax_disp *ax = (struct ax_disp*)dev->priv;
 	struct mkiss_channel *mkiss = ax->tty->driver_data;
@@ -523,7 +523,7 @@
 #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
 
 /* Return the frame type ID */
-static int ax_header(struct sk_buff *skb, struct device *dev, unsigned short type,
+static int ax_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
 	  void *daddr, void *saddr, unsigned len)
 {
 #ifdef CONFIG_INET
@@ -546,7 +546,7 @@
 #endif	/* CONFIG_{AX25,AX25_MODULE} */
 
 /* Open the low-level part of the AX25 channel. Easy! */
-static int ax_open(struct device *dev)
+static int ax_open(struct net_device *dev)
 {
 	struct ax_disp *ax = (struct ax_disp*)dev->priv;
 	unsigned long len;
@@ -600,7 +600,7 @@
 
 
 /* Close the low-level part of the AX25 channel. Easy! */
-static int ax_close(struct device *dev)
+static int ax_close(struct net_device *dev)
 {
 	struct ax_disp *ax = (struct ax_disp*)dev->priv;
 
@@ -737,7 +737,7 @@
 }
 
 
-static struct net_device_stats *ax_get_stats(struct device *dev)
+static struct net_device_stats *ax_get_stats(struct net_device *dev)
 {
 	static struct net_device_stats stats;
 	struct ax_disp *ax = (struct ax_disp*)dev->priv;
@@ -873,14 +873,14 @@
 }
 
 
-int ax_set_mac_address(struct device *dev, void *addr)
+int ax_set_mac_address(struct net_device *dev, void *addr)
 {
 	if (copy_from_user(dev->dev_addr, addr, AX25_ADDR_LEN))
 		return -EFAULT;
 	return 0;
 }
 
-static int ax_set_dev_mac_address(struct device *dev, void *addr)
+static int ax_set_dev_mac_address(struct net_device *dev, void *addr)
 {
 	struct sockaddr *sa = addr;
 
@@ -926,7 +926,7 @@
 	}
 }
 
-static int ax_open_dev(struct device *dev)
+static int ax_open_dev(struct net_device *dev)
 {
 	struct ax_disp *ax = (struct ax_disp*)dev->priv;
 
@@ -986,7 +986,7 @@
 
 /* Initialize the driver.  Called by network startup. */
 
-static int ax25_init(struct device *dev)
+static int ax25_init(struct net_device *dev)
 {
 	struct ax_disp *ax = (struct ax_disp*)dev->priv;
 
diff -u --recursive --new-file v2.3.13/linux/drivers/net/hamradio/mkiss.h linux/drivers/net/hamradio/mkiss.h
--- v2.3.13/linux/drivers/net/hamradio/mkiss.h	Wed Jul 22 13:45:52 1998
+++ linux/drivers/net/hamradio/mkiss.h	Wed Aug 18 11:38:50 1999
@@ -18,7 +18,7 @@
 
 	/* Various fields. */
 	struct tty_struct  *tty;		/* ptr to TTY structure		*/
-	struct device      *dev;		/* easy for intr handling	*/
+	struct net_device      *dev;		/* easy for intr handling	*/
 	struct ax_disp     *mkiss;		/* mkiss txport if mkiss channel*/
 
 	/* These are pointers to the malloc()ed frame buffers. */
diff -u --recursive --new-file v2.3.13/linux/drivers/net/hamradio/pi2.c linux/drivers/net/hamradio/pi2.c
--- v2.3.13/linux/drivers/net/hamradio/pi2.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/hamradio/pi2.c	Wed Aug 18 11:38:50 1999
@@ -130,9 +130,9 @@
  *	PI device declarations.
  */
 
-static int pi0_preprobe(struct device *dev){return 0;}	/* Dummy probe function */
-static struct device pi0a = { "pi0a", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, pi0_preprobe };
-static struct device pi0b = { "pi0b", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, pi0_preprobe };
+static int pi0_preprobe(struct net_device *dev){return 0;}	/* Dummy probe function */
+static struct net_device pi0a = { "pi0a", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, pi0_preprobe };
+static struct net_device pi0b = { "pi0b", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, pi0_preprobe };
 
 
 /* The number of low I/O ports used by the card. */
@@ -141,18 +141,18 @@
 
 /* Index to functions, as function prototypes. */
 
-static int pi_probe(struct device *dev, int card_type);
-static int pi_open(struct device *dev);
-static int pi_send_packet(struct sk_buff *skb, struct device *dev);
+static int pi_probe(struct net_device *dev, int card_type);
+static int pi_open(struct net_device *dev);
+static int pi_send_packet(struct sk_buff *skb, struct net_device *dev);
 static void pi_interrupt(int reg_ptr, void *dev_id, struct pt_regs *regs);
-static int pi_close(struct device *dev);
-static int pi_ioctl(struct device *dev, struct ifreq *ifr, int cmd);
-static struct net_device_stats *pi_get_stats(struct device *dev);
+static int pi_close(struct net_device *dev);
+static int pi_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
+static struct net_device_stats *pi_get_stats(struct net_device *dev);
 static void rts(struct pi_local *lp, int x);
-static void b_rxint(struct device *dev, struct pi_local *lp);
+static void b_rxint(struct net_device *dev, struct pi_local *lp);
 static void b_txint(struct pi_local *lp);
 static void b_exint(struct pi_local *lp);
-static void a_rxint(struct device *dev, struct pi_local *lp);
+static void a_rxint(struct net_device *dev, struct pi_local *lp);
 static void a_txint(struct pi_local *lp);
 static void a_exint(struct pi_local *lp);
 static char *get_dma_buffer(unsigned long *mem_ptr);
@@ -493,7 +493,7 @@
 
 /* Receive interrupt handler for the A channel
  */
-static void a_rxint(struct device *dev, struct pi_local *lp)
+static void a_rxint(struct net_device *dev, struct pi_local *lp)
 {
     unsigned long flags;
     int cmd;
@@ -568,7 +568,7 @@
     restore_flags(flags);
 }
 
-static void b_rxint(struct device *dev, struct pi_local *lp)
+static void b_rxint(struct net_device *dev, struct pi_local *lp)
 {
     unsigned long flags;
     int cmd;
@@ -1063,7 +1063,7 @@
     }
 }
 
-static void scc_init(struct device *dev)
+static void scc_init(struct net_device *dev)
 {
     unsigned long flags;
     struct pi_local *lp = (struct pi_local *) dev->priv;
@@ -1165,7 +1165,7 @@
     restore_flags(flags);
 }
 
-static void chipset_init(struct device *dev)
+static void chipset_init(struct net_device *dev)
 {
     int cardbase;
     unsigned long flags;
@@ -1251,7 +1251,7 @@
 	return 0;
 }
 
-static int pi_set_mac_address(struct device *dev, void *addr)
+static int pi_set_mac_address(struct net_device *dev, void *addr)
 {
     struct sockaddr *sa = (struct sockaddr *)addr;
     memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);	/* addr is an AX.25 shifted ASCII */
@@ -1274,7 +1274,7 @@
     return (ret);
 }
 
-static int pi_probe(struct device *dev, int card_type)
+static int pi_probe(struct net_device *dev, int card_type)
 {
     short ioaddr;
     struct pi_local *lp;
@@ -1423,7 +1423,7 @@
    registers that "should" only need to be set once at boot, so that
    there is non-reboot way to recover if something goes wrong.
    */
-static int pi_open(struct device *dev)
+static int pi_open(struct net_device *dev)
 {
     unsigned long flags;
     static first_time = 1;
@@ -1464,7 +1464,7 @@
     return 0;
 }
 
-static int pi_send_packet(struct sk_buff *skb, struct device *dev)
+static int pi_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
     struct pi_local *lp = (struct pi_local *) dev->priv;
 
@@ -1531,7 +1531,7 @@
 }
 
 /* The inverse routine to pi_open(). */
-static int pi_close(struct device *dev)
+static int pi_close(struct net_device *dev)
 {
     unsigned long flags;
     struct pi_local *lp;
@@ -1562,7 +1562,7 @@
     return 0;
 }
 
-static int pi_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
+static int pi_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
     unsigned long flags;
     struct pi_req rq;
@@ -1643,7 +1643,7 @@
 
 /* Get the current statistics.	This may be called with the card open or
    closed. */
-static struct net_device_stats *pi_get_stats(struct device *dev)
+static struct net_device_stats *pi_get_stats(struct net_device *dev)
 {
 	struct pi_local *lp = (struct pi_local *) dev->priv;
 
diff -u --recursive --new-file v2.3.13/linux/drivers/net/hamradio/pt.c linux/drivers/net/hamradio/pt.c
--- v2.3.13/linux/drivers/net/hamradio/pt.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/hamradio/pt.c	Wed Aug 18 11:38:50 1999
@@ -105,9 +105,9 @@
 /*
  * The actual PT devices we will use
  */
-static int pt0_preprobe(struct device *dev) {return 0;} /* Dummy probe function */
-static struct device pt0a = { "pt0a", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, pt0_preprobe };
-static struct device pt0b = { "pt0b", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, pt0_preprobe };
+static int pt0_preprobe(struct net_device *dev) {return 0;} /* Dummy probe function */
+static struct net_device pt0a = { "pt0a", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, pt0_preprobe };
+static struct net_device pt0b = { "pt0b", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, pt0_preprobe };
 
 /* Ok, they shouldn't be here, but both channels share them */
 /* The Images of the Serial and DMA config registers */
@@ -119,15 +119,15 @@
 
 /* Index to functions, as function prototypes. */
 
-static int pt_probe(struct device *dev);
-static int pt_open(struct device *dev);
-static int pt_send_packet(struct sk_buff *skb, struct device *dev);
+static int pt_probe(struct net_device *dev);
+static int pt_open(struct net_device *dev);
+static int pt_send_packet(struct sk_buff *skb, struct net_device *dev);
 static void pt_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static int pt_close(struct device *dev);
-static int pt_ioctl(struct device *dev, struct ifreq *ifr, int cmd);
-static struct net_device_stats *pt_get_stats(struct device *dev);
+static int pt_close(struct net_device *dev);
+static int pt_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
+static struct net_device_stats *pt_get_stats(struct net_device *dev);
 static void pt_rts(struct pt_local *lp, int x);
-static void pt_rxisr(struct device *dev);
+static void pt_rxisr(struct net_device *dev);
 static void pt_txisr(struct pt_local *lp);
 static void pt_exisr(struct pt_local *lp);
 static void pt_tmrisr(struct pt_local *lp);
@@ -135,7 +135,7 @@
 static int valid_dma_page(unsigned long addr, unsigned long dev_buffsize);
 static int hw_probe(int ioaddr);
 static void tdelay(struct pt_local *lp, int time);
-static void chipset_init(struct device *dev);
+static void chipset_init(struct net_device *dev);
 
 static char ax25_bcast[7] =
 {'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1};
@@ -179,7 +179,7 @@
 	char kickflag;
 	unsigned long flags;
 	char *ptr;
-	struct device *dev;
+	struct net_device *dev;
 
 	/* First, let's see if this packet is actually a KISS packet */
 	ptr = skb->data;
@@ -322,7 +322,7 @@
  * This sets up all the registers in the SCC for the given channel
  * based upon tsync_hwint()
  */
-static void scc_init(struct device *dev)
+static void scc_init(struct net_device *dev)
 {
 	unsigned long flags;
 	struct pt_local *lp = (struct pt_local*) dev->priv;
@@ -443,7 +443,7 @@
 } /* scc_init() */
 
 /* Resets the given channel and whole SCC if both channels off */
-static void chipset_init(struct device *dev)
+static void chipset_init(struct net_device *dev)
 {
 
 	struct pt_local *lp = (struct pt_local*) dev->priv;
@@ -699,7 +699,7 @@
         return 0;
 }
 
-static int pt_set_mac_address(struct device *dev, void *addr)
+static int pt_set_mac_address(struct net_device *dev, void *addr)
 {
 	struct sockaddr *sa = (struct sockaddr *)addr;
 	memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);		/* addr is an AX.25 shifted ASCII */
@@ -726,7 +726,7 @@
 /*
  * Sets up all the structures for the PT device
  */
-static int pt_probe(struct device *dev)
+static int pt_probe(struct net_device *dev)
 {
     short ioaddr;
     struct pt_local *lp;
@@ -878,7 +878,7 @@
  * a non-reboot way to recover if something goes wrong.
  * derived from last half of tsync_attach()
  */
-static int pt_open(struct device *dev)
+static int pt_open(struct net_device *dev)
 {
     unsigned long flags;
     struct pt_local *lp = dev->priv;
@@ -928,7 +928,7 @@
     return 0;
 } /* pt_open() */
 
-static int pt_send_packet(struct sk_buff *skb, struct device *dev)
+static int pt_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
 	struct pt_local *lp = (struct pt_local *) dev->priv;
 
@@ -944,7 +944,7 @@
 
 
 /* The inverse routine to pt_open() */
-static int pt_close(struct device *dev)
+static int pt_close(struct net_device *dev)
 {
 	unsigned long flags;
 	struct pt_local *lp = dev->priv;
@@ -980,7 +980,7 @@
 } /* pt_close() */
 
 
-static int pt_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
+static int pt_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
     unsigned long flags;
     struct pt_req rq;
@@ -1064,7 +1064,7 @@
  *	This may be called with the card open or closed. 
  */
  
-static struct net_device_stats *pt_get_stats(struct device *dev)
+static struct net_device_stats *pt_get_stats(struct net_device *dev)
 {
 	struct pt_local *lp = (struct pt_local *) dev->priv;
 	return &lp->stats;
@@ -1219,7 +1219,7 @@
     restore_flags(flags);
 }
 
-static void pt_rxisr(struct device *dev)
+static void pt_rxisr(struct net_device *dev)
 {
     struct pt_local *lp = (struct pt_local*) dev->priv;
     int cmd = lp->base + CTL;
@@ -1432,7 +1432,7 @@
 static void pt_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
     /* It's a tad dodgy here, but we assume pt0a until proven otherwise */
-    struct device *dev = &pt0a;
+    struct net_device *dev = &pt0a;
     struct pt_local *lp = dev->priv;
     unsigned char intreg;
     unsigned char st;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/hamradio/scc.c linux/drivers/net/hamradio/scc.c
--- v2.3.13/linux/drivers/net/hamradio/scc.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/hamradio/scc.c	Wed Aug 18 11:38:50 1999
@@ -210,15 +210,15 @@
 static void scc_init_timer(struct scc_channel *scc);
 
 static int scc_net_setup(struct scc_channel *scc, unsigned char *name, int addev);
-static int scc_net_init(struct device *dev);
-static int scc_net_open(struct device *dev);
-static int scc_net_close(struct device *dev);
+static int scc_net_init(struct net_device *dev);
+static int scc_net_open(struct net_device *dev);
+static int scc_net_close(struct net_device *dev);
 static void scc_net_rx(struct scc_channel *scc, struct sk_buff *skb);
-static int scc_net_tx(struct sk_buff *skb, struct device *dev);
-static int scc_net_ioctl(struct device *dev, struct ifreq *ifr, int cmd);
-static int scc_net_set_mac_address(struct device *dev, void *addr);
-static int scc_net_header(struct sk_buff *skb, struct device *dev, unsigned short type, void *daddr, void *saddr, unsigned len);
-static struct net_device_stats * scc_net_get_stats(struct device *dev);
+static int scc_net_tx(struct sk_buff *skb, struct net_device *dev);
+static int scc_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
+static int scc_net_set_mac_address(struct net_device *dev, void *addr);
+static int scc_net_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len);
+static struct net_device_stats * scc_net_get_stats(struct net_device *dev);
 
 static unsigned char *SCC_DriverName = "scc";
 
@@ -1569,7 +1569,7 @@
 static int scc_net_setup(struct scc_channel *scc, unsigned char *name, int addev)
 {
 	unsigned char *buf;
-	struct device *dev;
+	struct net_device *dev;
 
 	if (dev_get(name) != NULL)
 	{
@@ -1577,11 +1577,11 @@
 		return -EEXIST;
 	}
 
-	if ((scc->dev = (struct device *) kmalloc(sizeof(struct device), GFP_KERNEL)) == NULL)
+	if ((scc->dev = (struct net_device *) kmalloc(sizeof(struct net_device), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 
 	dev = scc->dev;
-	memset(dev, 0, sizeof(struct device));
+	memset(dev, 0, sizeof(struct net_device));
 
 	buf = (unsigned char *) kmalloc(10, GFP_KERNEL);
 	strcpy(buf, name);
@@ -1612,7 +1612,7 @@
 
 /* ----> Initialize device <----- */
 
-static int scc_net_init(struct device *dev)
+static int scc_net_init(struct net_device *dev)
 {
 	dev_init_buffers(dev);
 	
@@ -1643,7 +1643,7 @@
 
 /* ----> open network device <---- */
 
-static int scc_net_open(struct device *dev)
+static int scc_net_open(struct net_device *dev)
 {
 	struct scc_channel *scc = (struct scc_channel *) dev->priv;
 
@@ -1668,7 +1668,7 @@
 
 /* ----> close network device <---- */
 
-static int scc_net_close(struct device *dev)
+static int scc_net_close(struct net_device *dev)
 {
 	struct scc_channel *scc = (struct scc_channel *) dev->priv;
 	unsigned long flags;
@@ -1721,7 +1721,7 @@
 
 /* ----> transmit frame <---- */
 
-static int scc_net_tx(struct sk_buff *skb, struct device *dev)
+static int scc_net_tx(struct sk_buff *skb, struct net_device *dev)
 {
 	struct scc_channel *scc = (struct scc_channel *) dev->priv;
 	unsigned long flags;
@@ -1799,7 +1799,7 @@
  * SIOCSCCCAL		- send calib. pattern	arg: (struct scc_calibrate *) arg
  */
 
-static int scc_net_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
+static int scc_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	struct scc_kiss_cmd kiss_cmd;
 	struct scc_mem_config memcfg;
@@ -2031,7 +2031,7 @@
 
 /* ----> set interface callsign <---- */
 
-static int scc_net_set_mac_address(struct device *dev, void *addr)
+static int scc_net_set_mac_address(struct net_device *dev, void *addr)
 {
 	struct sockaddr *sa = (struct sockaddr *) addr;
 	memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
@@ -2040,7 +2040,7 @@
 
 /* ----> "hard" header <---- */
 
-static int  scc_net_header(struct sk_buff *skb, struct device *dev, 
+static int  scc_net_header(struct sk_buff *skb, struct net_device *dev, 
 	unsigned short type, void *daddr, void *saddr, unsigned len)
 {
 	return ax25_encapsulate(skb, dev, type, daddr, saddr, len);
@@ -2048,7 +2048,7 @@
 
 /* ----> get statistics <---- */
 
-static struct net_device_stats *scc_net_get_stats(struct device *dev)
+static struct net_device_stats *scc_net_get_stats(struct net_device *dev)
 {
 	struct scc_channel *scc = (struct scc_channel *) dev->priv;
 	
diff -u --recursive --new-file v2.3.13/linux/drivers/net/hamradio/soundmodem/sm.c linux/drivers/net/hamradio/soundmodem/sm.c
--- v2.3.13/linux/drivers/net/hamradio/soundmodem/sm.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/hamradio/soundmodem/sm.c	Wed Aug 18 11:38:50 1999
@@ -140,7 +140,7 @@
 
 #define NR_PORTS 4
 
-static struct device sm_device[NR_PORTS];
+static struct net_device sm_device[NR_PORTS];
 
 /* --------------------------------------------------------------------- */
 
@@ -357,9 +357,9 @@
 
 /* --------------------------------------------------------------------- */
 
-static int sm_open(struct device *dev);
-static int sm_close(struct device *dev);
-static int sm_ioctl(struct device *dev, struct ifreq *ifr,
+static int sm_open(struct net_device *dev);
+static int sm_close(struct net_device *dev);
+static int sm_ioctl(struct net_device *dev, struct ifreq *ifr,
 		    struct hdlcdrv_ioctl *hi, int cmd);
 
 /* --------------------------------------------------------------------- */
@@ -370,7 +370,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int sm_open(struct device *dev)
+static int sm_open(struct net_device *dev)
 {
 	struct sm_state *sm;
 	int err;
@@ -398,7 +398,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int sm_close(struct device *dev)
+static int sm_close(struct net_device *dev)
 {
 	struct sm_state *sm;
 	int err = -ENODEV;
@@ -422,7 +422,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int sethw(struct device *dev, struct sm_state *sm, char *mode)
+static int sethw(struct net_device *dev, struct sm_state *sm, char *mode)
 {
 	char *cp = strchr(mode, ':');
 	const struct hardware_info **hwp = sm_hardware_table;
@@ -451,7 +451,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int sm_ioctl(struct device *dev, struct ifreq *ifr,
+static int sm_ioctl(struct net_device *dev, struct ifreq *ifr,
 		    struct hdlcdrv_ioctl *hi, int cmd)
 {
 	struct sm_state *sm;
@@ -626,7 +626,7 @@
 	 * register net devices
 	 */
 	for (i = 0; i < NR_PORTS; i++) {
-		struct device *dev = sm_device+i;
+		struct net_device *dev = sm_device+i;
 		sprintf(ifname, "sm%d", i);
 
 		if (!mode[i])
@@ -700,7 +700,7 @@
 	printk(KERN_INFO "sm: cleanup_module called\n");
 
 	for(i = 0; i < NR_PORTS; i++) {
-		struct device *dev = sm_device+i;
+		struct net_device *dev = sm_device+i;
 		struct sm_state *sm = (struct sm_state *)dev->priv;
 
 		if (sm) {
diff -u --recursive --new-file v2.3.13/linux/drivers/net/hamradio/soundmodem/sm.h linux/drivers/net/hamradio/soundmodem/sm.h
--- v2.3.13/linux/drivers/net/hamradio/soundmodem/sm.h	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/hamradio/soundmodem/sm.h	Wed Aug 18 11:38:50 1999
@@ -141,11 +141,11 @@
 	/*
 	 * mode specific open/close
 	 */
-	int (*open)(struct device *, struct sm_state *);
-	int (*close)(struct device *, struct sm_state *);
-	int (*ioctl)(struct device *, struct sm_state *, struct ifreq *,
+	int (*open)(struct net_device *, struct sm_state *);
+	int (*close)(struct net_device *, struct sm_state *);
+	int (*ioctl)(struct net_device *, struct sm_state *, struct ifreq *,
 		     struct hdlcdrv_ioctl *, int);
-	int (*sethw)(struct device *, struct sm_state *, char *);
+	int (*sethw)(struct net_device *, struct sm_state *, char *);
 };
 
 /* --------------------------------------------------------------------- */
diff -u --recursive --new-file v2.3.13/linux/drivers/net/hamradio/soundmodem/sm_sbc.c linux/drivers/net/hamradio/soundmodem/sm_sbc.c
--- v2.3.13/linux/drivers/net/hamradio/soundmodem/sm_sbc.c	Tue Dec  9 09:49:58 1997
+++ linux/drivers/net/hamradio/soundmodem/sm_sbc.c	Wed Aug 18 11:38:50 1999
@@ -140,7 +140,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int inline reset_dsp(struct device *dev)
+static int inline reset_dsp(struct net_device *dev)
 {
 	int i;
 
@@ -156,7 +156,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static void inline write_dsp(struct device *dev, unsigned char data)
+static void inline write_dsp(struct net_device *dev, unsigned char data)
 {
 	int i;
 	
@@ -169,7 +169,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int inline read_dsp(struct device *dev, unsigned char *data)
+static int inline read_dsp(struct net_device *dev, unsigned char *data)
 {
 	int i;
 
@@ -185,7 +185,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int config_resources(struct device *dev, struct sm_state *sm, int fdx)
+static int config_resources(struct net_device *dev, struct sm_state *sm, int fdx)
 {
 	unsigned char irqreg = 0, dmareg = 0, realirq, realdma;
 	unsigned long flags;
@@ -266,21 +266,21 @@
 
 /* --------------------------------------------------------------------- */
 
-static void inline sbc_int_ack_8bit(struct device *dev)
+static void inline sbc_int_ack_8bit(struct net_device *dev)
 {
 	inb(DSP_DATA_AVAIL(dev->base_addr));
 }
 
 /* --------------------------------------------------------------------- */
 
-static void inline sbc_int_ack_16bit(struct device *dev)
+static void inline sbc_int_ack_16bit(struct net_device *dev)
 {
 	inb(DSP_INTACK_16BIT(dev->base_addr));
 }
 
 /* --------------------------------------------------------------------- */
 
-static void setup_dma_dsp(struct device *dev, struct sm_state *sm, int send)
+static void setup_dma_dsp(struct net_device *dev, struct sm_state *sm, int send)
 {
         unsigned long flags;
         static const unsigned char sbcmode[2][2] = {
@@ -323,7 +323,7 @@
 
 static void sbc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev = (struct device *)dev_id;
+	struct net_device *dev = (struct net_device *)dev_id;
 	struct sm_state *sm = (struct sm_state *)dev->priv;
 	unsigned int curfrag;
 
@@ -364,7 +364,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int sbc_open(struct device *dev, struct sm_state *sm) 
+static int sbc_open(struct net_device *dev, struct sm_state *sm) 
 {
 	int err;
 	unsigned int dmasz, u;
@@ -449,7 +449,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int sbc_close(struct device *dev, struct sm_state *sm) 
+static int sbc_close(struct net_device *dev, struct sm_state *sm) 
 {
 	if (!dev || !sm)
 		return -EINVAL;
@@ -467,7 +467,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int sbc_sethw(struct device *dev, struct sm_state *sm, char *mode)
+static int sbc_sethw(struct net_device *dev, struct sm_state *sm, char *mode)
 {
 	char *cp = strchr(mode, '.');
 	const struct modem_tx_info **mtp = sm_modem_tx_table;
@@ -524,7 +524,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int sbc_ioctl(struct device *dev, struct sm_state *sm, struct ifreq *ifr, 
+static int sbc_ioctl(struct net_device *dev, struct sm_state *sm, struct ifreq *ifr, 
 		     struct hdlcdrv_ioctl *hi, int cmd)
 {
 	struct sm_ioctl bi;
@@ -619,7 +619,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static void setup_dma_fdx_dsp(struct device *dev, struct sm_state *sm)
+static void setup_dma_fdx_dsp(struct net_device *dev, struct sm_state *sm)
 {
         unsigned long flags;
 	unsigned int isamps, osamps;
@@ -684,7 +684,7 @@
 
 static void sbcfdx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev = (struct device *)dev_id;
+	struct net_device *dev = (struct net_device *)dev_id;
 	struct sm_state *sm = (struct sm_state *)dev->priv;
 	unsigned char intsrc, pbint = 0, captint = 0;
 	unsigned int ocfrag, icfrag;
@@ -747,7 +747,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int sbcfdx_open(struct device *dev, struct sm_state *sm) 
+static int sbcfdx_open(struct net_device *dev, struct sm_state *sm) 
 {
 	int err;
 
@@ -830,7 +830,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int sbcfdx_close(struct device *dev, struct sm_state *sm) 
+static int sbcfdx_close(struct net_device *dev, struct sm_state *sm) 
 {
 	if (!dev || !sm)
 		return -EINVAL;
@@ -851,7 +851,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int sbcfdx_sethw(struct device *dev, struct sm_state *sm, char *mode)
+static int sbcfdx_sethw(struct net_device *dev, struct sm_state *sm, char *mode)
 {
 	char *cp = strchr(mode, '.');
 	const struct modem_tx_info **mtp = sm_modem_tx_table;
@@ -917,7 +917,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int sbcfdx_ioctl(struct device *dev, struct sm_state *sm, struct ifreq *ifr, 
+static int sbcfdx_ioctl(struct net_device *dev, struct sm_state *sm, struct ifreq *ifr, 
 			struct hdlcdrv_ioctl *hi, int cmd)
 {
 	if (cmd != SIOCDEVPRIVATE)
diff -u --recursive --new-file v2.3.13/linux/drivers/net/hamradio/soundmodem/sm_wss.c linux/drivers/net/hamradio/soundmodem/sm_wss.c
--- v2.3.13/linux/drivers/net/hamradio/soundmodem/sm_wss.c	Tue Aug  5 09:49:51 1997
+++ linux/drivers/net/hamradio/soundmodem/sm_wss.c	Wed Aug 18 11:38:51 1999
@@ -102,7 +102,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static void write_codec(struct device *dev, unsigned char idx,
+static void write_codec(struct net_device *dev, unsigned char idx,
 			unsigned char data)
 {
 	int timeout = 900000;
@@ -117,7 +117,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static unsigned char read_codec(struct device *dev, unsigned char idx)
+static unsigned char read_codec(struct net_device *dev, unsigned char idx)
 {
 	int timeout = 900000;
 
@@ -130,7 +130,7 @@
 
 /* --------------------------------------------------------------------- */
 
-extern void inline wss_ack_int(struct device *dev)
+extern void inline wss_ack_int(struct net_device *dev)
 {
 	outb(0, WSS_CODEC_STATUS(dev->base_addr));
 }
@@ -154,7 +154,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int wss_set_codec_fmt(struct device *dev, struct sm_state *sm, unsigned char fmt, 
+static int wss_set_codec_fmt(struct net_device *dev, struct sm_state *sm, unsigned char fmt, 
 			     unsigned char fmt2, char fdx, char fullcalib)
 {
 	unsigned long time;
@@ -202,7 +202,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int wss_init_codec(struct device *dev, struct sm_state *sm, char fdx, 
+static int wss_init_codec(struct net_device *dev, struct sm_state *sm, char fdx, 
 			  unsigned char src_l, unsigned char src_r, 
 			  int igain_l, int igain_r,
 			  int ogain_l, int ogain_r)
@@ -341,7 +341,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static void setup_dma_wss(struct device *dev, struct sm_state *sm, int send)
+static void setup_dma_wss(struct net_device *dev, struct sm_state *sm, int send)
 {
         unsigned long flags;
         static const unsigned char codecmode[2] = { 0x0e, 0x0d };
@@ -383,7 +383,7 @@
 
 static void wss_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev = (struct device *)dev_id;
+	struct net_device *dev = (struct net_device *)dev_id;
 	struct sm_state *sm = (struct sm_state *)dev->priv;
 	unsigned int curfrag;
 	unsigned int nums;
@@ -426,7 +426,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int wss_open(struct device *dev, struct sm_state *sm) 
+static int wss_open(struct net_device *dev, struct sm_state *sm) 
 {
 	unsigned int dmasz, u;
 
@@ -484,7 +484,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int wss_close(struct device *dev, struct sm_state *sm) 
+static int wss_close(struct net_device *dev, struct sm_state *sm) 
 {
 	if (!dev || !sm)
 		return -EINVAL;
@@ -502,7 +502,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int wss_sethw(struct device *dev, struct sm_state *sm, char *mode)
+static int wss_sethw(struct net_device *dev, struct sm_state *sm, char *mode)
 {
 	char *cp = strchr(mode, '.');
 	const struct modem_tx_info **mtp = sm_modem_tx_table;
@@ -600,7 +600,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int wss_ioctl(struct device *dev, struct sm_state *sm, struct ifreq *ifr, 
+static int wss_ioctl(struct net_device *dev, struct sm_state *sm, struct ifreq *ifr, 
 		     struct hdlcdrv_ioctl *hi, int cmd)
 {
 	struct sm_ioctl bi;
@@ -665,7 +665,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static void setup_fdx_dma_wss(struct device *dev, struct sm_state *sm)
+static void setup_fdx_dma_wss(struct net_device *dev, struct sm_state *sm)
 {
         unsigned long flags;
 	unsigned char oldcodecmode, codecdma;
@@ -703,7 +703,7 @@
 
 static void wssfdx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev = (struct device *)dev_id;
+	struct net_device *dev = (struct net_device *)dev_id;
 	struct sm_state *sm = (struct sm_state *)dev->priv;
 	unsigned long flags;
 	unsigned char cry_int_src;
@@ -781,7 +781,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int wssfdx_open(struct device *dev, struct sm_state *sm) 
+static int wssfdx_open(struct net_device *dev, struct sm_state *sm) 
 {
 	if (!dev || !sm || !sm->mode_rx || !sm->mode_tx)
 		return -ENXIO;
@@ -840,7 +840,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int wssfdx_close(struct device *dev, struct sm_state *sm) 
+static int wssfdx_close(struct net_device *dev, struct sm_state *sm) 
 {
 	if (!dev || !sm)
 		return -EINVAL;
@@ -861,7 +861,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int wssfdx_sethw(struct device *dev, struct sm_state *sm, char *mode)
+static int wssfdx_sethw(struct net_device *dev, struct sm_state *sm, char *mode)
 {
 	char *cp = strchr(mode, '.');
 	const struct modem_tx_info **mtp = sm_modem_tx_table;
@@ -938,7 +938,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int wssfdx_ioctl(struct device *dev, struct sm_state *sm, struct ifreq *ifr, 
+static int wssfdx_ioctl(struct net_device *dev, struct sm_state *sm, struct ifreq *ifr, 
 			struct hdlcdrv_ioctl *hi, int cmd)
 {
 	if (cmd != SIOCDEVPRIVATE)
diff -u --recursive --new-file v2.3.13/linux/drivers/net/hamradio/yam.c linux/drivers/net/hamradio/yam.c
--- v2.3.13/linux/drivers/net/hamradio/yam.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/hamradio/yam.c	Wed Aug 18 11:38:51 1999
@@ -117,7 +117,7 @@
 #endif
 
 #if LINUX_VERSION_CODE < 0x20115
-extern __inline__ void dev_init_buffers(struct device *dev)
+extern __inline__ void dev_init_buffers(struct net_device *dev)
 {
 	int i;
 	for (i = 0; i < DEV_NUMBUFFS; i++) {
@@ -174,7 +174,7 @@
 	int dupmode;
 	char name[16];
 
-	struct device dev;
+	struct net_device dev;
 
 	/* Stats section */
 
@@ -515,7 +515,7 @@
 * Serial port init 
 ************************************************************************/
 
-static void yam_set_uart(struct device *dev)
+static void yam_set_uart(struct net_device *dev)
 {
 	struct yam_port *yp = (struct yam_port *) dev->priv;
 	int divisor = 115200 / yp->baudrate;
@@ -584,7 +584,7 @@
 * Rx Section
 ******************************************************************************/
 static void inline
- yam_rx_flag(struct device *dev, struct yam_port *yp)
+ yam_rx_flag(struct net_device *dev, struct yam_port *yp)
 {
 	if (yp->dcd && yp->rx_len >= 3 && yp->rx_len < YAM_MAX_FRAME) {
 		int pkt_len = yp->rx_len - 2 + 1;	/* -CRC + kiss */
@@ -615,7 +615,7 @@
 }
 
 static void inline
- yam_rx_byte(struct device *dev, struct yam_port *yp, unsigned char rxb)
+ yam_rx_byte(struct net_device *dev, struct yam_port *yp, unsigned char rxb)
 {
 	if (yp->rx_len < YAM_MAX_FRAME) {
 		unsigned char c = yp->rx_crcl;
@@ -629,17 +629,17 @@
 * TX Section
 ********************************************************************************/
 
-static void ptt_on(struct device *dev)
+static void ptt_on(struct net_device *dev)
 {
 	outb(PTT_ON, MCR(dev->base_addr));
 }
 
-static void ptt_off(struct device *dev)
+static void ptt_off(struct net_device *dev)
 {
 	outb(PTT_OFF, MCR(dev->base_addr));
 }
 
-static int yam_send_packet(struct sk_buff *skb, struct device *dev)
+static int yam_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
 	struct yam_port *yp = dev->priv;
 
@@ -651,7 +651,7 @@
 	return 0;
 }
 
-static void yam_start_tx(struct device *dev, struct yam_port *yp)
+static void yam_start_tx(struct net_device *dev, struct yam_port *yp)
 {
 	if ((yp->tx_state == TX_TAIL) || (yp->txd == 0))
 		yp->tx_count = 1;
@@ -669,7 +669,7 @@
 	return random_seed;
 }
 
-static void yam_arbitrate(struct device *dev)
+static void yam_arbitrate(struct net_device *dev)
 {
 	struct yam_port *yp = dev->priv;
 
@@ -707,7 +707,7 @@
 	int i;
 
 	for (i = 0; i < NR_PORTS; i++) {
-		struct device *dev = &yam_ports[i].dev;
+		struct net_device *dev = &yam_ports[i].dev;
 		if (dev->start)
 			yam_arbitrate(dev);
 	}
@@ -715,7 +715,7 @@
 	add_timer(&yam_timer);
 }
 
-static void yam_tx_byte(struct device *dev, struct yam_port *yp)
+static void yam_tx_byte(struct net_device *dev, struct yam_port *yp)
 {
 	struct sk_buff *skb;
 	unsigned char b, temp;
@@ -795,7 +795,7 @@
 
 static void yam_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev;
+	struct net_device *dev;
 	struct yam_port *yp;
 	unsigned char iir;
 	int counter = 100;
@@ -915,10 +915,10 @@
 
 #if LINUX_VERSION_CODE >= 0x20119
 static struct net_device_stats *
- yam_get_stats(struct device *dev)
+ yam_get_stats(struct net_device *dev)
 #else
 static struct enet_statistics *
- yam_get_stats(struct device *dev)
+ yam_get_stats(struct net_device *dev)
 #endif
 {
 	struct yam_port *yp;
@@ -939,7 +939,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int yam_open(struct device *dev)
+static int yam_open(struct net_device *dev)
 {
 	struct yam_port *yp = (struct yam_port *) dev->priv;
 	enum uart u;
@@ -990,7 +990,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int yam_close(struct device *dev)
+static int yam_close(struct net_device *dev)
 {
 	struct sk_buff *skb;
 	struct yam_port *yp = (struct yam_port *) dev->priv;
@@ -1018,7 +1018,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int yam_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
+static int yam_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	struct yam_port *yp = (struct yam_port *) dev->priv;
 	struct yamdrv_ioctl_cfg yi;
@@ -1147,7 +1147,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int yam_set_mac_address(struct device *dev, void *addr)
+static int yam_set_mac_address(struct net_device *dev, void *addr)
 {
 	struct sockaddr *sa = (struct sockaddr *) addr;
 
@@ -1158,7 +1158,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int yam_probe(struct device *dev)
+static int yam_probe(struct net_device *dev)
 {
 	struct yam_port *yp;
 
@@ -1201,7 +1201,7 @@
 
 /* --------------------------------------------------------------------- */
 
-__initfunc(int yam_init(struct device *dev))
+__initfunc(int yam_init(struct net_device *dev))
 {
 	int i;
 
@@ -1282,7 +1282,7 @@
 
 	del_timer(&yam_timer);
 	for (i = 0; i < NR_PORTS; i++) {
-		struct device *dev = &yam_ports[i].dev;
+		struct net_device *dev = &yam_ports[i].dev;
 		if (!dev->priv)
 			continue;
 		if (dev->start)
diff -u --recursive --new-file v2.3.13/linux/drivers/net/hostess_sv11.c linux/drivers/net/hostess_sv11.c
--- v2.3.13/linux/drivers/net/hostess_sv11.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/hostess_sv11.c	Wed Aug 18 11:36:42 1999
@@ -73,7 +73,7 @@
  *	We've been placed in the UP state
  */ 
  
-static int hostess_open(struct device *d)
+static int hostess_open(struct net_device *d)
 {
 	struct sv11_device *sv11=d->priv;
 	int err = -1;
@@ -126,7 +126,7 @@
 	return 0;
 }
 
-static int hostess_close(struct device *d)
+static int hostess_close(struct net_device *d)
 {
 	struct sv11_device *sv11=d->priv;
 	/*
@@ -158,14 +158,14 @@
 	return 0;
 }
 
-static int hostess_ioctl(struct device *d, struct ifreq *ifr, int cmd)
+static int hostess_ioctl(struct net_device *d, struct ifreq *ifr, int cmd)
 {
 	/* struct sv11_device *sv11=d->priv;
 	   z8530_ioctl(d,&sv11->sync.chanA,ifr,cmd) */
 	return sppp_do_ioctl(d, ifr,cmd);
 }
 
-static struct enet_statistics *hostess_get_stats(struct device *d)
+static struct enet_statistics *hostess_get_stats(struct net_device *d)
 {
 	struct sv11_device *sv11=d->priv;
 	if(sv11)
@@ -178,7 +178,7 @@
  *	Passed PPP frames, fire them downwind.
  */
  
-static int hostess_queue_xmit(struct sk_buff *skb, struct device *d)
+static int hostess_queue_xmit(struct sk_buff *skb, struct net_device *d)
 {
 	struct sv11_device *sv11=d->priv;
 	return z8530_queue_xmit(&sv11->sync.chanA, skb);
@@ -194,7 +194,7 @@
 	return 0;
 }
 
-static int hostess_neigh_setup_dev(struct device *dev, struct neigh_parms *p)
+static int hostess_neigh_setup_dev(struct net_device *dev, struct neigh_parms *p)
 {
 	if (p->tbl->family == AF_INET) {
 		p->neigh_setup = hostess_neigh_setup;
@@ -206,7 +206,7 @@
 
 #else
 
-static int return_0(struct device *d)
+static int return_0(struct net_device *d)
 {
 	return 0;
 }
@@ -322,7 +322,7 @@
 		sprintf(sv->name,"hdlc%d", i);
 		if(dev_get(sv->name)==NULL)
 		{
-			struct device *d=dev->chanA.netdevice;
+			struct net_device *d=dev->chanA.netdevice;
 	
 			/* 
 			 *	Initialise the PPP components
diff -u --recursive --new-file v2.3.13/linux/drivers/net/hp-plus.c linux/drivers/net/hp-plus.c
--- v2.3.13/linux/drivers/net/hp-plus.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/hp-plus.c	Wed Aug 18 11:36:42 1999
@@ -94,23 +94,23 @@
 	EnableIRQ = 4, FakeIntr = 8, BootROMEnb = 0x10, IOEnb = 0x20,
 	MemEnable = 0x40, ZeroWait = 0x80, MemDisable = 0x1000, };
 
-int hp_plus_probe(struct device *dev);
-int hpp_probe1(struct device *dev, int ioaddr);
+int hp_plus_probe(struct net_device *dev);
+int hpp_probe1(struct net_device *dev, int ioaddr);
 
-static void hpp_reset_8390(struct device *dev);
-static int hpp_open(struct device *dev);
-static int hpp_close(struct device *dev);
-static void hpp_mem_block_input(struct device *dev, int count,
+static void hpp_reset_8390(struct net_device *dev);
+static int hpp_open(struct net_device *dev);
+static int hpp_close(struct net_device *dev);
+static void hpp_mem_block_input(struct net_device *dev, int count,
 						  struct sk_buff *skb, int ring_offset);
-static void hpp_mem_block_output(struct device *dev, int count,
+static void hpp_mem_block_output(struct net_device *dev, int count,
 							const unsigned char *buf, int start_page);
-static void hpp_mem_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
+static void hpp_mem_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
 						  int ring_page);
-static void hpp_io_block_input(struct device *dev, int count,
+static void hpp_io_block_input(struct net_device *dev, int count,
 						  struct sk_buff *skb, int ring_offset);
-static void hpp_io_block_output(struct device *dev, int count,
+static void hpp_io_block_output(struct net_device *dev, int count,
 							const unsigned char *buf, int start_page);
-static void hpp_io_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
+static void hpp_io_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
 						  int ring_page);
 
 
@@ -123,7 +123,7 @@
 {"hpplus", hpp_probe1, HP_IO_EXTENT, hpplus_portlist};
 #else
 
-int __init hp_plus_probe(struct device *dev)
+int __init hp_plus_probe(struct net_device *dev)
 {
 	int i;
 	int base_addr = dev ? dev->base_addr : 0;
@@ -146,7 +146,7 @@
 #endif
 
 /* Do the interesting part of the probe at a single address. */
-int __init hpp_probe1(struct device *dev, int ioaddr)
+int __init hpp_probe1(struct net_device *dev, int ioaddr)
 {
 	int i;
 	unsigned char checksum = 0;
@@ -258,7 +258,7 @@
 }
 
 static int
-hpp_open(struct device *dev)
+hpp_open(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr - NIC_OFFSET;
 	int option_reg;
@@ -287,7 +287,7 @@
 }
 
 static int
-hpp_close(struct device *dev)
+hpp_close(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr - NIC_OFFSET;
 	int option_reg = inw(ioaddr + HPP_OPTION);
@@ -302,7 +302,7 @@
 }
 
 static void
-hpp_reset_8390(struct device *dev)
+hpp_reset_8390(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr - NIC_OFFSET;
 	int option_reg = inw(ioaddr + HPP_OPTION);
@@ -329,7 +329,7 @@
    Note that transfer with the EtherTwist+ must be on word boundaries. */
 
 static void
-hpp_io_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+hpp_io_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 {
 	int ioaddr = dev->base_addr - NIC_OFFSET;
 
@@ -340,7 +340,7 @@
 /* Block input and output, similar to the Crynwr packet driver. */
 
 static void
-hpp_io_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
+hpp_io_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
 {
 	int ioaddr = dev->base_addr - NIC_OFFSET;
 	char *buf = skb->data;
@@ -354,7 +354,7 @@
 /* The corresponding shared memory versions of the above 2 functions. */
 
 static void
-hpp_mem_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+hpp_mem_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 {
 	int ioaddr = dev->base_addr - NIC_OFFSET;
 	int option_reg = inw(ioaddr + HPP_OPTION);
@@ -367,7 +367,7 @@
 }
 
 static void
-hpp_mem_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
+hpp_mem_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
 {
 	int ioaddr = dev->base_addr - NIC_OFFSET;
 	int option_reg = inw(ioaddr + HPP_OPTION);
@@ -387,7 +387,7 @@
 /* A special note: we *must* always transfer >=16 bit words.
    It's always safe to round up, so we do. */
 static void
-hpp_io_block_output(struct device *dev, int count,
+hpp_io_block_output(struct net_device *dev, int count,
 					const unsigned char *buf, int start_page)
 {
 	int ioaddr = dev->base_addr - NIC_OFFSET;
@@ -397,7 +397,7 @@
 }
 
 static void
-hpp_mem_block_output(struct device *dev, int count,
+hpp_mem_block_output(struct net_device *dev, int count,
 				const unsigned char *buf, int start_page)
 {
 	int ioaddr = dev->base_addr - NIC_OFFSET;
@@ -416,7 +416,7 @@
 #define MAX_HPP_CARDS	4	/* Max number of HPP cards per module */
 #define NAMELEN		8	/* # of chars for storing dev->name */
 static char namelist[NAMELEN * MAX_HPP_CARDS] = { 0, };
-static struct device dev_hpp[MAX_HPP_CARDS] = {
+static struct net_device dev_hpp[MAX_HPP_CARDS] = {
 	{
 		NULL,		/* assign a chunk of namelist[] below */
 		0, 0, 0, 0,
@@ -439,7 +439,7 @@
 	int this_dev, found = 0;
 
 	for (this_dev = 0; this_dev < MAX_HPP_CARDS; this_dev++) {
-		struct device *dev = &dev_hpp[this_dev];
+		struct net_device *dev = &dev_hpp[this_dev];
 		dev->name = namelist+(NAMELEN*this_dev);
 		dev->irq = irq[this_dev];
 		dev->base_addr = io[this_dev];
@@ -468,7 +468,7 @@
 	int this_dev;
 
 	for (this_dev = 0; this_dev < MAX_HPP_CARDS; this_dev++) {
-		struct device *dev = &dev_hpp[this_dev];
+		struct net_device *dev = &dev_hpp[this_dev];
 		if (dev->priv != NULL) {
 			int ioaddr = dev->base_addr - NIC_OFFSET;
 			void *priv = dev->priv;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/hp.c linux/drivers/net/hp.c
--- v2.3.13/linux/drivers/net/hp.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/hp.c	Wed Aug 18 11:36:42 1999
@@ -56,20 +56,20 @@
 #define HP_8BSTOP_PG	0x80	/* Last page +1 of RX ring */
 #define HP_16BSTOP_PG	0xFF	/* Same, for 16 bit cards. */
 
-int hp_probe(struct device *dev);
-int hp_probe1(struct device *dev, int ioaddr);
+int hp_probe(struct net_device *dev);
+int hp_probe1(struct net_device *dev, int ioaddr);
 
-static int hp_open(struct device *dev);
-static int hp_close(struct device *dev);
-static void hp_reset_8390(struct device *dev);
-static void hp_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
+static int hp_open(struct net_device *dev);
+static int hp_close(struct net_device *dev);
+static void hp_reset_8390(struct net_device *dev);
+static void hp_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
 					int ring_page);
-static void hp_block_input(struct device *dev, int count,
+static void hp_block_input(struct net_device *dev, int count,
 					struct sk_buff *skb , int ring_offset);
-static void hp_block_output(struct device *dev, int count,
+static void hp_block_output(struct net_device *dev, int count,
 							const unsigned char *buf, int start_page);
 
-static void hp_init_card(struct device *dev);
+static void hp_init_card(struct net_device *dev);
 
 /* The map from IRQ number to HP_CONFIGURE register setting. */
 /* My default is IRQ5	             0  1  2  3  4  5  6  7  8  9 10 11 */
@@ -84,7 +84,7 @@
 {"hp", hp_probe1, HP_IO_EXTENT, hppclan_portlist};
 #else
 
-int __init hp_probe(struct device *dev)
+int __init hp_probe(struct net_device *dev)
 {
 	int i;
 	int base_addr = dev ? dev->base_addr : 0;
@@ -106,7 +106,7 @@
 }
 #endif
 
-int __init hp_probe1(struct device *dev, int ioaddr)
+int __init hp_probe1(struct net_device *dev, int ioaddr)
 {
 	int i, board_id, wordmode;
 	const char *name;
@@ -215,7 +215,7 @@
 }
 
 static int
-hp_open(struct device *dev)
+hp_open(struct net_device *dev)
 {
 	ei_open(dev);
 	MOD_INC_USE_COUNT;
@@ -223,7 +223,7 @@
 }
 
 static int
-hp_close(struct device *dev)
+hp_close(struct net_device *dev)
 {
 	ei_close(dev);
 	MOD_DEC_USE_COUNT;
@@ -231,7 +231,7 @@
 }
 
 static void
-hp_reset_8390(struct device *dev)
+hp_reset_8390(struct net_device *dev)
 {
 	int hp_base = dev->base_addr - NIC_OFFSET;
 	int saved_config = inb_p(hp_base + HP_CONFIGURE);
@@ -253,7 +253,7 @@
 }
 
 static void
-hp_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+hp_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 {
 	int nic_base = dev->base_addr;
 	int saved_config = inb_p(nic_base - NIC_OFFSET + HP_CONFIGURE);
@@ -280,7 +280,7 @@
    out through the "remote DMA" dataport. */
 
 static void
-hp_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
+hp_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
 {
 	int nic_base = dev->base_addr;
 	int saved_config = inb_p(nic_base - NIC_OFFSET + HP_CONFIGURE);
@@ -315,7 +315,7 @@
 }
 
 static void
-hp_block_output(struct device *dev, int count,
+hp_block_output(struct net_device *dev, int count,
 				const unsigned char *buf, int start_page)
 {
 	int nic_base = dev->base_addr;
@@ -374,7 +374,7 @@
 
 /* This function resets the ethercard if something screws up. */
 static void
-hp_init_card(struct device *dev)
+hp_init_card(struct net_device *dev)
 {
 	int irq = dev->irq;
 	NS8390_init(dev, 0);
@@ -387,7 +387,7 @@
 #define MAX_HP_CARDS	4	/* Max number of HP cards per module */
 #define NAMELEN		8	/* # of chars for storing dev->name */
 static char namelist[NAMELEN * MAX_HP_CARDS] = { 0, };
-static struct device dev_hp[MAX_HP_CARDS] = {
+static struct net_device dev_hp[MAX_HP_CARDS] = {
 	{
 		NULL,		/* assign a chunk of namelist[] below */
 		0, 0, 0, 0,
@@ -410,7 +410,7 @@
 	int this_dev, found = 0;
 
 	for (this_dev = 0; this_dev < MAX_HP_CARDS; this_dev++) {
-		struct device *dev = &dev_hp[this_dev];
+		struct net_device *dev = &dev_hp[this_dev];
 		dev->name = namelist+(NAMELEN*this_dev);
 		dev->irq = irq[this_dev];
 		dev->base_addr = io[this_dev];
@@ -439,7 +439,7 @@
 	int this_dev;
 
 	for (this_dev = 0; this_dev < MAX_HP_CARDS; this_dev++) {
-		struct device *dev = &dev_hp[this_dev];
+		struct net_device *dev = &dev_hp[this_dev];
 		if (dev->priv != NULL) {
 			int ioaddr = dev->base_addr - NIC_OFFSET;
 			void *priv = dev->priv;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/hp100.c linux/drivers/net/hp100.c
--- v2.3.13/linux/drivers/net/hp100.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/hp100.c	Wed Aug 18 11:36:42 1999
@@ -300,38 +300,38 @@
  */
 
 #ifdef LINUX_2_1
-static int  hp100_probe1( struct device *dev, int ioaddr, u_char bus, struct pci_dev *pci_dev );
+static int  hp100_probe1( struct net_device *dev, int ioaddr, u_char bus, struct pci_dev *pci_dev );
 #else
-static int  hp100_probe1( struct device *dev, int ioaddr, u_char bus, u_char pci_bus, u_char pci_device_fn );
+static int  hp100_probe1( struct net_device *dev, int ioaddr, u_char bus, u_char pci_bus, u_char pci_device_fn );
 #endif
-static int  hp100_open( struct device *dev );
-static int  hp100_close( struct device *dev );
-static int  hp100_start_xmit( struct sk_buff *skb, struct device *dev );
-static int  hp100_start_xmit_bm (struct sk_buff *skb, struct device *dev );
-static void hp100_rx( struct device *dev );
-static hp100_stats_t *hp100_get_stats( struct device *dev );
-static void hp100_misc_interrupt( struct device *dev );
-static void hp100_update_stats( struct device *dev );
+static int  hp100_open( struct net_device *dev );
+static int  hp100_close( struct net_device *dev );
+static int  hp100_start_xmit( struct sk_buff *skb, struct net_device *dev );
+static int  hp100_start_xmit_bm (struct sk_buff *skb, struct net_device *dev );
+static void hp100_rx( struct net_device *dev );
+static hp100_stats_t *hp100_get_stats( struct net_device *dev );
+static void hp100_misc_interrupt( struct net_device *dev );
+static void hp100_update_stats( struct net_device *dev );
 static void hp100_clear_stats( int ioaddr );
-static void hp100_set_multicast_list( struct device *dev);
+static void hp100_set_multicast_list( struct net_device *dev);
 static void hp100_interrupt( int irq, void *dev_id, struct pt_regs *regs );
-static void hp100_start_interface( struct device *dev );
-static void hp100_stop_interface( struct device *dev );
-static void hp100_load_eeprom( struct device *dev, u_short ioaddr );
-static int  hp100_sense_lan( struct device *dev );
-static int  hp100_login_to_vg_hub( struct device *dev, u_short force_relogin );
-static int  hp100_down_vg_link( struct device *dev );
-static void hp100_cascade_reset( struct device *dev, u_short enable );
-static void hp100_BM_shutdown( struct device *dev );
-static void hp100_mmuinit( struct device *dev );
-static void hp100_init_pdls( struct device *dev );
-static int  hp100_init_rxpdl( struct device *dev, register hp100_ring_t *ringptr, register u_int *pdlptr);
-static int  hp100_init_txpdl( struct device *dev, register hp100_ring_t *ringptr, register u_int *pdlptr);
-static void hp100_rxfill( struct device *dev );
-static void hp100_hwinit( struct device *dev );
-static void hp100_clean_txring( struct device *dev );
+static void hp100_start_interface( struct net_device *dev );
+static void hp100_stop_interface( struct net_device *dev );
+static void hp100_load_eeprom( struct net_device *dev, u_short ioaddr );
+static int  hp100_sense_lan( struct net_device *dev );
+static int  hp100_login_to_vg_hub( struct net_device *dev, u_short force_relogin );
+static int  hp100_down_vg_link( struct net_device *dev );
+static void hp100_cascade_reset( struct net_device *dev, u_short enable );
+static void hp100_BM_shutdown( struct net_device *dev );
+static void hp100_mmuinit( struct net_device *dev );
+static void hp100_init_pdls( struct net_device *dev );
+static int  hp100_init_rxpdl( struct net_device *dev, register hp100_ring_t *ringptr, register u_int *pdlptr);
+static int  hp100_init_txpdl( struct net_device *dev, register hp100_ring_t *ringptr, register u_int *pdlptr);
+static void hp100_rxfill( struct net_device *dev );
+static void hp100_hwinit( struct net_device *dev );
+static void hp100_clean_txring( struct net_device *dev );
 #ifdef HP100_DEBUG
-static void hp100_RegisterDump( struct device *dev );
+static void hp100_RegisterDump( struct net_device *dev );
 #endif
 
 /* TODO: This function should not really be needed in a good design... */
@@ -346,7 +346,7 @@
  *  since this could cause problems when the card is not installed.
  */
  
-int __init hp100_probe( struct device *dev )
+int __init hp100_probe( struct net_device *dev )
 {
   int base_addr = dev ? dev -> base_addr : 0;
   int ioaddr = 0;
@@ -523,9 +523,9 @@
 
 
 #ifdef LINUX_2_1
-static int __init hp100_probe1( struct device *dev, int ioaddr, u_char bus, struct pci_dev *pci_dev )
+static int __init hp100_probe1( struct net_device *dev, int ioaddr, u_char bus, struct pci_dev *pci_dev )
 #else
-static int __init hp100_probe1( struct device *dev, int ioaddr, u_char bus, u_char pci_bus, u_char pci_device_fn )
+static int __init hp100_probe1( struct net_device *dev, int ioaddr, u_char bus, u_char pci_bus, u_char pci_device_fn )
 #endif
 {
   int i;
@@ -941,7 +941,7 @@
 
 
 /* This procedure puts the card into a stable init state */
-static void hp100_hwinit( struct device *dev )
+static void hp100_hwinit( struct net_device *dev )
 {
   int ioaddr = dev->base_addr;
   struct hp100_private *lp = (struct hp100_private *)dev->priv;
@@ -1037,7 +1037,7 @@
  * mmuinit - Reinitialise Cascade MMU and MAC settings.
  * Note: Must already be in reset and leaves card in reset. 
  */
-static void hp100_mmuinit( struct device *dev )
+static void hp100_mmuinit( struct net_device *dev )
 {
   int ioaddr = dev->base_addr;
   struct hp100_private *lp = (struct hp100_private *)dev->priv;
@@ -1230,7 +1230,7 @@
  *  open/close functions
  */
 
-static int hp100_open( struct device *dev )
+static int hp100_open( struct net_device *dev )
 {
   struct hp100_private *lp = (struct hp100_private *)dev->priv;
 #ifdef HP100_DEBUG_B
@@ -1274,7 +1274,7 @@
 
 
 /* The close function is called when the interface is to be brought down */
-static int hp100_close( struct device *dev )
+static int hp100_close( struct net_device *dev )
 {
   int ioaddr = dev->base_addr;
   struct hp100_private *lp = (struct hp100_private *)dev->priv;
@@ -1309,7 +1309,7 @@
 /*
  * Configure the PDL Rx rings and LAN 
  */
-static void hp100_init_pdls( struct device *dev )
+static void hp100_init_pdls( struct net_device *dev )
 {
   struct hp100_private *lp = (struct hp100_private *)dev->priv;
   hp100_ring_t         *ringptr;
@@ -1362,7 +1362,7 @@
 
 /* These functions "format" the entries in the pdl structure   */
 /* They return how much memory the fragments need.            */
-static int hp100_init_rxpdl( struct device *dev, register hp100_ring_t *ringptr, register u32 *pdlptr )
+static int hp100_init_rxpdl( struct net_device *dev, register hp100_ring_t *ringptr, register u32 *pdlptr )
 {
   /* pdlptr is starting address for this pdl */
 
@@ -1388,7 +1388,7 @@
 }
 
 
-static int hp100_init_txpdl( struct device *dev, register hp100_ring_t *ringptr, register u32 *pdlptr )
+static int hp100_init_txpdl( struct net_device *dev, register hp100_ring_t *ringptr, register u32 *pdlptr )
 {
   if( 0!=( ((unsigned)pdlptr) & 0xf) )
     printk("hp100: %s: Init txpdl: Unaligned pdlptr 0x%x.\n",dev->name,(unsigned) pdlptr);
@@ -1408,7 +1408,7 @@
  * Returns: 0 if unable to allocate skb_buff
  *          1 if successful
  */
-int hp100_build_rx_pdl( hp100_ring_t *ringptr, struct device *dev )
+int hp100_build_rx_pdl( hp100_ring_t *ringptr, struct net_device *dev )
 {
 #ifdef HP100_DEBUG_B
   int ioaddr = dev->base_addr;
@@ -1492,7 +1492,7 @@
  *      b.  Put the physical address of the buffer into the PDL.
  *      c.  Output physical address of PDL to adapter.
  */
-static void hp100_rxfill( struct device *dev )
+static void hp100_rxfill( struct net_device *dev )
 {
   int ioaddr=dev->base_addr; 
 
@@ -1540,7 +1540,7 @@
  * BM_shutdown - shutdown bus mastering and leave chip in reset state
  */
 
-static void hp100_BM_shutdown( struct device *dev )
+static void hp100_BM_shutdown( struct net_device *dev )
 {
   int ioaddr = dev->base_addr;
   struct hp100_private *lp = (struct hp100_private *)dev->priv;
@@ -1634,7 +1634,7 @@
  */
 
 /* tx function for busmaster mode */
-static int hp100_start_xmit_bm( struct sk_buff *skb, struct device *dev )
+static int hp100_start_xmit_bm( struct sk_buff *skb, struct net_device *dev )
 {
   unsigned long flags;
   int i, ok_flag;
@@ -1772,7 +1772,7 @@
  *
  * Needs the PERFORMANCE page selected. 
  */
-static void hp100_clean_txring( struct device *dev )
+static void hp100_clean_txring( struct net_device *dev )
 {
   struct hp100_private *lp = (struct hp100_private *)dev->priv;
   int    ioaddr = dev->base_addr;
@@ -1814,7 +1814,7 @@
 
 
 /* tx function for slave modes */
-static int hp100_start_xmit( struct sk_buff *skb, struct device *dev )
+static int hp100_start_xmit( struct sk_buff *skb, struct net_device *dev )
 {
   int i, ok_flag;
   int ioaddr = dev->base_addr;
@@ -1984,7 +1984,7 @@
  * and netif_rx. 
  */
 
-static void hp100_rx( struct device *dev )
+static void hp100_rx( struct net_device *dev )
 {
   int packets, pkt_len;
   int ioaddr = dev->base_addr;
@@ -2103,7 +2103,7 @@
 /* 
  * Receive Function for Busmaster Mode
  */
-static void hp100_rx_bm( struct device *dev )
+static void hp100_rx_bm( struct net_device *dev )
 {
   int ioaddr = dev->base_addr;
   struct hp100_private *lp = (struct hp100_private *)dev->priv;
@@ -2232,7 +2232,7 @@
 /*
  *  statistics
  */
-static hp100_stats_t *hp100_get_stats( struct device *dev )
+static hp100_stats_t *hp100_get_stats( struct net_device *dev )
 {
   int ioaddr = dev->base_addr;
 
@@ -2246,7 +2246,7 @@
   return &((struct hp100_private *)dev->priv)->stats;
 }
 
-static void hp100_update_stats( struct device *dev )
+static void hp100_update_stats( struct net_device *dev )
 {
   int ioaddr = dev->base_addr;
   u_short val;
@@ -2271,7 +2271,7 @@
   hp100_page( PERFORMANCE );
 }
 
-static void hp100_misc_interrupt( struct device *dev )
+static void hp100_misc_interrupt( struct net_device *dev )
 {
   struct hp100_private *lp = (struct hp100_private *)dev->priv;
 
@@ -2313,7 +2313,7 @@
  *  Set or clear the multicast filter for this adapter.
  */
                                                           
-static void hp100_set_multicast_list( struct device *dev )
+static void hp100_set_multicast_list( struct net_device *dev )
 {
   unsigned long flags;
   int ioaddr = dev->base_addr;
@@ -2468,7 +2468,7 @@
 
 static void hp100_interrupt( int irq, void *dev_id, struct pt_regs *regs )
 {
-  struct device *dev = (struct device *)dev_id;
+  struct net_device *dev = (struct net_device *)dev_id;
   struct hp100_private *lp = (struct hp100_private *)dev->priv;
 
   int ioaddr;
@@ -2609,7 +2609,7 @@
  *  some misc functions
  */
 
-static void hp100_start_interface( struct device *dev )
+static void hp100_start_interface( struct net_device *dev )
 {
   unsigned long flags;
   int ioaddr = dev->base_addr;
@@ -2676,7 +2676,7 @@
 }
 
 
-static void hp100_stop_interface( struct device *dev )
+static void hp100_stop_interface( struct net_device *dev )
 {
   struct hp100_private *lp = (struct hp100_private *)dev->priv; 
   int ioaddr = dev->base_addr;
@@ -2714,7 +2714,7 @@
 }
 
 
-static void hp100_load_eeprom( struct device *dev, u_short probe_ioaddr )
+static void hp100_load_eeprom( struct net_device *dev, u_short probe_ioaddr )
 {
   int i;
   int ioaddr = probe_ioaddr > 0 ? probe_ioaddr : dev->base_addr;
@@ -2737,7 +2737,7 @@
  *                 LAN_100 - Connected to 100Mbit/s network
  *                 LAN_ERR - not connected or 100Mbit/s Hub down
  */
-static int hp100_sense_lan( struct device *dev )
+static int hp100_sense_lan( struct net_device *dev )
 {
   int ioaddr = dev->base_addr;
   u_short val_VG, val_10;
@@ -2779,7 +2779,7 @@
 
 
 
-static int hp100_down_vg_link( struct device *dev )
+static int hp100_down_vg_link( struct net_device *dev )
 {
   struct hp100_private *lp = (struct hp100_private *)dev->priv;
   int ioaddr = dev->base_addr;
@@ -2873,7 +2873,7 @@
 }
 
 
-static int hp100_login_to_vg_hub( struct device *dev, u_short force_relogin )
+static int hp100_login_to_vg_hub( struct net_device *dev, u_short force_relogin )
 {
   int ioaddr = dev->base_addr;
   struct hp100_private *lp = (struct hp100_private *)dev->priv;
@@ -3046,7 +3046,7 @@
 }
 
 
-static void hp100_cascade_reset( struct device *dev, u_short enable )
+static void hp100_cascade_reset( struct net_device *dev, u_short enable )
 {
   int ioaddr = dev->base_addr;
   struct hp100_private *lp = (struct hp100_private *)dev->priv;
@@ -3083,7 +3083,7 @@
 }
 
 #ifdef HP100_DEBUG		
-void hp100_RegisterDump( struct device *dev )
+void hp100_RegisterDump( struct net_device *dev )
 {
   int ioaddr=dev->base_addr;
   int Page;
@@ -3140,7 +3140,7 @@
 #endif
 
 /* List of devices */
-static struct device *hp100_devlist[5] = { NULL, NULL, NULL, NULL, NULL };
+static struct net_device *hp100_devlist[5] = { NULL, NULL, NULL, NULL, NULL };
 
 /*
  * Note: if you have more than five 100vg cards in your pc, feel free to
@@ -3166,8 +3166,8 @@
   while((hp100_port[++i] != -1) && (i < 5))
     {
       /* Create device and set basics args */
-      hp100_devlist[i] = kmalloc(sizeof(struct device), GFP_KERNEL);
-      memset(hp100_devlist[i], 0x00, sizeof(struct device));
+      hp100_devlist[i] = kmalloc(sizeof(struct net_device), GFP_KERNEL);
+      memset(hp100_devlist[i], 0x00, sizeof(struct net_device));
       hp100_devlist[i]->name = hp100_name[i];
       hp100_devlist[i]->base_addr = hp100_port[i];
       hp100_devlist[i]->init = &hp100_probe;
@@ -3177,8 +3177,8 @@
 	{
 	  /* DeAllocate everything */
 	  /* Note: if dev->priv is mallocated, there is no way to fail */
-	  kfree_s(hp100_devlist[i], sizeof(struct device));
-	  hp100_devlist[i] = (struct device *) NULL;
+	  kfree_s(hp100_devlist[i], sizeof(struct net_device));
+	  hp100_devlist[i] = (struct net_device *) NULL;
 	}
        else
         cards++;
@@ -3193,7 +3193,7 @@
 
   /* TODO: Check if all skb's are released/freed. */
   for(i = 0; i < 5; i++)
-    if(hp100_devlist[i] != (struct device *) NULL)
+    if(hp100_devlist[i] != (struct net_device *) NULL)
       {
 	unregister_netdev( hp100_devlist[i] );
 	release_region( hp100_devlist[i]->base_addr, HP100_REGION_SIZE );
@@ -3203,8 +3203,8 @@
 	  iounmap( ((struct hp100_private *)hp100_devlist[i]->priv) -> mem_ptr_virt );
 	kfree_s( hp100_devlist[i]->priv, sizeof( struct hp100_private ) );
 	hp100_devlist[i]->priv = NULL;
-	kfree_s(hp100_devlist[i], sizeof(struct device));
-	hp100_devlist[i] = (struct device *) NULL;
+	kfree_s(hp100_devlist[i], sizeof(struct net_device));
+	hp100_devlist[i] = (struct net_device *) NULL;
       }
 }
 
diff -u --recursive --new-file v2.3.13/linux/drivers/net/hplance.c linux/drivers/net/hplance.c
--- v2.3.13/linux/drivers/net/hplance.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/hplance.c	Wed Aug 18 11:36:42 1999
@@ -54,10 +54,10 @@
  * plus board-specific init, open and close actions. 
  * Oh, and we need to tell the generic code how to read and write LANCE registers...
  */
-int hplance_probe(struct device *dev);
-static int hplance_init(struct device *dev, int scode);
-static int hplance_open(struct device *dev);
-static int hplance_close(struct device *dev);
+int hplance_probe(struct net_device *dev);
+static int hplance_init(struct net_device *dev, int scode);
+static int hplance_open(struct net_device *dev);
+static int hplance_close(struct net_device *dev);
 static void hplance_writerap(struct hplance_private *lp, unsigned short value);
 static void hplance_writerdp(struct hplance_private *lp, unsigned short value);
 static unsigned short hplance_readrdp(struct hplance_private *lp);
@@ -67,7 +67,7 @@
 #endif
 
 /* Find all the HP Lance boards and initialise them... */
-int __init hplance_probe(struct device *dev)
+int __init hplance_probe(struct net_device *dev)
 {
         int cards = 0, called = 0;
 
@@ -98,7 +98,7 @@
 }
 
 /* Initialise a single lance board at the given select code */
-static int __init hplance_init(struct device *dev, int scode)
+static int __init hplance_init(struct net_device *dev, int scode)
 {
         /* const char *name = dio_scodetoname(scode); */
         static const char name[] = "HP LANCE";
@@ -198,7 +198,7 @@
         return val;
 }
 
-static int hplance_open(struct device *dev)
+static int hplance_open(struct net_device *dev)
 {
         int status;
         struct hplance_private *lp = (struct hplance_private *)dev->priv;
@@ -214,7 +214,7 @@
         return 0;
 }
 
-static int hplance_close(struct device *dev)
+static int hplance_close(struct net_device *dev)
 {
         struct hplance_private *lp = (struct hplance_private *)dev->priv;
         struct hplance_reg *hpregs = (struct hplance_reg *)lp->base;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/hydra.c linux/drivers/net/hydra.c
--- v2.3.13/linux/drivers/net/hydra.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/hydra.c	Wed Aug 18 11:36:42 1999
@@ -90,14 +90,14 @@
 	unsigned int key;
 };
 
-static int hydra_open(struct device *dev);
-static int hydra_start_xmit(struct sk_buff *skb, struct device *dev);
+static int hydra_open(struct net_device *dev);
+static int hydra_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static void hydra_interrupt(int irq, void *data, struct pt_regs *fp);
-static void __inline__ hydra_rx(struct device *dev, struct hydra_private *priv, volatile u8 *nicbase);
-static int hydra_close(struct device *dev);
-static struct net_device_stats *hydra_get_stats(struct device *dev);
+static void __inline__ hydra_rx(struct net_device *dev, struct hydra_private *priv, volatile u8 *nicbase);
+static int hydra_close(struct net_device *dev);
+static struct net_device_stats *hydra_get_stats(struct net_device *dev);
 #ifdef HAVE_MULTICAST
-static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
+static void set_multicast_list(struct net_device *dev, int num_addrs, void *addrs);
 #endif
 
 
@@ -157,7 +157,7 @@
 
 #endif
 
-int __init hydra_probe(struct device *dev)
+int __init hydra_probe(struct net_device *dev)
 {
 	struct hydra_private *priv;
 	u32 board;
@@ -210,7 +210,7 @@
 }
 
 
-static int hydra_open(struct device *dev)
+static int hydra_open(struct net_device *dev)
 {
 	struct hydra_private *priv = (struct hydra_private *)dev->priv;
 	volatile u8 *nicbase = priv->hydra_nic_base;
@@ -282,7 +282,8 @@
 	dev->interrupt = 0;
 	dev->start = 1;
     
-	if(request_irq(IRQ_AMIGA_PORTS, hydra_interrupt, 0, "Hydra Ethernet", dev))
+	if(request_irq(IRQ_AMIGA_PORTS, hydra_interrupt, SA_SHIRQ,
+		       "Hydra Ethernet", dev))
 		return(-EAGAIN);
 
 	MOD_INC_USE_COUNT;
@@ -291,7 +292,7 @@
 }
 
 
-static int hydra_close(struct device *dev)
+static int hydra_close(struct net_device *dev)
 {
 	struct hydra_private *priv = (struct hydra_private *)dev->priv;
 	volatile u8 *nicbase = priv->hydra_nic_base;
@@ -322,7 +323,7 @@
 {
 	volatile u8 *nicbase;
   
-	struct device *dev = (struct device *) data;
+	struct net_device *dev = (struct net_device *) data;
 	struct hydra_private *priv;
 	u16 intbits;
 
@@ -433,7 +434,7 @@
  * packet transmit routine
  */
 
-static int hydra_start_xmit(struct sk_buff *skb, struct device *dev)
+static int hydra_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct hydra_private *priv = (struct hydra_private *)dev->priv;
 	volatile u8 *nicbase = priv->hydra_nic_base;
@@ -524,7 +525,7 @@
 }
 
 
-static void __inline__ hydra_rx(struct device *dev, struct hydra_private *priv, volatile u8 *nicbase)
+static void __inline__ hydra_rx(struct net_device *dev, struct hydra_private *priv, volatile u8 *nicbase)
 {
 	volatile u16 *board_ram_ptr;
 	struct sk_buff *skb;
@@ -633,7 +634,7 @@
 }
     
 
-static struct net_device_stats *hydra_get_stats(struct device *dev)
+static struct net_device_stats *hydra_get_stats(struct net_device *dev)
 {
 	struct hydra_private *priv = (struct hydra_private *)dev->priv;
 #if 0
@@ -647,7 +648,7 @@
 }
 
 #ifdef HAVE_MULTICAST
-static void set_multicast_list(struct device *dev, int num_addrs, void *addrs)
+static void set_multicast_list(struct net_device *dev, int num_addrs, void *addrs)
 {
 	struct hydra_private *priv = (struct hydra_private *)dev->priv;
 	u8 *board = priv->hydra_base;
@@ -662,7 +663,7 @@
 #ifdef MODULE
 static char devicename[9] = { 0, };
 
-static struct device hydra_dev =
+static struct net_device hydra_dev =
 {
 	devicename,			/* filled in by register_netdev() */
 	0, 0, 0, 0,			/* memory */
diff -u --recursive --new-file v2.3.13/linux/drivers/net/ibmtr.c linux/drivers/net/ibmtr.c
--- v2.3.13/linux/drivers/net/ibmtr.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/ibmtr.c	Wed Aug 18 11:36:42 1999
@@ -193,27 +193,27 @@
 #define TRC_INIT 0x01              /*  Trace initialization & PROBEs */
 #define TRC_INITV 0x02             /*  verbose init trace points     */
 
-int		ibmtr_probe(struct device *dev);
-static int	ibmtr_probe1(struct device *dev, int ioaddr);
+int		ibmtr_probe(struct net_device *dev);
+static int	ibmtr_probe1(struct net_device *dev, int ioaddr);
 static unsigned char	get_sram_size(struct tok_info *adapt_info);
 #ifdef PCMCIA
 extern unsigned char 	pcmcia_reality_check(unsigned char gss);
 #endif
-static int	tok_init_card(struct device *dev);
+static int	tok_init_card(struct net_device *dev);
 void		tok_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static int	trdev_init(struct device *dev);
-static void 	initial_tok_int(struct device *dev);
-static void 	open_sap(unsigned char type,struct device *dev);
+static int	trdev_init(struct net_device *dev);
+static void 	initial_tok_int(struct net_device *dev);
+static void 	open_sap(unsigned char type,struct net_device *dev);
 void		tok_open_adapter(unsigned long dev_addr);
-static		void tr_rx(struct device *dev);
-static		void tr_tx(struct device *dev);
-static int	tok_open(struct device *dev);
-static int	tok_close(struct device *dev);
-static int	tok_send_packet(struct sk_buff *skb, struct device *dev);
-static struct net_device_stats * tok_get_stats(struct device *dev);
-void		ibmtr_readlog(struct device *dev);
-void		ibmtr_reset_timer(struct timer_list *tmr, struct device *dev);
-int             ibmtr_change_mtu(struct device *dev, int mtu);
+static		void tr_rx(struct net_device *dev);
+static		void tr_tx(struct net_device *dev);
+static int	tok_open(struct net_device *dev);
+static int	tok_close(struct net_device *dev);
+static int	tok_send_packet(struct sk_buff *skb, struct net_device *dev);
+static struct net_device_stats * tok_get_stats(struct net_device *dev);
+void		ibmtr_readlog(struct net_device *dev);
+void		ibmtr_reset_timer(struct timer_list *tmr, struct net_device *dev);
+int             ibmtr_change_mtu(struct net_device *dev, int mtu);
 
 static unsigned int ibmtr_portlist[] __initdata = {
 	0xa20, 0xa24, 0
@@ -250,7 +250,7 @@
  *	which references it.
  */
  
-int __init ibmtr_probe(struct device *dev)
+int __init ibmtr_probe(struct net_device *dev)
 {
         int i;
         int base_addr = dev ? dev->base_addr : 0;
@@ -293,7 +293,7 @@
         return -ENODEV;
 }
 
-static int __init ibmtr_probe1(struct device *dev, int PIOaddr)
+static int __init ibmtr_probe1(struct net_device *dev, int PIOaddr)
 {
 	unsigned char segment=0, intr=0, irq=0, i=0, j=0, cardpresent=NOTOK,temp=0;
 	__u32 t_mmio=0;
@@ -767,7 +767,7 @@
 		return 1<<((readb(adapt_info->mmio+ ACA_OFFSET + ACA_RW + RRR_ODD)>>2)+4);
 }
 
-static int __init trdev_init(struct device *dev)
+static int __init trdev_init(struct net_device *dev)
 {
 	struct tok_info *ti=(struct tok_info *)dev->priv;
 
@@ -791,7 +791,7 @@
 
 
 
-static int tok_open(struct device *dev)
+static int tok_open(struct net_device *dev)
 {
 	struct tok_info *ti=(struct tok_info *)dev->priv;
 
@@ -815,7 +815,7 @@
 
 }
 
-static int tok_close(struct device *dev)
+static int tok_close(struct net_device *dev)
 {
 
 	struct tok_info *ti=(struct tok_info *) dev->priv;
@@ -846,7 +846,7 @@
 {
 	unsigned char status;
 	struct tok_info *ti;
-	struct device *dev;
+	struct net_device *dev;
 
 	dev = dev_id;
 #if TR_VERBOSE
@@ -1220,7 +1220,7 @@
 	spin_unlock(&(ti->lock));
 }
 
-static void initial_tok_int(struct device *dev)
+static void initial_tok_int(struct net_device *dev)
 {
 
 	__u32 encoded_addr;
@@ -1288,7 +1288,7 @@
 	tok_open_adapter((unsigned long)dev);
 }
 
-static int tok_init_card(struct device *dev)
+static int tok_init_card(struct net_device *dev)
 {
 	struct tok_info *ti;
 	short PIOaddr;
@@ -1326,7 +1326,7 @@
 	return 0;
 }
 
-static void open_sap(unsigned char type,struct device *dev)
+static void open_sap(unsigned char type,struct net_device *dev)
 {
 	int i;
 	struct tok_info *ti=(struct tok_info *) dev->priv;
@@ -1351,7 +1351,7 @@
 void tok_open_adapter(unsigned long dev_addr)
 {
 
-	struct device *dev=(struct device *)dev_addr;
+	struct net_device *dev=(struct net_device *)dev_addr;
 	struct tok_info *ti;
 	int i;
 
@@ -1400,7 +1400,7 @@
 
 }
 
-static void tr_tx(struct device *dev)
+static void tr_tx(struct net_device *dev)
 {
 	struct tok_info *ti=(struct tok_info *) dev->priv;
 	struct trh_hdr *trhdr=(struct trh_hdr *)ti->current_skb->data;
@@ -1475,7 +1475,7 @@
 	if (ti->readlog_pending) ibmtr_readlog(dev);
 }
 
-static void tr_rx(struct device *dev)
+static void tr_rx(struct net_device *dev)
 {
 	struct tok_info *ti=(struct tok_info *) dev->priv;
 	__u32 rbuffer, rbufdata;
@@ -1630,7 +1630,7 @@
 	netif_rx(skb);
 }
 
-static int tok_send_packet(struct sk_buff *skb, struct device *dev)
+static int tok_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
 	struct tok_info *ti;
 	ti=(struct tok_info *) dev->priv;
@@ -1668,7 +1668,7 @@
 	return 0;
 }
 
-void ibmtr_reset_timer(struct timer_list *tmr, struct device *dev) {
+void ibmtr_reset_timer(struct timer_list *tmr, struct net_device *dev) {
 	tmr->expires  = jiffies + TR_RETRY_INTERVAL;
 	tmr->data     = (unsigned long) dev;
 	tmr->function = tok_open_adapter;
@@ -1676,7 +1676,7 @@
 	add_timer(tmr);
 }
 
-void ibmtr_readlog(struct device *dev) {
+void ibmtr_readlog(struct net_device *dev) {
 	 struct tok_info *ti;
 	 ti=(struct tok_info *) dev->priv;
 
@@ -1692,14 +1692,14 @@
    this device -- the tr.... structure is an ethnet look-alike
    so at least for this iteration may suffice.   */
 
-static struct net_device_stats * tok_get_stats(struct device *dev) {
+static struct net_device_stats * tok_get_stats(struct net_device *dev) {
 
 	struct tok_info *toki;
 	toki=(struct tok_info *) dev->priv;
 	return (struct net_device_stats *) &toki->tr_stats;
 }
 
-int ibmtr_change_mtu(struct device *dev, int mtu) {
+int ibmtr_change_mtu(struct net_device *dev, int mtu) {
 	struct tok_info *ti = (struct tok_info *) dev->priv;
 	
 	if (ti->ring_speed == 16 && mtu > ti->maxmtu16)
@@ -1713,7 +1713,7 @@
 #ifdef MODULE
 
 /* 3COM 3C619C supports 8 interrupts, 32 I/O ports */
-static struct device* dev_ibmtr[IBMTR_MAX_ADAPTERS];
+static struct net_device* dev_ibmtr[IBMTR_MAX_ADAPTERS];
 static int io[IBMTR_MAX_ADAPTERS] = {0xa20,0xa24};
 static int irq[IBMTR_MAX_ADAPTERS] = {0,0};
 static int mem[IBMTR_MAX_ADAPTERS] = {0,0};
@@ -1739,7 +1739,7 @@
 		dev_ibmtr[i]->init      = &ibmtr_probe;
 
 	        if (register_trdev(dev_ibmtr[i]) != 0) {
-			kfree_s(dev_ibmtr[i], sizeof(struct device));
+			kfree_s(dev_ibmtr[i], sizeof(struct net_device));
 			dev_ibmtr[i] = NULL;
 		        if (i == 0) {
 			        printk("ibmtr: register_trdev() returned non-zero.\n");
@@ -1762,7 +1762,7 @@
 			 free_irq(dev_ibmtr[i]->irq, dev_ibmtr[i]);
 			 release_region(dev_ibmtr[i]->base_addr, IBMTR_IO_EXTENT);
 			 kfree_s(dev_ibmtr[i]->priv, sizeof(struct tok_info));
-			 kfree_s(dev_ibmtr[i], sizeof(struct device));
+			 kfree_s(dev_ibmtr[i], sizeof(struct net_device));
 			 dev_ibmtr[i] = NULL;
                 }
 }
diff -u --recursive --new-file v2.3.13/linux/drivers/net/ipddp.c linux/drivers/net/ipddp.c
--- v2.3.13/linux/drivers/net/ipddp.c	Sun Nov  8 13:45:07 1998
+++ linux/drivers/net/ipddp.c	Wed Aug 18 11:36:42 1999
@@ -75,15 +75,15 @@
 static unsigned int ipddp_debug = IPDDP_DEBUG;
 
 /* Index to functions, as function prototypes. */
-static int ipddp_xmit(struct sk_buff *skb, struct device *dev);
-static struct net_device_stats *ipddp_get_stats(struct device *dev);
+static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev);
+static struct net_device_stats *ipddp_get_stats(struct net_device *dev);
 static int ipddp_create(struct ipddp_route *new_rt);
 static int ipddp_delete(struct ipddp_route *rt);
 static struct ipddp_route* ipddp_find_route(struct ipddp_route *rt);
-static int ipddp_ioctl(struct device *dev, struct ifreq *ifr, int cmd);
+static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
 
 
-static int ipddp_open(struct device *dev)
+static int ipddp_open(struct net_device *dev)
 {
 #ifdef MODULE
         MOD_INC_USE_COUNT;
@@ -92,7 +92,7 @@
         return 0;
 }
 
-static int ipddp_close(struct device *dev)
+static int ipddp_close(struct net_device *dev)
 {
 #ifdef MODULE
         MOD_DEC_USE_COUNT;
@@ -101,7 +101,7 @@
         return 0;
 }
 
-int ipddp_init(struct device *dev)
+int ipddp_init(struct net_device *dev)
 {
 	static unsigned version_printed = 0;
 
@@ -149,7 +149,7 @@
 /*
  * Get the current statistics. This may be called with the card open or closed.
  */
-static struct net_device_stats *ipddp_get_stats(struct device *dev)
+static struct net_device_stats *ipddp_get_stats(struct net_device *dev)
 {
         return (struct net_device_stats *)dev->priv;
 }
@@ -157,7 +157,7 @@
 /*
  * Transmit LLAP/ELAP frame using aarp_send_ddp.
  */
-static int ipddp_xmit(struct sk_buff *skb, struct device *dev)
+static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	u32 paddr = ((struct rtable*)skb->dst)->rt_gateway;
         struct ddpehdr *ddp;
@@ -297,7 +297,7 @@
         return (NULL);
 }
 
-static int ipddp_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
+static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
         struct ipddp_route *rt = (struct ipddp_route *)ifr->ifr_data;
 
@@ -324,7 +324,7 @@
 
 #ifdef MODULE	/* Module specific functions for ipddp.c */
 
-static struct device dev_ipddp=
+static struct net_device dev_ipddp=
 {
         "ipddp0\0   ",
                 0, 0, 0, 0,
diff -u --recursive --new-file v2.3.13/linux/drivers/net/ipddp.h linux/drivers/net/ipddp.h
--- v2.3.13/linux/drivers/net/ipddp.h	Thu Mar 12 10:54:12 1998
+++ linux/drivers/net/ipddp.h	Wed Aug 18 11:36:45 1999
@@ -13,7 +13,7 @@
 
 struct ipddp_route
 {
-        struct device *dev;             /* Carrier device */
+        struct net_device *dev;             /* Carrier device */
         __u32 ip;                       /* IP address */
         struct at_addr at;              /* Gateway appletalk address */
         int flags;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/irda/irport.c linux/drivers/net/irda/irport.c
--- v2.3.13/linux/drivers/net/irda/irport.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/irda/irport.c	Wed Aug 18 11:38:51 1999
@@ -79,9 +79,9 @@
 static int  irport_write(int iobase, int fifo_size, __u8 *buf, int len);
 static void irport_receive(struct irda_device *idev);
 
-static int  irport_net_init(struct device *dev);
-static int  irport_net_open(struct device *dev);
-static int  irport_net_close(struct device *dev);
+static int  irport_net_init(struct net_device *dev);
+static int  irport_net_open(struct net_device *dev);
+static int  irport_net_close(struct net_device *dev);
 static int  irport_is_receiving(struct irda_device *idev);
 static void irport_set_dtr_rts(struct irda_device *idev, int dtr, int rts);
 static int  irport_raw_write(struct irda_device *idev, __u8 *buf, int len);
@@ -413,7 +413,7 @@
  *    waits until the next transmitt interrupt, and continues until the
  *    frame is transmited.
  */
-int irport_hard_xmit(struct sk_buff *skb, struct device *dev)
+int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct irda_device *idev;
 	unsigned long flags;
@@ -555,7 +555,7 @@
 	spin_unlock(&idev->lock);
 }
 
-static int irport_net_init(struct device *dev)
+static int irport_net_init(struct net_device *dev)
 {
 	/* Set up to be a normal IrDA network device driver */
 	irda_device_setup(dev);
@@ -571,7 +571,7 @@
  *    
  *
  */
-static int irport_net_open(struct device *dev)
+static int irport_net_open(struct net_device *dev)
 {
 	struct irda_device *idev;
 	int iobase;
@@ -607,7 +607,7 @@
  *    
  *
  */
-static int irport_net_close(struct device *dev)
+static int irport_net_close(struct net_device *dev)
 {
 	struct irda_device *idev;
 	int iobase;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/irda/irtty.c linux/drivers/net/irda/irtty.c
--- v2.3.13/linux/drivers/net/irda/irtty.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/irda/irtty.c	Wed Aug 18 11:38:51 1999
@@ -44,14 +44,14 @@
 
 static int qos_mtt_bits = 0x03;      /* 5 ms or more */
 
-static int  irtty_hard_xmit(struct sk_buff *skb, struct device *dev);
+static int  irtty_hard_xmit(struct sk_buff *skb, struct net_device *dev);
 static void irtty_wait_until_sent(struct irda_device *driver);
 static int  irtty_is_receiving(struct irda_device *idev);
 static void irtty_set_dtr_rts(struct irda_device *idev, int dtr, int rts);
 static int  irtty_raw_write(struct irda_device *idev, __u8 *buf, int len);
-static int  irtty_net_init(struct device *dev);
-static int  irtty_net_open(struct device *dev);
-static int  irtty_net_close(struct device *dev);
+static int  irtty_net_init(struct net_device *dev);
+static int  irtty_net_open(struct net_device *dev);
+static int  irtty_net_close(struct net_device *dev);
 
 static int  irtty_open(struct tty_struct *tty);
 static void irtty_close(struct tty_struct *tty);
@@ -427,7 +427,7 @@
  *    Transmit frame
  *
  */
-static int irtty_hard_xmit(struct sk_buff *skb, struct device *dev)
+static int irtty_hard_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct irtty_cb *self;
 	struct irda_device *idev;
@@ -634,7 +634,7 @@
 	return actual;
 }
 
-static int irtty_net_init(struct device *dev)
+static int irtty_net_init(struct net_device *dev)
 {
 	/* Set up to be a normal IrDA network device driver */
 	irda_device_setup(dev);
@@ -644,7 +644,7 @@
 	return 0;
 }
 
-static int irtty_net_open(struct device *dev)
+static int irtty_net_open(struct net_device *dev)
 {
 	ASSERT(dev != NULL, return -1;);
 
@@ -658,7 +658,7 @@
 	return 0;
 }
 
-static int irtty_net_close(struct device *dev)
+static int irtty_net_close(struct net_device *dev)
 {
 	ASSERT(dev != NULL, return -1;);
 	
diff -u --recursive --new-file v2.3.13/linux/drivers/net/irda/pc87108.c linux/drivers/net/irda/pc87108.c
--- v2.3.13/linux/drivers/net/irda/pc87108.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/irda/pc87108.c	Wed Aug 18 11:38:51 1999
@@ -107,7 +107,7 @@
 static void pc87108_pio_receive(struct irda_device *idev);
 static int  pc87108_dma_receive(struct irda_device *idev); 
 static int  pc87108_dma_receive_complete(struct irda_device *idev, int iobase);
-static int  pc87108_hard_xmit(struct sk_buff *skb, struct device *dev);
+static int  pc87108_hard_xmit(struct sk_buff *skb, struct net_device *dev);
 static int  pc87108_pio_write(int iobase, __u8 *buf, int len, int fifo_size);
 static void pc87108_dma_write(struct irda_device *idev, int iobase);
 static void pc87108_change_speed(struct irda_device *idev, int baud);
@@ -117,9 +117,9 @@
 static int  pc87108_read_dongle_id (int iobase);
 static void pc87108_init_dongle_interface (int iobase, int dongle_id);
 
-static int  pc87108_net_init(struct device *dev);
-static int  pc87108_net_open(struct device *dev);
-static int  pc87108_net_close(struct device *dev);
+static int  pc87108_net_init(struct net_device *dev);
+static int  pc87108_net_open(struct net_device *dev);
+static int  pc87108_net_close(struct net_device *dev);
 
 /*
  * Function pc87108_init ()
@@ -712,7 +712,7 @@
  *    Transmit the frame!
  *
  */
-static int pc87108_hard_xmit( struct sk_buff *skb, struct device *dev)
+static int pc87108_hard_xmit( struct sk_buff *skb, struct net_device *dev)
 {
 	struct irda_device *idev;
 	int iobase;
@@ -1344,7 +1344,7 @@
  *    Initialize network device
  *
  */
-static int pc87108_net_init( struct device *dev)
+static int pc87108_net_init( struct net_device *dev)
 {
 	DEBUG( 4, __FUNCTION__ "()\n");
 
@@ -1363,7 +1363,7 @@
  *    Start the device
  *
  */
-static int pc87108_net_open( struct device *dev)
+static int pc87108_net_open( struct net_device *dev)
 {
 	struct irda_device *idev;
 	int iobase;
@@ -1418,7 +1418,7 @@
  *    Stop the device
  *
  */
-static int pc87108_net_close(struct device *dev)
+static int pc87108_net_close(struct net_device *dev)
 {
 	struct irda_device *idev;
 	int iobase;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/irda/smc-ircc.c linux/drivers/net/irda/smc-ircc.c
--- v2.3.13/linux/drivers/net/irda/smc-ircc.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/irda/smc-ircc.c	Wed Aug 18 11:38:52 1999
@@ -63,16 +63,16 @@
 static int  ircc_probe( int iobase, int board_addr);
 static int  ircc_dma_receive( struct irda_device *idev); 
 static int  ircc_dma_receive_complete(struct irda_device *idev, int iobase);
-static int  ircc_hard_xmit( struct sk_buff *skb, struct device *dev);
+static int  ircc_hard_xmit( struct sk_buff *skb, struct net_device *dev);
 static void ircc_dma_write( struct irda_device *idev, int iobase);
 static void ircc_change_speed( struct irda_device *idev, int baud);
 static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static void ircc_wait_until_sent( struct irda_device *idev);
 static int  ircc_is_receiving( struct irda_device *idev);
 
-static int  ircc_net_init( struct device *dev);
-static int  ircc_net_open( struct device *dev);
-static int  ircc_net_close( struct device *dev);
+static int  ircc_net_init( struct net_device *dev);
+static int  ircc_net_open( struct net_device *dev);
+static int  ircc_net_close( struct net_device *dev);
 
 static int ircc_debug=3;
 static int ircc_irq=255;
@@ -448,7 +448,7 @@
  *    Transmit the frame!
  *
  */
-static int ircc_hard_xmit( struct sk_buff *skb, struct device *dev)
+static int ircc_hard_xmit( struct sk_buff *skb, struct net_device *dev)
 {
 	struct irda_device *idev;
 	int iobase;
@@ -835,7 +835,7 @@
  *    Initialize network device
  *
  */
-static int ircc_net_init( struct device *dev)
+static int ircc_net_init( struct net_device *dev)
 {
 	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
 
@@ -855,7 +855,7 @@
  *    Start the device
  *
  */
-static int ircc_net_open( struct device *dev)
+static int ircc_net_open( struct net_device *dev)
 {
 	struct irda_device *idev;
 	int iobase;
@@ -902,7 +902,7 @@
  *    Stop the device
  *
  */
-static int ircc_net_close(struct device *dev)
+static int ircc_net_close(struct net_device *dev)
 {
 	struct irda_device *idev;
 	int iobase;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/irda/toshoboe.c linux/drivers/net/irda/toshoboe.c
--- v2.3.13/linux/drivers/net/irda/toshoboe.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/irda/toshoboe.c	Wed Aug 18 11:38:51 1999
@@ -267,7 +267,7 @@
 
 /*Transmit something */
 static int 
-toshoboe_hard_xmit (struct sk_buff *skb, struct device *dev)
+toshoboe_hard_xmit (struct sk_buff *skb, struct net_device *dev)
 {
   struct irda_device *idev;
   struct toshoboe_cb *self;
@@ -515,7 +515,7 @@
 
 
 static int 
-toshoboe_net_init (struct device *dev)
+toshoboe_net_init (struct net_device *dev)
 {
   DEBUG (4, __FUNCTION__ "()\n");
 
@@ -530,7 +530,7 @@
 
 
 static int 
-toshoboe_net_open (struct device *dev)
+toshoboe_net_open (struct net_device *dev)
 {
   struct irda_device *idev;
   struct toshoboe_cb *self;
@@ -594,7 +594,7 @@
 }
 
 static int 
-toshoboe_net_close (struct device *dev)
+toshoboe_net_close (struct net_device *dev)
 {
   struct irda_device *idev;
   struct toshoboe_cb *self;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/irda/uircc.c linux/drivers/net/irda/uircc.c
--- v2.3.13/linux/drivers/net/irda/uircc.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/irda/uircc.c	Wed Aug 18 11:38:51 1999
@@ -71,16 +71,16 @@
 static int  uircc_probe(int iobase, int board_addr, int irq, int dma);
 static int  uircc_dma_receive(struct irda_device *idev); 
 static int  uircc_dma_receive_complete(struct irda_device *idev, int iobase);
-static int  uircc_hard_xmit(struct sk_buff *skb, struct device *dev);
+static int  uircc_hard_xmit(struct sk_buff *skb, struct net_device *dev);
 static void uircc_dma_write(struct irda_device *idev, int iobase);
 static void uircc_change_speed(struct irda_device *idev, int baud);
 static void uircc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static void uircc_wait_until_sent(struct irda_device *idev);
 static int  uircc_is_receiving(struct irda_device *idev);
 static int uircc_toshiba_cmd(int *retval, int arg0, int arg1, int arg2);
-static int  uircc_net_init(struct device *dev);
-static int  uircc_net_open(struct device *dev);
-static int  uircc_net_close(struct device *dev);
+static int  uircc_net_init(struct net_device *dev);
+static int  uircc_net_open(struct net_device *dev);
+static int  uircc_net_close(struct net_device *dev);
 
 /*
  * Function uircc_init ()
@@ -406,7 +406,7 @@
  *    Transmit the frame!
  *
  */
-static int uircc_hard_xmit(struct sk_buff *skb, struct device *dev)
+static int uircc_hard_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct irda_device *idev;
 	int iobase;
@@ -798,7 +798,7 @@
  *    Initialize network device
  *
  */
-static int uircc_net_init( struct device *dev)
+static int uircc_net_init( struct net_device *dev)
 {
 	DEBUG( 4, __FUNCTION__ "()\n");
 
@@ -817,7 +817,7 @@
  *    Start the device
  *
  */
-static int uircc_net_open(struct device *dev)
+static int uircc_net_open(struct net_device *dev)
 {
 	struct irda_device *idev;
 	int iobase;
@@ -863,7 +863,7 @@
  *    Stop the device
  *
  */
-static int uircc_net_close(struct device *dev)
+static int uircc_net_close(struct net_device *dev)
 {
 	struct irda_device *idev;
 	int iobase;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/irda/w83977af_ir.c linux/drivers/net/irda/w83977af_ir.c
--- v2.3.13/linux/drivers/net/irda/w83977af_ir.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/irda/w83977af_ir.c	Wed Aug 18 11:38:51 1999
@@ -87,7 +87,7 @@
 static int  w83977af_probe(int iobase, int irq, int dma);
 static int  w83977af_dma_receive(struct irda_device *idev); 
 static int  w83977af_dma_receive_complete(struct irda_device *idev);
-static int  w83977af_hard_xmit(struct sk_buff *skb, struct device *dev);
+static int  w83977af_hard_xmit(struct sk_buff *skb, struct net_device *dev);
 static int  w83977af_pio_write(int iobase, __u8 *buf, int len, int fifo_size);
 static void w83977af_dma_write(struct irda_device *idev, int iobase);
 static void w83977af_change_speed(struct irda_device *idev, int baud);
@@ -95,9 +95,9 @@
 static void w83977af_wait_until_sent(struct irda_device *idev);
 static int  w83977af_is_receiving(struct irda_device *idev);
 
-static int  w83977af_net_init(struct device *dev);
-static int  w83977af_net_open(struct device *dev);
-static int  w83977af_net_close(struct device *dev);
+static int  w83977af_net_init(struct net_device *dev);
+static int  w83977af_net_open(struct net_device *dev);
+static int  w83977af_net_close(struct net_device *dev);
 
 /*
  * Function w83977af_init ()
@@ -460,7 +460,7 @@
  *    Sets up a DMA transfer to send the current frame.
  *
  */
-int w83977af_hard_xmit(struct sk_buff *skb, struct device *dev)
+int w83977af_hard_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct irda_device *idev;
 	int iobase;
@@ -1155,7 +1155,7 @@
  *    
  *
  */
-static int w83977af_net_init(struct device *dev)
+static int w83977af_net_init(struct net_device *dev)
 {
 	DEBUG(0, __FUNCTION__ "()\n");
 
@@ -1174,7 +1174,7 @@
  *    Start the device
  *
  */
-static int w83977af_net_open(struct device *dev)
+static int w83977af_net_open(struct net_device *dev)
 {
 	struct irda_device *idev;
 	int iobase;
@@ -1233,7 +1233,7 @@
  *    Stop the device
  *
  */
-static int w83977af_net_close(struct device *dev)
+static int w83977af_net_close(struct net_device *dev)
 {
 	struct irda_device *idev;
 	int iobase;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/jazzsonic.c linux/drivers/net/jazzsonic.c
--- v2.3.13/linux/drivers/net/jazzsonic.c	Wed Jun 30 13:38:20 1999
+++ linux/drivers/net/jazzsonic.c	Wed Aug 18 11:36:42 1999
@@ -82,15 +82,15 @@
 
 /* Index to functions, as function prototypes. */
 
-extern int sonic_probe(struct device *dev);
-static int sonic_probe1(struct device *dev, unsigned int base_addr, unsigned int irq);
+extern int sonic_probe(struct net_device *dev);
+static int sonic_probe1(struct net_device *dev, unsigned int base_addr, unsigned int irq);
 
 
 /*
  * Probe for a SONIC ethernet controller on a Mips Jazz board.
  * Actually probing is superfluous but we're paranoid.
  */
-__initfunc(int sonic_probe(struct device *dev))
+__initfunc(int sonic_probe(struct net_device *dev))
 {
     unsigned int base_addr = dev ? dev->base_addr : 0;
     int i;
@@ -115,7 +115,7 @@
     return -ENODEV;
 }
 
-__initfunc(static int sonic_probe1(struct device *dev,
+__initfunc(static int sonic_probe1(struct net_device *dev,
                                    unsigned int base_addr, unsigned int irq))
 {
     static unsigned version_printed = 0;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/lance.c linux/drivers/net/lance.c
--- v2.3.13/linux/drivers/net/lance.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/lance.c	Wed Aug 18 11:36:42 1999
@@ -68,8 +68,8 @@
 #include <linux/skbuff.h>
 
 static unsigned int lance_portlist[] __initdata = { 0x300, 0x320, 0x340, 0x360, 0};
-int lance_probe(struct device *dev);
-int lance_probe1(struct device *dev, int ioaddr, int irq, int options);
+int lance_probe(struct net_device *dev);
+int lance_probe1(struct net_device *dev, int ioaddr, int irq, int options);
 
 #ifdef LANCE_DEBUG
 int lance_debug = LANCE_DEBUG;
@@ -283,15 +283,15 @@
    Assume yes until we know the memory size. */
 static unsigned char lance_need_isa_bounce_buffers = 1;
 
-static int lance_open(struct device *dev);
-static int lance_open_fail(struct device *dev);
-static void lance_init_ring(struct device *dev, int mode);
-static int lance_start_xmit(struct sk_buff *skb, struct device *dev);
-static int lance_rx(struct device *dev);
+static int lance_open(struct net_device *dev);
+static int lance_open_fail(struct net_device *dev);
+static void lance_init_ring(struct net_device *dev, int mode);
+static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int lance_rx(struct net_device *dev);
 static void lance_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static int lance_close(struct device *dev);
-static struct net_device_stats *lance_get_stats(struct device *dev);
-static void set_multicast_list(struct device *dev);
+static int lance_close(struct net_device *dev);
+static struct net_device_stats *lance_get_stats(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
 
 
 
@@ -308,7 +308,7 @@
 MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_CARDS) "i");
 
 static char ifnames[MAX_CARDS][IF_NAMELEN] = { {0, }, };
-static struct device dev_lance[MAX_CARDS] =
+static struct net_device dev_lance[MAX_CARDS] =
 {{
     0, /* device name is inserted by linux/drivers/net/net_init.c */
 	0, 0, 0, 0,
@@ -320,7 +320,7 @@
 	int this_dev, found = 0;
 
 	for (this_dev = 0; this_dev < MAX_CARDS; this_dev++) {
-		struct device *dev = &dev_lance[this_dev];
+		struct net_device *dev = &dev_lance[this_dev];
 		dev->name = ifnames[this_dev];
 		dev->irq = irq[this_dev];
 		dev->base_addr = io[this_dev];
@@ -347,7 +347,7 @@
 	int this_dev;
 
 	for (this_dev = 0; this_dev < MAX_CARDS; this_dev++) {
-		struct device *dev = &dev_lance[this_dev];
+		struct net_device *dev = &dev_lance[this_dev];
 		if (dev->priv != NULL) {
 			kfree(dev->priv);
 			dev->priv = NULL;
@@ -363,7 +363,7 @@
    board probes now that kmalloc() can allocate ISA DMA-able regions.
    This also allows the LANCE driver to be used as a module.
    */
-int lance_probe(struct device *dev)
+int lance_probe(struct net_device *dev)
 {
 	int *port, result;
 
@@ -420,7 +420,7 @@
 	return -ENODEV;
 }
 
-int __init lance_probe1(struct device *dev, int ioaddr, int irq, int options)
+int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int options)
 {
 	struct lance_private *lp;
 	short dma_channels;					/* Mark spuriously-busy DMA channels */
@@ -677,7 +677,7 @@
 }
 
 static int
-lance_open_fail(struct device *dev)
+lance_open_fail(struct net_device *dev)
 {
 	return -ENODEV;
 }
@@ -685,7 +685,7 @@
 
 
 static int
-lance_open(struct device *dev)
+lance_open(struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -776,7 +776,7 @@
 */
 
 static void 
-lance_purge_tx_ring(struct device *dev)
+lance_purge_tx_ring(struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *)dev->priv;
 	int i;
@@ -792,7 +792,7 @@
 
 /* Initialize the LANCE Rx and Tx rings. */
 static void
-lance_init_ring(struct device *dev, int gfp)
+lance_init_ring(struct net_device *dev, int gfp)
 {
 	struct lance_private *lp = (struct lance_private *)dev->priv;
 	int i;
@@ -835,7 +835,7 @@
 }
 
 static void
-lance_restart(struct device *dev, unsigned int csr0_bits, int must_reinit)
+lance_restart(struct net_device *dev, unsigned int csr0_bits, int must_reinit)
 {
 	struct lance_private *lp = (struct lance_private *)dev->priv;
 
@@ -848,7 +848,7 @@
 	outw(csr0_bits, dev->base_addr + LANCE_DATA);
 }
 
-static int lance_start_xmit(struct sk_buff *skb, struct device *dev)
+static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -967,7 +967,7 @@
 static void
 lance_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
-	struct device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	struct lance_private *lp;
 	int csr0, ioaddr, boguscnt=10;
 	int must_restart;
@@ -1093,7 +1093,7 @@
 }
 
 static int
-lance_rx(struct device *dev)
+lance_rx(struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *)dev->priv;
 	int entry = lp->cur_rx & RX_RING_MOD_MASK;
@@ -1171,7 +1171,7 @@
 }
 
 static int
-lance_close(struct device *dev)
+lance_close(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr;
 	struct lance_private *lp = (struct lance_private *)dev->priv;
@@ -1220,7 +1220,7 @@
 	return 0;
 }
 
-static struct net_device_stats *lance_get_stats(struct device *dev)
+static struct net_device_stats *lance_get_stats(struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *)dev->priv;
 	short ioaddr = dev->base_addr;
@@ -1243,7 +1243,7 @@
 /* Set or clear the multicast filter for this adaptor.
  */
 
-static void set_multicast_list(struct device *dev)
+static void set_multicast_list(struct net_device *dev)
 {
 	short ioaddr = dev->base_addr;
 
diff -u --recursive --new-file v2.3.13/linux/drivers/net/lapbether.c linux/drivers/net/lapbether.c
--- v2.3.13/linux/drivers/net/lapbether.c	Tue May 25 13:06:34 1999
+++ linux/drivers/net/lapbether.c	Wed Aug 18 11:36:42 1999
@@ -45,7 +45,7 @@
 
 static char bcast_addr[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
 
-static int lapbeth_rcv(struct sk_buff *, struct device *, struct packet_type *);
+static int lapbeth_rcv(struct sk_buff *, struct net_device *, struct packet_type *);
 static int lapbeth_device_event(struct notifier_block *, unsigned long, void *);
 
 static struct packet_type lapbeth_packet_type = {
@@ -67,8 +67,8 @@
 static struct lapbethdev {
 	struct lapbethdev *next;
 	char   ethname[14];		/* ether device name */
-	struct device *ethdev;		/* link to ethernet device */
-	struct device axdev;		/* lapbeth device (lapb#) */
+	struct net_device *ethdev;		/* link to ethernet device */
+	struct net_device axdev;		/* lapbeth device (lapb#) */
 	struct net_device_stats stats;	/* some statistics */
 } *lapbeth_devices = NULL;
 
@@ -79,7 +79,7 @@
 /*
  *	Get the ethernet device for a LAPB device
  */
-static __inline__ struct device *lapbeth_get_ether_dev(struct device *dev)
+static __inline__ struct net_device *lapbeth_get_ether_dev(struct net_device *dev)
 {
 	struct lapbethdev *lapbeth;
 	
@@ -91,7 +91,7 @@
 /*
  *	Get the LAPB device for the ethernet device
  */
-static __inline__ struct device *lapbeth_get_x25_dev(struct device *dev)
+static __inline__ struct net_device *lapbeth_get_x25_dev(struct net_device *dev)
 {
 	struct lapbethdev *lapbeth;
 
@@ -102,7 +102,7 @@
 	return NULL;
 }
 
-static __inline__ int dev_is_ethdev(struct device *dev)
+static __inline__ int dev_is_ethdev(struct net_device *dev)
 {
 	return (
 			dev->type == ARPHRD_ETHER
@@ -114,7 +114,7 @@
  *	Sanity check: remove all devices that ceased to exists and
  *	return '1' if the given LAPB device was affected.
  */
-static int lapbeth_check_devices(struct device *dev)
+static int lapbeth_check_devices(struct net_device *dev)
 {
 	struct lapbethdev *lapbeth, *lapbeth_prev;
 	int result = 0;
@@ -154,7 +154,7 @@
 /*
  *	Receive a LAPB frame via an ethernet interface.
  */
-static int lapbeth_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *ptype)
+static int lapbeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype)
 {
 	int len, err;
 	struct lapbethdev *lapbeth;
@@ -204,7 +204,7 @@
 /*
  * 	Send a LAPB frame via an ethernet interface
  */
-static int lapbeth_xmit(struct sk_buff *skb, struct device *dev)
+static int lapbeth_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct lapbethdev *lapbeth;
 	int err;
@@ -254,7 +254,7 @@
 {
 	struct lapbethdev *lapbeth = (struct lapbethdev *)token;
 	unsigned char *ptr;
-	struct device *dev;
+	struct net_device *dev;
 	int size;
 
 	skb->protocol = htons(ETH_P_X25);
@@ -322,7 +322,7 @@
 /*
  *	Statistics
  */
-static struct net_device_stats *lapbeth_get_stats(struct device *dev)
+static struct net_device_stats *lapbeth_get_stats(struct net_device *dev)
 {
 	struct lapbethdev *lapbeth;
 
@@ -334,7 +334,7 @@
 /*
  *	Set AX.25 callsign
  */
-static int lapbeth_set_mac_address(struct device *dev, void *addr)
+static int lapbeth_set_mac_address(struct net_device *dev, void *addr)
 {
     struct sockaddr *sa = (struct sockaddr *)addr;
 
@@ -343,7 +343,7 @@
     return 0;
 }
 
-static int lapbeth_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
+static int lapbeth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	return -EINVAL;
 }
@@ -351,7 +351,7 @@
 /*
  * open/close a device
  */
-static int lapbeth_open(struct device *dev)
+static int lapbeth_open(struct net_device *dev)
 {
 	struct lapb_register_struct lapbeth_callbacks;
 	struct lapbethdev *lapbeth;
@@ -384,7 +384,7 @@
 	return 0;
 }
 
-static int lapbeth_close(struct device *dev)
+static int lapbeth_close(struct net_device *dev)
 {
 	struct lapbethdev *lapbeth;
 	int err;
@@ -402,7 +402,7 @@
 	return 0;
 }
 
-static int lapbeth_dev_init(struct device *dev)
+static int lapbeth_dev_init(struct net_device *dev)
 {
 	return 0;
 }
@@ -412,7 +412,7 @@
 /*
  *	Setup a new device.
  */
-static int lapbeth_new_device(struct device *dev)
+static int lapbeth_new_device(struct net_device *dev)
 {
 	int k;
 	unsigned char *buf;
@@ -432,7 +432,7 @@
 	buf = kmalloc(14, GFP_KERNEL);
 
 	for (k = 0; k < MAXLAPBDEV; k++) {
-		struct device *odev;
+		struct net_device *odev;
 
 		sprintf(buf, "lapb%d", k);
 
@@ -490,7 +490,7 @@
  */
 static int lapbeth_device_event(struct notifier_block *this,unsigned long event, void *ptr)
 {
-	struct device *dev = (struct device *)ptr;
+	struct net_device *dev = (struct net_device *)ptr;
 	
 	if (!dev_is_ethdev(dev))
 		return NOTIFY_DONE;
@@ -524,7 +524,7 @@
  */
 int lapbeth_init(void)
 {
-	struct device *dev;
+	struct net_device *dev;
 
 	lapbeth_packet_type.type  = htons(ETH_P_DEC);
 	dev_add_pack(&lapbeth_packet_type);
diff -u --recursive --new-file v2.3.13/linux/drivers/net/lne390.c linux/drivers/net/lne390.c
--- v2.3.13/linux/drivers/net/lne390.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/lne390.c	Wed Aug 18 11:36:42 1999
@@ -46,17 +46,17 @@
 #include <linux/etherdevice.h>
 #include "8390.h"
 
-int lne390_probe(struct device *dev);
-int lne390_probe1(struct device *dev, int ioaddr);
+int lne390_probe(struct net_device *dev);
+int lne390_probe1(struct net_device *dev, int ioaddr);
 
-static int lne390_open(struct device *dev);
-static int lne390_close(struct device *dev);
+static int lne390_open(struct net_device *dev);
+static int lne390_close(struct net_device *dev);
 
-static void lne390_reset_8390(struct device *dev);
+static void lne390_reset_8390(struct net_device *dev);
 
-static void lne390_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page);
-static void lne390_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset);
-static void lne390_block_output(struct device *dev, int count, const unsigned char *buf, const int start_page);
+static void lne390_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page);
+static void lne390_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset);
+static void lne390_block_output(struct net_device *dev, int count, const unsigned char *buf, const int start_page);
 
 #define LNE390_START_PG		0x00    /* First page of TX buffer	*/
 #define LNE390_STOP_PG		0x80    /* Last page +1 of RX ring	*/
@@ -100,7 +100,7 @@
  *	PROM for a match against the value assigned to Mylex.
  */
 
-int __init lne390_probe(struct device *dev)
+int __init lne390_probe(struct net_device *dev)
 {
 	unsigned short ioaddr = dev->base_addr;
 
@@ -127,7 +127,7 @@
 	return ENODEV;
 }
 
-int __init lne390_probe1(struct device *dev, int ioaddr)
+int __init lne390_probe1(struct net_device *dev, int ioaddr)
 {
 	int i, revision;
 	unsigned long eisa_id;
@@ -281,7 +281,7 @@
  *	file, this just toggles the "Board Enable" bits (bit 2 and 0).
  */
 
-static void lne390_reset_8390(struct device *dev)
+static void lne390_reset_8390(struct net_device *dev)
 {
 	unsigned short ioaddr = dev->base_addr;
 
@@ -313,7 +313,7 @@
  */
 
 static void
-lne390_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+lne390_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 {
 	unsigned long hdr_start = dev->mem_start + ((ring_page - LNE390_START_PG)<<8);
 	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
@@ -326,7 +326,7 @@
  *	be rounded up to a doubleword value via lne390_get_8390_hdr() above.
  */
 
-static void lne390_block_input(struct device *dev, int count, struct sk_buff *skb,
+static void lne390_block_input(struct net_device *dev, int count, struct sk_buff *skb,
 						  int ring_offset)
 {
 	unsigned long xfer_start = dev->mem_start + ring_offset - (LNE390_START_PG<<8);
@@ -343,7 +343,7 @@
 	}
 }
 
-static void lne390_block_output(struct device *dev, int count,
+static void lne390_block_output(struct net_device *dev, int count,
 				const unsigned char *buf, int start_page)
 {
 	unsigned long shmem = dev->mem_start + ((start_page - LNE390_START_PG)<<8);
@@ -352,14 +352,14 @@
 	memcpy_toio(shmem, buf, count);
 }
 
-static int lne390_open(struct device *dev)
+static int lne390_open(struct net_device *dev)
 {
 	ei_open(dev);
 	MOD_INC_USE_COUNT;
 	return 0;
 }
 
-static int lne390_close(struct device *dev)
+static int lne390_close(struct net_device *dev)
 {
 
 	if (ei_debug > 1)
@@ -374,7 +374,7 @@
 #define MAX_LNE_CARDS	4	/* Max number of LNE390 cards per module */
 #define NAMELEN		8	/* # of chars for storing dev->name */
 static char namelist[NAMELEN * MAX_LNE_CARDS] = { 0, };
-static struct device dev_lne[MAX_LNE_CARDS] = {
+static struct net_device dev_lne[MAX_LNE_CARDS] = {
 	{
 		NULL,		/* assign a chunk of namelist[] below */
 		0, 0, 0, 0,
@@ -396,7 +396,7 @@
 	int this_dev, found = 0;
 
 	for (this_dev = 0; this_dev < MAX_LNE_CARDS; this_dev++) {
-		struct device *dev = &dev_lne[this_dev];
+		struct net_device *dev = &dev_lne[this_dev];
 		dev->name = namelist+(NAMELEN*this_dev);
 		dev->irq = irq[this_dev];
 		dev->base_addr = io[this_dev];
@@ -423,7 +423,7 @@
 	int this_dev;
 
 	for (this_dev = 0; this_dev < MAX_LNE_CARDS; this_dev++) {
-		struct device *dev = &dev_lne[this_dev];
+		struct net_device *dev = &dev_lne[this_dev];
 		if (dev->priv != NULL) {
 			void *priv = dev->priv;
 			free_irq(dev->irq, dev);
diff -u --recursive --new-file v2.3.13/linux/drivers/net/loopback.c linux/drivers/net/loopback.c
--- v2.3.13/linux/drivers/net/loopback.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/loopback.c	Wed Aug 18 11:36:42 1999
@@ -58,7 +58,7 @@
  * The higher levels take care of making this non-reentrant (it's
  * called with bh's disabled).
  */
-static int loopback_xmit(struct sk_buff *skb, struct device *dev)
+static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct net_device_stats *stats = (struct net_device_stats *)dev->priv;
 
@@ -102,19 +102,19 @@
 	return(0);
 }
 
-static struct net_device_stats *get_stats(struct device *dev)
+static struct net_device_stats *get_stats(struct net_device *dev)
 {
 	return (struct net_device_stats *)dev->priv;
 }
 
-static int loopback_open(struct device *dev)
+static int loopback_open(struct net_device *dev)
 {
 	dev->flags|=IFF_LOOPBACK;
 	return 0;
 }
 
 /* Initialize the rest of the LOOPBACK device. */
-int __init loopback_init(struct device *dev)
+int __init loopback_init(struct net_device *dev)
 {
 	dev->mtu		= LOOPBACK_MTU;
 	dev->tbusy		= 0;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/ltpc.c linux/drivers/net/ltpc.c
--- v2.3.13/linux/drivers/net/ltpc.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/ltpc.c	Wed Aug 18 11:36:42 1999
@@ -240,9 +240,9 @@
 #include "ltpc.h"
 
 /* function prototypes */
-static int do_read(struct device *dev, void *cbuf, int cbuflen,
+static int do_read(struct net_device *dev, void *cbuf, int cbuflen,
 	void *dbuf, int dbuflen);
-static int sendup_buffer (struct device *dev);
+static int sendup_buffer (struct net_device *dev);
 
 /* Dma Memory related stuff, cribbed directly from 3c505.c */
 
@@ -348,7 +348,7 @@
 static unsigned char mailbox[16];
 static unsigned char mboxinuse[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
 
-static int wait_timeout(struct device *dev, int c)
+static int wait_timeout(struct net_device *dev, int c)
 {
 	/* returns true if it stayed c */
 	/* this uses base+6, but it's ok */
@@ -383,7 +383,7 @@
 }
 
 /* read a command from the card */
-static void handlefc(struct device *dev)
+static void handlefc(struct net_device *dev)
 {
 	/* called *only* from idle, non-reentrant */
 	int dma = dev->dma;
@@ -407,7 +407,7 @@
 }
 
 /* read data from the card */
-static void handlefd(struct device *dev)
+static void handlefd(struct net_device *dev)
 {
 	int dma = dev->dma;
 	int base = dev->base_addr;
@@ -429,7 +429,7 @@
 	sendup_buffer(dev);
 } 
 
-static void handlewrite(struct device *dev)
+static void handlewrite(struct net_device *dev)
 {
 	/* called *only* from idle, non-reentrant */
 	/* on entry, 0xfb and ltdmabuf holds data */
@@ -457,7 +457,7 @@
 	}
 }
 
-static void handleread(struct device *dev)
+static void handleread(struct net_device *dev)
 {
 	/* on entry, 0xfb */
 	/* on exit, ltdmabuf holds data */
@@ -480,7 +480,7 @@
 	if ( wait_timeout(dev,0xfb) ) printk("timed out in handleread\n");
 }
 
-static void handlecommand(struct device *dev)
+static void handlecommand(struct net_device *dev)
 {
 	/* on entry, 0xfa and ltdmacbuf holds command */
 	int dma = dev->dma;
@@ -510,7 +510,7 @@
  * an interrupt, or because the line is tri-stated
  */
 
-static void idle(struct device *dev)
+static void idle(struct net_device *dev)
 {
 	unsigned long flags;
 	int state;
@@ -665,7 +665,7 @@
 }
 
 
-static int do_write(struct device *dev, void *cbuf, int cbuflen,
+static int do_write(struct net_device *dev, void *cbuf, int cbuflen,
 	void *dbuf, int dbuflen)
 {
 
@@ -689,7 +689,7 @@
 	return -1;
 }
 
-static int do_read(struct device *dev, void *cbuf, int cbuflen,
+static int do_read(struct net_device *dev, void *cbuf, int cbuflen,
 	void *dbuf, int dbuflen)
 {
 
@@ -717,10 +717,10 @@
 
 static struct timer_list ltpc_timer;
 
-static int ltpc_xmit(struct sk_buff *skb, struct device *dev);
-static struct net_device_stats *ltpc_get_stats(struct device *dev);
+static int ltpc_xmit(struct sk_buff *skb, struct net_device *dev);
+static struct net_device_stats *ltpc_get_stats(struct net_device *dev);
 
-static int ltpc_open(struct device *dev)
+static int ltpc_open(struct net_device *dev)
 {
 #ifdef MODULE
 	MOD_INC_USE_COUNT;
@@ -728,7 +728,7 @@
 	return 0;
 }
 
-static int ltpc_close(struct device *dev)
+static int ltpc_close(struct net_device *dev)
 {
 #ifdef MODULE
 	MOD_DEC_USE_COUNT;
@@ -736,14 +736,14 @@
 	return 0;
 }
 
-static int read_30 ( struct device *dev)
+static int read_30 ( struct net_device *dev)
 {
 	lt_command c;
 	c.getflags.command = LT_GETFLAGS;
 	return do_read(dev, &c, sizeof(c.getflags),&c,0);
 }
 
-static int set_30 (struct device *dev,int x)
+static int set_30 (struct net_device *dev,int x)
 {
 	lt_command c;
 	c.setflags.command = LT_SETFLAGS;
@@ -753,7 +753,7 @@
 
 /* LLAP to DDP translation */
 
-static int sendup_buffer (struct device *dev)
+static int sendup_buffer (struct net_device *dev)
 {
 	/* on entry, command is in ltdmacbuf, data in ltdmabuf */
 	/* called from idle, non-reentrant */
@@ -825,7 +825,7 @@
  
 static void ltpc_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
 {
-	struct device *dev = dev_id;
+	struct net_device *dev = dev_id;
 
 	if (dev==NULL) {
 		printk("ltpc_interrupt: unknown device.\n");
@@ -852,7 +852,7 @@
  *
  ***/
 
-static int ltpc_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
+static int ltpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	struct sockaddr_at *sa = (struct sockaddr_at *) &ifr->ifr_addr;
 	/* we'll keep the localtalk node address in dev->pa_addr */
@@ -897,13 +897,13 @@
 	}
 }
 
-static void set_multicast_list(struct device *dev)
+static void set_multicast_list(struct net_device *dev)
 {
 	/* This needs to be present to keep netatalk happy. */
 	/* Actually netatalk needs fixing! */
 }
 
-static int ltpc_hard_header (struct sk_buff *skb, struct device *dev, 
+static int ltpc_hard_header (struct sk_buff *skb, struct net_device *dev, 
 	unsigned short type, void *daddr, void *saddr, unsigned len)
 {
 	if(debug&DEBUG_VERBOSE)
@@ -912,7 +912,7 @@
 	return 0;
 }
 
-static int ltpc_init(struct device *dev)
+static int ltpc_init(struct net_device *dev)
 {
 	/* Initialize the device structure. */
   
@@ -947,7 +947,7 @@
 
 static void ltpc_poll(unsigned long l)
 {
-	struct device *dev = (struct device *) l;
+	struct net_device *dev = (struct net_device *) l;
 
 	del_timer(&ltpc_timer);
 
@@ -970,7 +970,7 @@
 
 /* DDP to LLAP translation */
 
-static int ltpc_xmit(struct sk_buff *skb, struct device *dev)
+static int ltpc_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	/* in kernel 1.3.xx, on entry skb->data points to ddp header,
 	 * and skb->len is the length of the ddp data + ddp header
@@ -1010,7 +1010,7 @@
 	return 0;
 }
 
-static struct net_device_stats *ltpc_get_stats(struct device *dev)
+static struct net_device_stats *ltpc_get_stats(struct net_device *dev)
 {
 	struct net_device_stats *stats = &((struct ltpc_private *) dev->priv)->stats;
 	return stats;
@@ -1088,7 +1088,7 @@
 	return dma;
 }
 
-int __init ltpc_probe(struct device *dev)
+int __init ltpc_probe(struct net_device *dev)
 {
 	int err;
 	int x=0,y=0;
@@ -1281,7 +1281,7 @@
 
 static char dev_name[8];
 
-static struct device dev_ltpc = {
+static struct net_device dev_ltpc = {
 		dev_name, 
 		0, 0, 0, 0,
 	 	0x0, 0,
diff -u --recursive --new-file v2.3.13/linux/drivers/net/mace.c linux/drivers/net/mace.c
--- v2.3.13/linux/drivers/net/mace.c	Wed Jul 21 15:46:48 1999
+++ linux/drivers/net/mace.c	Wed Aug 18 11:36:42 1999
@@ -23,7 +23,7 @@
 #include "mace.h"
 
 #ifdef MODULE
-static struct device *mace_devs = NULL;
+static struct net_device *mace_devs = NULL;
 #endif
 
 #define N_RX_RING	8
@@ -69,21 +69,21 @@
 	+ (N_RX_RING + NCMDS_TX * N_TX_RING + 3) * sizeof(struct dbdma_cmd))
 
 static int bitrev(int);
-static int mace_open(struct device *dev);
-static int mace_close(struct device *dev);
-static int mace_xmit_start(struct sk_buff *skb, struct device *dev);
-static struct net_device_stats *mace_stats(struct device *dev);
-static void mace_set_multicast(struct device *dev);
-static void mace_reset(struct device *dev);
-static int mace_set_address(struct device *dev, void *addr);
+static int mace_open(struct net_device *dev);
+static int mace_close(struct net_device *dev);
+static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev);
+static struct net_device_stats *mace_stats(struct net_device *dev);
+static void mace_set_multicast(struct net_device *dev);
+static void mace_reset(struct net_device *dev);
+static int mace_set_address(struct net_device *dev, void *addr);
 static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static void mace_txdma_intr(int irq, void *dev_id, struct pt_regs *regs);
 static void mace_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs);
-static void mace_set_timeout(struct device *dev);
+static void mace_set_timeout(struct net_device *dev);
 static void mace_tx_timeout(unsigned long data);
 static inline void dbdma_reset(volatile struct dbdma_regs *dma);
 static inline void mace_clean_rings(struct mace_data *mp);
-static void __mace_set_address(struct device *dev, void *addr);
+static void __mace_set_address(struct net_device *dev, void *addr);
 
 /*
  * If we can't get a skbuff when we need it, we use this area for DMA.
@@ -102,7 +102,7 @@
 }
 
 int
-mace_probe(struct device *dev)
+mace_probe(struct net_device *dev)
 {
 	int j, rev;
 	struct mace_data *mp;
@@ -222,7 +222,7 @@
 	    udelay(1);
 }
 
-static void mace_reset(struct device *dev)
+static void mace_reset(struct net_device *dev)
 {
     struct mace_data *mp = (struct mace_data *) dev->priv;
     volatile struct mace *mb = mp->mace;
@@ -269,7 +269,7 @@
     out_8(&mb->plscc, PORTSEL_GPSI + ENPLSIO);
 }
 
-static void __mace_set_address(struct device *dev, void *addr)
+static void __mace_set_address(struct net_device *dev, void *addr)
 {
     volatile struct mace *mb = ((struct mace_data *) dev->priv)->mace;
     unsigned char *p = addr;
@@ -283,7 +283,7 @@
 	out_8(&mb->padr, dev->dev_addr[i] = p[i]);
 }
 
-static int mace_set_address(struct device *dev, void *addr)
+static int mace_set_address(struct net_device *dev, void *addr)
 {
     struct mace_data *mp = (struct mace_data *) dev->priv;
     volatile struct mace *mb = mp->mace;
@@ -301,7 +301,7 @@
     return 0;
 }
 
-static int mace_open(struct device *dev)
+static int mace_open(struct net_device *dev)
 {
     struct mace_data *mp = (struct mace_data *) dev->priv;
     volatile struct mace *mb = mp->mace;
@@ -392,7 +392,7 @@
     }
 }
 
-static int mace_close(struct device *dev)
+static int mace_close(struct net_device *dev)
 {
     struct mace_data *mp = (struct mace_data *) dev->priv;
     volatile struct mace *mb = mp->mace;
@@ -416,7 +416,7 @@
     return 0;
 }
 
-static inline void mace_set_timeout(struct device *dev)
+static inline void mace_set_timeout(struct net_device *dev)
 {
     struct mace_data *mp = (struct mace_data *) dev->priv;
     unsigned long flags;
@@ -433,7 +433,7 @@
     restore_flags(flags);
 }
 
-static int mace_xmit_start(struct sk_buff *skb, struct device *dev)
+static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev)
 {
     struct mace_data *mp = (struct mace_data *) dev->priv;
     volatile struct dbdma_regs *td = mp->tx_dma;
@@ -489,7 +489,7 @@
     return 0;
 }
 
-static struct net_device_stats *mace_stats(struct device *dev)
+static struct net_device_stats *mace_stats(struct net_device *dev)
 {
     struct mace_data *p = (struct mace_data *) dev->priv;
 
@@ -501,7 +501,7 @@
  */
 #define CRC_POLY	0xedb88320
 
-static void mace_set_multicast(struct device *dev)
+static void mace_set_multicast(struct net_device *dev)
 {
     struct mace_data *mp = (struct mace_data *) dev->priv;
     volatile struct mace *mb = mp->mace;
@@ -579,7 +579,7 @@
 
 static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-    struct device *dev = (struct device *) dev_id;
+    struct net_device *dev = (struct net_device *) dev_id;
     struct mace_data *mp = (struct mace_data *) dev->priv;
     volatile struct mace *mb = mp->mace;
     volatile struct dbdma_regs *td = mp->tx_dma;
@@ -722,7 +722,7 @@
 
 static void mace_tx_timeout(unsigned long data)
 {
-    struct device *dev = (struct device *) data;
+    struct net_device *dev = (struct net_device *) data;
     struct mace_data *mp = (struct mace_data *) dev->priv;
     volatile struct mace *mb = mp->mace;
     volatile struct dbdma_regs *td = mp->tx_dma;
@@ -794,7 +794,7 @@
 
 static void mace_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
-    struct device *dev = (struct device *) dev_id;
+    struct net_device *dev = (struct net_device *) dev_id;
     struct mace_data *mp = (struct mace_data *) dev->priv;
     volatile struct dbdma_regs *rd = mp->rx_dma;
     volatile struct dbdma_cmd *cp, *np;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/macsonic.c linux/drivers/net/macsonic.c
--- v2.3.13/linux/drivers/net/macsonic.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/macsonic.c	Wed Aug 18 11:36:42 1999
@@ -176,7 +176,7 @@
 
 __initfunc(int mac_onboard_sonic_probe(void))
 {
-	struct device *dev;
+	struct net_device *dev;
 	unsigned int silicon_revision;
 	unsigned int val;
 	struct sonic_local *lp;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/mvme147.c linux/drivers/net/mvme147.c
--- v2.3.13/linux/drivers/net/mvme147.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/mvme147.c	Wed Aug 18 11:36:42 1999
@@ -54,9 +54,9 @@
  * plus board-specific init, open and close actions.
  * Oh, and we need to tell the generic code how to read and write LANCE registers...
  */
-int mvme147lance_probe(struct device *dev);
-static int m147lance_open(struct device *dev);
-static int m147lance_close(struct device *dev);
+int mvme147lance_probe(struct net_device *dev);
+static int m147lance_open(struct net_device *dev);
+static int m147lance_close(struct net_device *dev);
 static void m147lance_writerap(struct m147lance_private *lp, unsigned short value);
 static void m147lance_writerdp(struct m147lance_private *lp, unsigned short value);
 static unsigned short m147lance_readrdp(struct m147lance_private *lp);
@@ -70,7 +70,7 @@
 #endif
 
 /* Initialise the one and only on-board 7990 */
-__initfunc(int mvme147lance_probe(struct device *dev))
+__initfunc(int mvme147lance_probe(struct net_device *dev))
 {
 	static int called = 0;
 	static const char name[] = "MVME147 LANCE";
@@ -162,7 +162,7 @@
 	return lp->lance.ll->rdp;
 }
 
-static int m147lance_open(struct device *dev)
+static int m147lance_open(struct net_device *dev)
 {
 	int status;
 
@@ -177,7 +177,7 @@
 	return 0;
 }
 
-static int m147lance_close(struct device *dev)
+static int m147lance_close(struct net_device *dev)
 {
 	/* disable interrupts at boardlevel */
 	m147_pcc->lan_cntrl=0x0; /* disable interrupts */
diff -u --recursive --new-file v2.3.13/linux/drivers/net/myri_sbus.c linux/drivers/net/myri_sbus.c
--- v2.3.13/linux/drivers/net/myri_sbus.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/myri_sbus.c	Wed Aug 18 11:36:42 1999
@@ -176,7 +176,7 @@
 
 static inline int myri_load_lanai(struct myri_eth *mp)
 {
-	struct device		*dev = mp->dev;
+	struct net_device		*dev = mp->dev;
 	struct myri_shmem	*shmem = mp->shmem;
 	unsigned char		*rptr;
 	int 			i;
@@ -261,7 +261,7 @@
 {
 	struct recvq *rq = mp->rq;
 	struct myri_rxd *rxd = &rq->myri_rxd[0];
-	struct device *dev = mp->dev;
+	struct net_device *dev = mp->dev;
 	int gfp_flags = GFP_KERNEL;
 	int i;
 
@@ -323,7 +323,7 @@
 }
 #endif
 
-static inline void myri_tx(struct myri_eth *mp, struct device *dev)
+static inline void myri_tx(struct myri_eth *mp, struct net_device *dev)
 {
 	struct sendq *sq	= mp->sq;
 	int entry		= mp->tx_old;
@@ -348,7 +348,7 @@
  * assume 802.3 if the type field is short enough to be a length.
  * This is normal practice and works for any 'now in use' protocol.
  */
-static unsigned short myri_type_trans(struct sk_buff *skb, struct device *dev)
+static unsigned short myri_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ethhdr *eth;
 	unsigned char *rawp;
@@ -388,7 +388,7 @@
 	return htons(ETH_P_802_2);
 }
 
-static inline void myri_rx(struct myri_eth *mp, struct device *dev)
+static inline void myri_rx(struct myri_eth *mp, struct net_device *dev)
 {
 	struct recvq *rq	= mp->rq;
 	struct recvq *rqa	= mp->rqack;
@@ -506,7 +506,7 @@
 
 static void myri_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev		= (struct device *) dev_id;
+	struct net_device *dev		= (struct net_device *) dev_id;
 	struct myri_eth *mp		= (struct myri_eth *) dev->priv;
 	struct lanai_regs *lregs	= mp->lregs;
 	struct myri_channel *chan	= &mp->shmem->channel;
@@ -537,14 +537,14 @@
 	DIRQ(("\n"));
 }
 
-static int myri_open(struct device *dev)
+static int myri_open(struct net_device *dev)
 {
 	struct myri_eth *mp = (struct myri_eth *) dev->priv;
 
 	return myri_init(mp, in_interrupt());
 }
 
-static int myri_close(struct device *dev)
+static int myri_close(struct net_device *dev)
 {
 	struct myri_eth *mp = (struct myri_eth *) dev->priv;
 
@@ -552,7 +552,7 @@
 	return 0;
 }
 
-static int myri_start_xmit(struct sk_buff *skb, struct device *dev)
+static int myri_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct myri_eth *mp = (struct myri_eth *) dev->priv;
 	struct sendq *sq = mp->sq;
@@ -656,7 +656,7 @@
  * saddr=NULL	means use device source address
  * daddr=NULL	means leave destination address (eg unresolved arp)
  */
-static int myri_header(struct sk_buff *skb, struct device *dev, unsigned short type,
+static int myri_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
 		       void *daddr, void *saddr, unsigned len)
 {
 	struct ethhdr *eth = (struct ethhdr *)skb_push(skb,ETH_HLEN);
@@ -708,7 +708,7 @@
 {
 	unsigned char *pad = (unsigned char *)skb->data;
 	struct ethhdr *eth = (struct ethhdr *)(pad + MYRI_PAD_LEN);
-	struct device *dev = skb->dev;
+	struct net_device *dev = skb->dev;
 
 #ifdef DEBUG_HEADER
 	DHDR(("myri_rebuild_header: pad[%02x,%02x] ", pad[0], pad[1]));
@@ -744,7 +744,7 @@
 	unsigned short type = hh->hh_type;
 	unsigned char *pad = (unsigned char *)hh->hh_data;
 	struct ethhdr *eth = (struct ethhdr *)(pad + MYRI_PAD_LEN);
-	struct device *dev = neigh->dev;
+	struct net_device *dev = neigh->dev;
 
 	if (type == __constant_htons(ETH_P_802_3))
 		return -1;
@@ -762,12 +762,12 @@
 
 
 /* Called by Address Resolution module to notify changes in address. */
-void myri_header_cache_update(struct hh_cache *hh, struct device *dev, unsigned char * haddr)
+void myri_header_cache_update(struct hh_cache *hh, struct net_device *dev, unsigned char * haddr)
 {
 	memcpy(((u8*)hh->hh_data) + 2, haddr, dev->addr_len);
 }
 
-static int myri_change_mtu(struct device *dev, int new_mtu)
+static int myri_change_mtu(struct net_device *dev, int new_mtu)
 {
 	if ((new_mtu < (ETH_HLEN + MYRI_PAD_LEN)) || (new_mtu > MYRINET_MTU))
 		return -EINVAL;
@@ -775,13 +775,13 @@
 	return 0;
 }
 
-static struct net_device_stats *myri_get_stats(struct device *dev)
+static struct net_device_stats *myri_get_stats(struct net_device *dev)
 { return &(((struct myri_eth *)dev->priv)->enet_stats); }
 
 #define CRC_POLYNOMIAL_BE 0x04c11db7UL  /* Ethernet CRC, big endian */
 #define CRC_POLYNOMIAL_LE 0xedb88320UL  /* Ethernet CRC, little endian */
 
-static void myri_set_multicast(struct device *dev)
+static void myri_set_multicast(struct net_device *dev)
 {
 	/* Do nothing, all MyriCOM nodes transmit multicast frames
 	 * as broadcast packets...
@@ -862,7 +862,7 @@
 }
 #endif
 
-static inline int myri_ether_init(struct device *dev, struct linux_sbus_device *sdev, int num)
+static inline int myri_ether_init(struct net_device *dev, struct linux_sbus_device *sdev, int num)
 {
 	static unsigned version_printed = 0;
 	struct myri_eth *mp;
@@ -1074,7 +1074,7 @@
 	return 0;
 }
 
-int __init myri_sbus_probe(struct device *dev)
+int __init myri_sbus_probe(struct net_device *dev)
 {
 	struct linux_sbus *bus;
 	struct linux_sbus_device *sdev = 0;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/myri_sbus.h linux/drivers/net/myri_sbus.h
--- v2.3.13/linux/drivers/net/myri_sbus.h	Fri May  8 00:20:47 1998
+++ linux/drivers/net/myri_sbus.h	Wed Aug 18 11:36:45 1999
@@ -273,7 +273,7 @@
 	struct recvq			*rqack;		/* Where we ack rx's.         */
 	struct recvq			*rq;		/* Where we put buffers.      */
 	struct sendq			*sq;		/* Where we stuff tx's.       */
-	struct device			*dev;		/* Linux/NET dev struct.      */
+	struct net_device			*dev;		/* Linux/NET dev struct.      */
 	int				tx_old;		/* To speed up tx cleaning.   */
 	struct lanai_regs		*lregs;		/* Quick ptr to LANAI regs.   */
 	struct sk_buff	       *rx_skbs[RX_RING_SIZE+1];/* RX skb's                   */
diff -u --recursive --new-file v2.3.13/linux/drivers/net/ne.c linux/drivers/net/ne.c
--- v2.3.13/linux/drivers/net/ne.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/ne.c	Wed Aug 18 11:36:42 1999
@@ -126,21 +126,21 @@
 /* Non-zero only if the current card is a PCI with BIOS-set IRQ. */
 static unsigned int pci_irq_line = 0;
 
-int ne_probe(struct device *dev);
-static int ne_probe1(struct device *dev, int ioaddr);
+int ne_probe(struct net_device *dev);
+static int ne_probe1(struct net_device *dev, int ioaddr);
 #ifdef CONFIG_PCI
-static int ne_probe_pci(struct device *dev);
+static int ne_probe_pci(struct net_device *dev);
 #endif
 
-static int ne_open(struct device *dev);
-static int ne_close(struct device *dev);
+static int ne_open(struct net_device *dev);
+static int ne_close(struct net_device *dev);
 
-static void ne_reset_8390(struct device *dev);
-static void ne_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
+static void ne_reset_8390(struct net_device *dev);
+static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
 			  int ring_page);
-static void ne_block_input(struct device *dev, int count,
+static void ne_block_input(struct net_device *dev, int count,
 			  struct sk_buff *skb, int ring_offset);
-static void ne_block_output(struct device *dev, const int count,
+static void ne_block_output(struct net_device *dev, const int count,
 		const unsigned char *buf, const int start_page);
 
 
@@ -177,7 +177,7 @@
  * the card.
  */
 
-int __init ne_probe(struct device *dev)
+int __init ne_probe(struct net_device *dev)
 {
 	int base_addr = dev ? dev->base_addr : 0;
 
@@ -209,7 +209,7 @@
 #endif
 
 #ifdef CONFIG_PCI
-static int __init ne_probe_pci(struct device *dev)
+static int __init ne_probe_pci(struct net_device *dev)
 {
 	int i;
 
@@ -243,7 +243,7 @@
 }
 #endif  /* CONFIG_PCI */
 
-static int __init ne_probe1(struct device *dev, int ioaddr)
+static int __init ne_probe1(struct net_device *dev, int ioaddr)
 {
 	int i;
 	unsigned char SA_prom[32];
@@ -497,14 +497,14 @@
 	return 0;
 }
 
-static int ne_open(struct device *dev)
+static int ne_open(struct net_device *dev)
 {
 	ei_open(dev);
 	MOD_INC_USE_COUNT;
 	return 0;
 }
 
-static int ne_close(struct device *dev)
+static int ne_close(struct net_device *dev)
 {
 	if (ei_debug > 1)
 		printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name);
@@ -516,7 +516,7 @@
 /* Hard reset the card.  This used to pause for the same period that a
    8390 reset command required, but that shouldn't be necessary. */
 
-static void ne_reset_8390(struct device *dev)
+static void ne_reset_8390(struct net_device *dev)
 {
 	unsigned long reset_start_time = jiffies;
 
@@ -542,7 +542,7 @@
    we don't need to be concerned with ring wrap as the header will be at
    the start of a page, so we optimize accordingly. */
 
-static void ne_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 {
 	int nic_base = dev->base_addr;
 
@@ -579,7 +579,7 @@
    The NEx000 doesn't share the on-board packet memory -- you have to put
    the packet out through the "remote DMA" dataport using outb. */
 
-static void ne_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
+static void ne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
 {
 #ifdef NE_SANITY_CHECK
 	int xfer_count = count;
@@ -646,7 +646,7 @@
 	ei_status.dmaing &= ~0x01;
 }
 
-static void ne_block_output(struct device *dev, int count,
+static void ne_block_output(struct net_device *dev, int count,
 		const unsigned char *buf, const int start_page)
 {
 	int nic_base = NE_BASE;
@@ -756,7 +756,7 @@
 #define MAX_NE_CARDS	4	/* Max number of NE cards per module */
 #define NAMELEN		8	/* # of chars for storing dev->name */
 static char namelist[NAMELEN * MAX_NE_CARDS] = { 0, };
-static struct device dev_ne[MAX_NE_CARDS] = {
+static struct net_device dev_ne[MAX_NE_CARDS] = {
 	{
 		NULL,		/* assign a chunk of namelist[] below */
 		0, 0, 0, 0,
@@ -787,7 +787,7 @@
 	int this_dev, found = 0;
 
 	for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
-		struct device *dev = &dev_ne[this_dev];
+		struct net_device *dev = &dev_ne[this_dev];
 		dev->name = namelist+(NAMELEN*this_dev);
 		dev->irq = irq[this_dev];
 		dev->mem_end = bad[this_dev];
@@ -816,7 +816,7 @@
 	int this_dev;
 
 	for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
-		struct device *dev = &dev_ne[this_dev];
+		struct net_device *dev = &dev_ne[this_dev];
 		if (dev->priv != NULL) {
 			void *priv = dev->priv;
 			free_irq(dev->irq, dev);
diff -u --recursive --new-file v2.3.13/linux/drivers/net/ne2.c linux/drivers/net/ne2.c
--- v2.3.13/linux/drivers/net/ne2.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/ne2.c	Wed Aug 18 11:36:42 1999
@@ -126,19 +126,19 @@
 	{ 0x0000, NULL }
 };
 
-extern int netcard_probe(struct device *dev);
+extern int netcard_probe(struct net_device *dev);
 
-static int ne2_probe1(struct device *dev, int slot);
+static int ne2_probe1(struct net_device *dev, int slot);
 
-static int ne_open(struct device *dev);
-static int ne_close(struct device *dev);
+static int ne_open(struct net_device *dev);
+static int ne_close(struct net_device *dev);
 
-static void ne_reset_8390(struct device *dev);
-static void ne_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
+static void ne_reset_8390(struct net_device *dev);
+static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
 		int ring_page);
-static void ne_block_input(struct device *dev, int count,
+static void ne_block_input(struct net_device *dev, int count,
 		struct sk_buff *skb, int ring_offset);
-static void ne_block_output(struct device *dev, const int count,
+static void ne_block_output(struct net_device *dev, const int count,
 		const unsigned char *buf, const int start_page);
 
 
@@ -146,7 +146,7 @@
  * Note that at boot, this probe only picks up one card at a time.
  */
 
-int __init ne2_probe(struct device *dev)
+int __init ne2_probe(struct net_device *dev)
 {
 	static int current_mca_slot = -1;
 	int i;
@@ -175,7 +175,7 @@
 }
 
 
-static int ne2_procinfo(char *buf, int slot, struct device *dev)
+static int ne2_procinfo(char *buf, int slot, struct net_device *dev)
 {
 	int len=0;
 
@@ -198,7 +198,7 @@
 	return len;
 }
 
-static int __init ne2_probe1(struct device *dev, int slot)
+static int __init ne2_probe1(struct net_device *dev, int slot)
 {
 	int i, base_addr, irq;
 	unsigned char POS;
@@ -370,14 +370,14 @@
 	return 0;
 }
 
-static int ne_open(struct device *dev)
+static int ne_open(struct net_device *dev)
 {
 	ei_open(dev);
 	MOD_INC_USE_COUNT;
 	return 0;
 }
 
-static int ne_close(struct device *dev)
+static int ne_close(struct net_device *dev)
 {
 	if (ei_debug > 1)
 		printk("%s: Shutting down ethercard.\n", dev->name);
@@ -388,7 +388,7 @@
 
 /* Hard reset the card.  This used to pause for the same period that a
    8390 reset command required, but that shouldn't be necessary. */
-static void ne_reset_8390(struct device *dev)
+static void ne_reset_8390(struct net_device *dev)
 {
 	unsigned long reset_start_time = jiffies;
 
@@ -415,7 +415,7 @@
    we don't need to be concerned with ring wrap as the header will be at
    the start of a page, so we optimize accordingly. */
 
-static void ne_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, 
+static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, 
 		int ring_page)
 {
 
@@ -455,7 +455,7 @@
    hints. The NEx000 doesn't share the on-board packet memory -- you have
    to put the packet out through the "remote DMA" dataport using outb. */
 
-static void ne_block_input(struct device *dev, int count, struct sk_buff *skb, 
+static void ne_block_input(struct net_device *dev, int count, struct sk_buff *skb, 
 		int ring_offset)
 {
 #ifdef NE_SANITY_CHECK
@@ -518,7 +518,7 @@
 	ei_status.dmaing &= ~0x01;
 }
 
-static void ne_block_output(struct device *dev, int count,
+static void ne_block_output(struct net_device *dev, int count,
 		const unsigned char *buf, const int start_page)
 {
 	int nic_base = NE_BASE;
@@ -624,7 +624,7 @@
 #define MAX_NE_CARDS	4	/* Max number of NE cards per module */
 #define NAMELEN		8	/* # of chars for storing dev->name */
 static char namelist[NAMELEN * MAX_NE_CARDS] = { 0, };
-static struct device dev_ne[MAX_NE_CARDS] = {
+static struct net_device dev_ne[MAX_NE_CARDS] = {
 	{
 		NULL,		/* assign a chunk of namelist[] below */
 		0, 0, 0, 0,
@@ -650,7 +650,7 @@
 	int this_dev, found = 0;
 
 	for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
-		struct device *dev = &dev_ne[this_dev];
+		struct net_device *dev = &dev_ne[this_dev];
 		dev->name = namelist+(NAMELEN*this_dev);
 		dev->irq = irq[this_dev];
 		dev->mem_end = bad[this_dev];
@@ -672,7 +672,7 @@
 	int this_dev;
 
 	for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
-		struct device *dev = &dev_ne[this_dev];
+		struct net_device *dev = &dev_ne[this_dev];
 		if (dev->priv != NULL) {
 			mca_mark_as_unused(ei_status.priv);
 			mca_set_adapter_procfn( ei_status.priv, NULL, NULL);
diff -u --recursive --new-file v2.3.13/linux/drivers/net/ne2k-pci.c linux/drivers/net/ne2k-pci.c
--- v2.3.13/linux/drivers/net/ne2k-pci.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/ne2k-pci.c	Wed Aug 18 11:36:42 1999
@@ -104,19 +104,19 @@
 #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 device *dev);
-static struct device *ne2k_pci_probe1(struct device *dev, int ioaddr, int irq,
+int ne2k_pci_probe(struct net_device *dev);
+static struct net_device *ne2k_pci_probe1(struct net_device *dev, int ioaddr, int irq,
 									  int chip_idx);
 
-static int ne2k_pci_open(struct device *dev);
-static int ne2k_pci_close(struct device *dev);
+static int ne2k_pci_open(struct net_device *dev);
+static int ne2k_pci_close(struct net_device *dev);
 
-static void ne2k_pci_reset_8390(struct device *dev);
-static void ne2k_pci_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
+static void ne2k_pci_reset_8390(struct net_device *dev);
+static void ne2k_pci_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
 			  int ring_page);
-static void ne2k_pci_block_input(struct device *dev, int count,
+static void ne2k_pci_block_input(struct net_device *dev, int count,
 			  struct sk_buff *skb, int ring_offset);
-static void ne2k_pci_block_output(struct device *dev, const int count,
+static void ne2k_pci_block_output(struct net_device *dev, const int count,
 		const unsigned char *buf, const int start_page);
 
 
@@ -124,7 +124,7 @@
 /* No room in the standard 8390 structure for extra info we need. */
 struct ne2k_pci_card {
 	struct ne2k_pci_card *next;
-	struct device *dev;
+	struct net_device *dev;
 	struct pci_dev *pci_dev;
 };
 /* A list of all installed devices, for removing the driver module. */
@@ -150,7 +150,7 @@
 void
 cleanup_module(void)
 {
-	struct device *dev;
+	struct net_device *dev;
 	struct ne2k_pci_card *this_card;
 
 	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
@@ -186,7 +186,7 @@
 {"ne2k_pci", ne2k_pci_probe1, NE_IO_EXTENT, 0};
 #endif
 
-int __init ne2k_pci_probe(struct device *dev)
+int __init ne2k_pci_probe(struct net_device *dev)
 {
 	struct pci_dev *pdev = NULL;
 	int cards_found = 0;
@@ -263,7 +263,7 @@
 	return cards_found ? 0 : -ENODEV;
 }
 
-static struct device __init *ne2k_pci_probe1(struct device *dev, int ioaddr, int irq, int chip_idx)
+static struct net_device __init *ne2k_pci_probe1(struct net_device *dev, int ioaddr, int irq, int chip_idx)
 {
 	int i;
 	unsigned char SA_prom[32];
@@ -397,7 +397,7 @@
 }
 
 static int
-ne2k_pci_open(struct device *dev)
+ne2k_pci_open(struct net_device *dev)
 {
 	if (request_irq(dev->irq, ei_interrupt, SA_SHIRQ, dev->name, dev))
 		return -EAGAIN;
@@ -407,7 +407,7 @@
 }
 
 static int
-ne2k_pci_close(struct device *dev)
+ne2k_pci_close(struct net_device *dev)
 {
 	ei_close(dev);
 	free_irq(dev->irq, dev);
@@ -418,7 +418,7 @@
 /* Hard reset the card.  This used to pause for the same period that a
    8390 reset command required, but that shouldn't be necessary. */
 static void
-ne2k_pci_reset_8390(struct device *dev)
+ne2k_pci_reset_8390(struct net_device *dev)
 {
 	unsigned long reset_start_time = jiffies;
 
@@ -444,7 +444,7 @@
    the start of a page, so we optimize accordingly. */
 
 static void
-ne2k_pci_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+ne2k_pci_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 {
 
 	int nic_base = dev->base_addr;
@@ -483,7 +483,7 @@
    the packet out through the "remote DMA" dataport using outb. */
 
 static void
-ne2k_pci_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
+ne2k_pci_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
 {
 	int nic_base = dev->base_addr;
 	char *buf = skb->data;
@@ -527,7 +527,7 @@
 }
 
 static void
-ne2k_pci_block_output(struct device *dev, int count,
+ne2k_pci_block_output(struct net_device *dev, int count,
 		const unsigned char *buf, const int start_page)
 {
 	int nic_base = NE_BASE;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/ne3210.c linux/drivers/net/ne3210.c
--- v2.3.13/linux/drivers/net/ne3210.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/ne3210.c	Wed Aug 18 11:36:42 1999
@@ -43,17 +43,17 @@
 #include <linux/etherdevice.h>
 #include "8390.h"
 
-int ne3210_probe(struct device *dev);
-int ne3210_probe1(struct device *dev, int ioaddr);
+int ne3210_probe(struct net_device *dev);
+int ne3210_probe1(struct net_device *dev, int ioaddr);
 
-static int ne3210_open(struct device *dev);
-static int ne3210_close(struct device *dev);
+static int ne3210_open(struct net_device *dev);
+static int ne3210_close(struct net_device *dev);
 
-static void ne3210_reset_8390(struct device *dev);
+static void ne3210_reset_8390(struct net_device *dev);
 
-static void ne3210_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page);
-static void ne3210_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset);
-static void ne3210_block_output(struct device *dev, int count, const unsigned char *buf, const int start_page);
+static void ne3210_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page);
+static void ne3210_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset);
+static void ne3210_block_output(struct net_device *dev, int count, const unsigned char *buf, const int start_page);
 
 #define NE3210_START_PG		0x00    /* First page of TX buffer	*/
 #define NE3210_STOP_PG		0x80    /* Last page +1 of RX ring	*/
@@ -95,7 +95,7 @@
  *	PROM for a match against the value assigned to Novell.
  */
 
-int __init ne3210_probe(struct device *dev)
+int __init ne3210_probe(struct net_device *dev)
 {
 	unsigned short ioaddr = dev->base_addr;
 
@@ -122,7 +122,7 @@
 	return ENODEV;
 }
 
-int __init ne3210_probe1(struct device *dev, int ioaddr)
+int __init ne3210_probe1(struct net_device *dev, int ioaddr)
 {
 	int i;
 	unsigned long eisa_id;
@@ -272,7 +272,7 @@
  *	Reset by toggling the "Board Enable" bits (bit 2 and 0).
  */
 
-static void ne3210_reset_8390(struct device *dev)
+static void ne3210_reset_8390(struct net_device *dev)
 {
 	unsigned short ioaddr = dev->base_addr;
 
@@ -304,7 +304,7 @@
  */
 
 static void
-ne3210_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+ne3210_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 {
 	unsigned long hdr_start = dev->mem_start + ((ring_page - NE3210_START_PG)<<8);
 	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
@@ -317,7 +317,7 @@
  *	be rounded up to a doubleword value via ne3210_get_8390_hdr() above.
  */
 
-static void ne3210_block_input(struct device *dev, int count, struct sk_buff *skb,
+static void ne3210_block_input(struct net_device *dev, int count, struct sk_buff *skb,
 						  int ring_offset)
 {
 	unsigned long xfer_start = dev->mem_start + ring_offset - (NE3210_START_PG<<8);
@@ -334,7 +334,7 @@
 	}
 }
 
-static void ne3210_block_output(struct device *dev, int count,
+static void ne3210_block_output(struct net_device *dev, int count,
 				const unsigned char *buf, int start_page)
 {
 	unsigned long shmem = dev->mem_start + ((start_page - NE3210_START_PG)<<8);
@@ -343,14 +343,14 @@
 	memcpy_toio(shmem, buf, count);
 }
 
-static int ne3210_open(struct device *dev)
+static int ne3210_open(struct net_device *dev)
 {
 	ei_open(dev);
 	MOD_INC_USE_COUNT;
 	return 0;
 }
 
-static int ne3210_close(struct device *dev)
+static int ne3210_close(struct net_device *dev)
 {
 
 	if (ei_debug > 1)
@@ -365,7 +365,7 @@
 #define MAX_NE3210_CARDS	4	/* Max number of NE3210 cards per module */
 #define NAMELEN			8	/* # of chars for storing dev->name */
 static char namelist[NAMELEN * MAX_NE3210_CARDS] = { 0, };
-static struct device dev_ne3210[MAX_NE3210_CARDS] = {
+static struct net_device dev_ne3210[MAX_NE3210_CARDS] = {
 	{
 		NULL,		/* assign a chunk of namelist[] below */
 		0, 0, 0, 0,
@@ -387,7 +387,7 @@
 	int this_dev, found = 0;
 
 	for (this_dev = 0; this_dev < MAX_NE3210_CARDS; this_dev++) {
-		struct device *dev = &dev_ne3210[this_dev];
+		struct net_device *dev = &dev_ne3210[this_dev];
 		dev->name = namelist+(NAMELEN*this_dev);
 		dev->irq = irq[this_dev];
 		dev->base_addr = io[this_dev];
@@ -414,7 +414,7 @@
 	int this_dev;
 
 	for (this_dev = 0; this_dev < MAX_NE3210_CARDS; this_dev++) {
-		struct device *dev = &dev_ne3210[this_dev];
+		struct net_device *dev = &dev_ne3210[this_dev];
 		if (dev->priv != NULL) {
 			void *priv = dev->priv;
 			free_irq(dev->irq, dev);
diff -u --recursive --new-file v2.3.13/linux/drivers/net/net_init.c linux/drivers/net/net_init.c
--- v2.3.13/linux/drivers/net/net_init.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/net_init.c	Wed Aug 18 11:36:42 1999
@@ -62,7 +62,7 @@
 
 /* The list of used and available "eth" slots (for "eth0", "eth1", etc.) */
 #define MAX_ETH_CARDS 16
-static struct device *ethdev_index[MAX_ETH_CARDS];
+static struct net_device *ethdev_index[MAX_ETH_CARDS];
 
 
 /* Fill in the fields of the device structure with ethernet-generic values.
@@ -75,17 +75,17 @@
    long.
  */
 
-struct device *
-init_etherdev(struct device *dev, int sizeof_priv)
+struct net_device *
+init_etherdev(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 device) + sizeof("eth%d  ")
+		int alloc_size = sizeof(struct net_device) + sizeof("eth%d  ")
 			+ sizeof_priv + 3;
-		struct device *cur_dev;
+		struct net_device *cur_dev;
 		char pname[8];		/* Putative name for the device.  */
 
 		for (i = 0; i < MAX_ETH_CARDS; ++i)
@@ -110,7 +110,7 @@
 
 		alloc_size &= ~3;		/* Round to dword boundary. */
 
-		dev = (struct device *)kmalloc(alloc_size, GFP_KERNEL);
+		dev = (struct net_device *)kmalloc(alloc_size, GFP_KERNEL);
 		if(dev==NULL)
 			return NULL;
 		memset(dev, 0, alloc_size);
@@ -141,7 +141,7 @@
 }
 
 
-static int eth_mac_addr(struct device *dev, void *p)
+static int eth_mac_addr(struct net_device *dev, void *p)
 {
 	struct sockaddr *addr=p;
 	if(dev->start)
@@ -150,7 +150,7 @@
 	return 0;
 }
 
-static int eth_change_mtu(struct device *dev, int new_mtu)
+static int eth_change_mtu(struct net_device *dev, int new_mtu)
 {
 	if ((new_mtu < 68) || (new_mtu > 1500))
 		return -EINVAL;
@@ -160,7 +160,7 @@
 
 #ifdef CONFIG_FDDI
 
-static int fddi_change_mtu(struct device *dev, int new_mtu)
+static int fddi_change_mtu(struct net_device *dev, int new_mtu)
 {
 	if ((new_mtu < FDDI_K_SNAP_HLEN) || (new_mtu > FDDI_K_SNAP_DLEN))
 		return(-EINVAL);
@@ -172,9 +172,9 @@
 
 #ifdef CONFIG_HIPPI
 #define MAX_HIP_CARDS	4
-static struct device *hipdev_index[MAX_HIP_CARDS];
+static struct net_device *hipdev_index[MAX_HIP_CARDS];
 
-static int hippi_change_mtu(struct device *dev, int new_mtu)
+static int hippi_change_mtu(struct net_device *dev, int new_mtu)
 {
 	/*
 	 * HIPPI's got these nice large MTUs.
@@ -190,7 +190,7 @@
  * For HIPPI we will actually use the lower 4 bytes of the hardware
  * address as the I-FIELD rather than the actual hardware address.
  */
-static int hippi_mac_addr(struct device *dev, void *p)
+static int hippi_mac_addr(struct net_device *dev, void *p)
 {
 	struct sockaddr *addr = p;
 	if(dev->start)
@@ -200,16 +200,16 @@
 }
 
 
-struct device *init_hippi_dev(struct device *dev, int sizeof_priv)
+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 device) + sizeof("hip%d  ")
+		int alloc_size = sizeof(struct net_device) + sizeof("hip%d  ")
 			+ sizeof_priv + 3;
-		struct device *cur_dev;
+		struct net_device *cur_dev;
 		char pname[8];
 
 		for (i = 0; i < MAX_HIP_CARDS; ++i)
@@ -234,7 +234,7 @@
 
 		alloc_size &= ~3;		/* Round to dword boundary. */
 
-		dev = (struct device *)kmalloc(alloc_size, GFP_KERNEL);
+		dev = (struct net_device *)kmalloc(alloc_size, GFP_KERNEL);
 		if(dev==NULL)
 			return NULL;
 		memset(dev, 0, alloc_size);
@@ -265,7 +265,7 @@
 }
 
 
-void unregister_hipdev(struct device *dev)
+void unregister_hipdev(struct net_device *dev)
 {
 	int i;
 	rtnl_lock();
@@ -280,7 +280,7 @@
 }
 
 
-static int hippi_neigh_setup_dev(struct device *dev, struct neigh_parms *p)
+static int hippi_neigh_setup_dev(struct net_device *dev, struct neigh_parms *p)
 {
 	/* Never send broadcast/multicast ARP messages */
 	p->mcast_probes = 0;
@@ -296,7 +296,7 @@
 
 #endif
 
-void ether_setup(struct device *dev)
+void ether_setup(struct net_device *dev)
 {
 	int i;
 	/* Fill in the fields of the device structure with ethernet-generic values.
@@ -339,7 +339,7 @@
 
 #ifdef CONFIG_FDDI
 
-void fddi_setup(struct device *dev)
+void fddi_setup(struct net_device *dev)
 {
 	/*
 	 * Fill in the fields of the device structure with FDDI-generic values.
@@ -369,7 +369,7 @@
 #endif
 
 #ifdef CONFIG_HIPPI
-void hippi_setup(struct device *dev)
+void hippi_setup(struct net_device *dev)
 {
 	int i;
 
@@ -419,18 +419,18 @@
 
 #if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE)
 
-static int ltalk_change_mtu(struct device *dev, int mtu)
+static int ltalk_change_mtu(struct net_device *dev, int mtu)
 {
 	return -EINVAL;
 }
 
-static int ltalk_mac_addr(struct device *dev, void *addr)
+static int ltalk_mac_addr(struct net_device *dev, void *addr)
 {	
 	return -EINVAL;
 }
 
 
-void ltalk_setup(struct device *dev)
+void ltalk_setup(struct net_device *dev)
 {
 	/* Fill in the fields of the device structure with localtalk-generic values. */
 	
@@ -456,7 +456,7 @@
 
 #endif
 
-int ether_config(struct device *dev, struct ifmap *map)
+int ether_config(struct net_device *dev, struct ifmap *map)
 {
 	if (map->mem_start != (u_long)(-1))
 		dev->mem_start = map->mem_start;
@@ -473,7 +473,7 @@
 	return 0;
 }
 
-static int etherdev_get_index(struct device *dev)
+static int etherdev_get_index(struct net_device *dev)
 {
 	int i=MAX_ETH_CARDS;
 
@@ -488,7 +488,7 @@
 	return -1;
 }
 
-static void etherdev_put_index(struct device *dev)
+static void etherdev_put_index(struct net_device *dev)
 {
 	int i;
 	for (i = 0; i < MAX_ETH_CARDS; ++i) {
@@ -499,7 +499,7 @@
 	}
 }
 
-int register_netdev(struct device *dev)
+int register_netdev(struct net_device *dev)
 {
 	int i=-1;
 
@@ -519,7 +519,7 @@
 	return 0;
 }
 
-void unregister_netdev(struct device *dev)
+void unregister_netdev(struct net_device *dev)
 {
 	rtnl_lock();
 	unregister_netdevice(dev);
@@ -531,18 +531,18 @@
 #ifdef CONFIG_TR
 /* The list of used and available "tr" slots */
 #define MAX_TR_CARDS 16
-static struct device *trdev_index[MAX_TR_CARDS];
+static struct net_device *trdev_index[MAX_TR_CARDS];
 
-struct device *init_trdev(struct device *dev, int sizeof_priv)
+struct net_device *init_trdev(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 device) + sizeof("tr%d  ")
+		int alloc_size = sizeof(struct net_device) + sizeof("tr%d  ")
 			+ sizeof_priv + 3;
-		struct device *cur_dev;
+		struct net_device *cur_dev;
 		char pname[8];		/* Putative name for the device.  */
 
 		for (i = 0; i < MAX_TR_CARDS; ++i)
@@ -566,7 +566,7 @@
 			}
 
 		alloc_size &= ~3;		/* Round to dword boundary. */
-		dev = (struct device *)kmalloc(alloc_size, GFP_KERNEL);
+		dev = (struct net_device *)kmalloc(alloc_size, GFP_KERNEL);
 		if(dev==NULL)
 			return NULL;
 		memset(dev, 0, alloc_size);
@@ -606,7 +606,7 @@
 	return dev;
 }
 
-void tr_setup(struct device *dev)
+void tr_setup(struct net_device *dev)
 {
 	int i;
 
@@ -624,7 +624,7 @@
 	}
 }
 
-void tr_freedev(struct device *dev)
+void tr_freedev(struct net_device *dev)
 {
 	int i;
 	for (i = 0; i < MAX_TR_CARDS; ++i) 
@@ -637,7 +637,7 @@
 	}
 }
 
-int register_trdev(struct device *dev)
+int register_trdev(struct net_device *dev)
 {
 	dev_init_buffers(dev);
 	
@@ -648,7 +648,7 @@
 	return 0;
 }
 
-void unregister_trdev(struct device *dev)
+void unregister_trdev(struct net_device *dev)
 {
 	rtnl_lock();
 	unregister_netdevice(dev);
diff -u --recursive --new-file v2.3.13/linux/drivers/net/ni5010.c linux/drivers/net/ni5010.c
--- v2.3.13/linux/drivers/net/ni5010.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/ni5010.c	Wed Aug 18 11:36:42 1999
@@ -100,26 +100,26 @@
 
 /* Index to functions, as function prototypes. */
 
-extern int 	ni5010_probe(struct device *dev);
-static int	ni5010_probe1(struct device *dev, int ioaddr);
-static int	ni5010_open(struct device *dev);
-static int	ni5010_send_packet(struct sk_buff *skb, struct device *dev);
+extern int 	ni5010_probe(struct net_device *dev);
+static int	ni5010_probe1(struct net_device *dev, int ioaddr);
+static int	ni5010_open(struct net_device *dev);
+static int	ni5010_send_packet(struct sk_buff *skb, struct net_device *dev);
 static void	ni5010_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void	ni5010_rx(struct device *dev);
-static int	ni5010_close(struct device *dev);
-static struct net_device_stats *ni5010_get_stats(struct device *dev);
-static void 	ni5010_set_multicast_list(struct device *dev);
-static void	reset_receiver(struct device *dev);
+static void	ni5010_rx(struct net_device *dev);
+static int	ni5010_close(struct net_device *dev);
+static struct net_device_stats *ni5010_get_stats(struct net_device *dev);
+static void 	ni5010_set_multicast_list(struct net_device *dev);
+static void	reset_receiver(struct net_device *dev);
 
-static int	process_xmt_interrupt(struct device *dev);
+static int	process_xmt_interrupt(struct net_device *dev);
 #define tx_done(dev) 1
-extern void	hardware_send_packet(struct device *dev, char *buf, int length);
-extern void 	chipset_init(struct device *dev, int startp);
+extern void	hardware_send_packet(struct net_device *dev, char *buf, int length);
+extern void 	chipset_init(struct net_device *dev, int startp);
 static void	dump_packet(void *buf, int len);
-static void 	show_registers(struct device *dev);
+static void 	show_registers(struct net_device *dev);
 
 
-int __init ni5010_probe(struct device *dev)
+int __init ni5010_probe(struct net_device *dev)
 {
 	int *port;
 
@@ -182,7 +182,7 @@
  *      verifies that the correct device exists and functions.
  */
 
-static int __init ni5010_probe1(struct device *dev, int ioaddr)
+static int __init ni5010_probe1(struct net_device *dev, int ioaddr)
 {
 	static unsigned version_printed = 0;
 	int i;
@@ -355,7 +355,7 @@
  * there is non-reboot way to recover if something goes wrong.
  */
    
-static int ni5010_open(struct device *dev)
+static int ni5010_open(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr;
 	int i;
@@ -414,7 +414,7 @@
      	return 0;
 }
 
-static void reset_receiver(struct device *dev)
+static void reset_receiver(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr;
 	
@@ -426,7 +426,7 @@
 	outb(0xff, EDLC_RMASK);	/* Enable all rcv interrupts */
 }
 
-static int ni5010_send_packet(struct sk_buff *skb, struct device *dev)
+static int ni5010_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
 	PRINTK2((KERN_DEBUG "%s: entering ni5010_send_packet\n", dev->name));
 	if (dev->tbusy) {
@@ -472,7 +472,7 @@
 static void 
 ni5010_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	struct ni5010_local *lp;
 	int ioaddr, status;
 	int xmit_was_error = 0;
@@ -531,7 +531,7 @@
 
 /* We have a good packet, get it out of the buffer. */
 static void
-ni5010_rx(struct device *dev)
+ni5010_rx(struct net_device *dev)
 {
 	struct ni5010_local *lp = (struct ni5010_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -594,7 +594,7 @@
 	
 }
 
-static int process_xmt_interrupt(struct device *dev)
+static int process_xmt_interrupt(struct net_device *dev)
 {
 	struct ni5010_local *lp = (struct ni5010_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -635,7 +635,7 @@
 
 /* The inverse routine to ni5010_open(). */
 static int
-ni5010_close(struct device *dev)
+ni5010_close(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr;
 
@@ -659,7 +659,7 @@
 /* Get the current statistics.	This may be called with the card open or
    closed. */
 static struct net_device_stats *
-ni5010_get_stats(struct device *dev)
+ni5010_get_stats(struct net_device *dev)
 {
 	struct ni5010_local *lp = (struct ni5010_local *)dev->priv;
 
@@ -682,7 +682,7 @@
                         best-effort filtering.
 */
 static void
-ni5010_set_multicast_list(struct device *dev)
+ni5010_set_multicast_list(struct net_device *dev)
 {
 	short ioaddr = dev->base_addr;  
 
@@ -702,7 +702,7 @@
 	}
 }
 
-extern void hardware_send_packet(struct device *dev, char *buf, int length)
+extern void hardware_send_packet(struct net_device *dev, char *buf, int length)
 {
 	struct ni5010_local *lp = (struct ni5010_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -751,13 +751,13 @@
 	if (NI5010_DEBUG) show_registers(dev);	
 }
 
-extern void chipset_init(struct device *dev, int startp)
+extern void chipset_init(struct net_device *dev, int startp)
 {
 	/* FIXME: Move some stuff here */
 	PRINTK3((KERN_DEBUG "%s: doing NOTHING in chipset_init\n", dev->name));
 }
 
-static void show_registers(struct device *dev)
+static void show_registers(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr;
 	
@@ -772,7 +772,7 @@
 
 #ifdef MODULE
 static char devicename[9] = { 0, };
-static struct device dev_ni5010 = {
+static struct net_device dev_ni5010 = {
         devicename,
         0, 0, 0, 0,
         0, 0,
diff -u --recursive --new-file v2.3.13/linux/drivers/net/ni52.c linux/drivers/net/ni52.c
--- v2.3.13/linux/drivers/net/ni52.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/ni52.c	Wed Aug 18 11:36:42 1999
@@ -192,26 +192,26 @@
 #define NI52_ADDR1 0x07
 #define NI52_ADDR2 0x01
 
-static int     ni52_probe1(struct device *dev,int ioaddr);
+static int     ni52_probe1(struct net_device *dev,int ioaddr);
 static void    ni52_interrupt(int irq,void *dev_id,struct pt_regs *reg_ptr);
-static int     ni52_open(struct device *dev);
-static int     ni52_close(struct device *dev);
-static int     ni52_send_packet(struct sk_buff *,struct device *);
-static struct  net_device_stats *ni52_get_stats(struct device *dev);
-static void    set_multicast_list(struct device *dev);
+static int     ni52_open(struct net_device *dev);
+static int     ni52_close(struct net_device *dev);
+static int     ni52_send_packet(struct sk_buff *,struct net_device *);
+static struct  net_device_stats *ni52_get_stats(struct net_device *dev);
+static void    set_multicast_list(struct net_device *dev);
 #if 0
-static void    ni52_dump(struct device *,void *);
+static void    ni52_dump(struct net_device *,void *);
 #endif
 
 /* helper-functions */
-static int     init586(struct device *dev);
-static int     check586(struct device *dev,char *where,unsigned size);
-static void    alloc586(struct device *dev);
-static void    startrecv586(struct device *dev);
-static void   *alloc_rfa(struct device *dev,void *ptr);
-static void    ni52_rcv_int(struct device *dev);
-static void    ni52_xmt_int(struct device *dev);
-static void    ni52_rnr_int(struct device *dev);
+static int     init586(struct net_device *dev);
+static int     check586(struct net_device *dev,char *where,unsigned size);
+static void    alloc586(struct net_device *dev);
+static void    startrecv586(struct net_device *dev);
+static void   *alloc_rfa(struct net_device *dev,void *ptr);
+static void    ni52_rcv_int(struct net_device *dev);
+static void    ni52_xmt_int(struct net_device *dev);
+static void    ni52_rnr_int(struct net_device *dev);
 
 struct priv
 {
@@ -238,7 +238,7 @@
 /**********************************************
  * close device
  */
-static int ni52_close(struct device *dev)
+static int ni52_close(struct net_device *dev)
 {
 	free_irq(dev->irq, dev);
 
@@ -255,7 +255,7 @@
 /**********************************************
  * open device
  */
-static int ni52_open(struct device *dev)
+static int ni52_open(struct net_device *dev)
 {
 	ni_disint();
 	alloc586(dev);
@@ -281,7 +281,7 @@
 /**********************************************
  * Check to see if there's an 82586 out there.
  */
-static int check586(struct device *dev,char *where,unsigned size)
+static int check586(struct net_device *dev,char *where,unsigned size)
 {
 	struct priv pb;
 	struct priv *p = /* (struct priv *) dev->priv*/ &pb;
@@ -323,7 +323,7 @@
 /******************************************************************
  * set iscp at the right place, called by ni52_probe1 and open586.
  */
-void alloc586(struct device *dev)
+void alloc586(struct net_device *dev)
 {
 	struct priv *p =	(struct priv *) dev->priv;
 
@@ -358,7 +358,7 @@
 /**********************************************
  * probe the ni5210-card
  */
-int __init ni52_probe(struct device *dev)
+int __init ni52_probe(struct net_device *dev)
 {
 #ifndef MODULE
 	int *port;
@@ -409,7 +409,7 @@
 	return ENODEV;
 }
 
-static int __init ni52_probe1(struct device *dev,int ioaddr)
+static int __init ni52_probe1(struct net_device *dev,int ioaddr)
 {
 	int i,size;
 
@@ -534,7 +534,7 @@
  * needs a correct 'allocated' memory
  */
 
-static int init586(struct device *dev)
+static int init586(struct net_device *dev)
 {
 	void *ptr;
 	int i,result=0;
@@ -769,7 +769,7 @@
  * It sets up the Receive Frame Area (RFA).
  */
 
-static void *alloc_rfa(struct device *dev,void *ptr)
+static void *alloc_rfa(struct net_device *dev,void *ptr)
 {
 	volatile struct rfd_struct *rfd = (struct rfd_struct *)ptr;
 	volatile struct rbd_struct *rbd;
@@ -817,7 +817,7 @@
 
 static void ni52_interrupt(int irq,void *dev_id,struct pt_regs *reg_ptr)
 {
-	struct device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	unsigned short stat;
 	int cnt=0;
 	struct priv *p;
@@ -893,7 +893,7 @@
  * receive-interrupt
  */
 
-static void ni52_rcv_int(struct device *dev)
+static void ni52_rcv_int(struct net_device *dev)
 {
 	int status,cnt=0;
 	unsigned short totlen;
@@ -1016,7 +1016,7 @@
  * handle 'Receiver went not ready'.
  */
 
-static void ni52_rnr_int(struct device *dev)
+static void ni52_rnr_int(struct net_device *dev)
 {
 	struct priv *p = (struct priv *) dev->priv;
 
@@ -1039,7 +1039,7 @@
  * handle xmit - interrupt
  */
 
-static void ni52_xmt_int(struct device *dev)
+static void ni52_xmt_int(struct net_device *dev)
 {
 	int status;
 	struct priv *p = (struct priv *) dev->priv;
@@ -1092,7 +1092,7 @@
  * (re)start the receiver
  */
 
-static void startrecv586(struct device *dev)
+static void startrecv586(struct net_device *dev)
 {
 	struct priv *p = (struct priv *) dev->priv;
 
@@ -1108,7 +1108,7 @@
  * send frame
  */
 
-static int ni52_send_packet(struct sk_buff *skb, struct device *dev)
+static int ni52_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
 	int len,i;
 #ifndef NO_NOPCOMMANDS
@@ -1258,7 +1258,7 @@
  * Someone wanna have the statistics
  */
 
-static struct net_device_stats *ni52_get_stats(struct device *dev)
+static struct net_device_stats *ni52_get_stats(struct net_device *dev)
 {
 	struct priv *p = (struct priv *) dev->priv;
 	unsigned short crc,aln,rsc,ovrn;
@@ -1283,7 +1283,7 @@
 /********************************************************
  * Set MC list ..
  */
-static void set_multicast_list(struct device *dev)
+static void set_multicast_list(struct net_device *dev)
 {
 	if(!dev->start)
 	{
@@ -1304,7 +1304,7 @@
 
 #ifdef MODULE
 static char devicename[9] = { 0, };
-static struct device dev_ni52 = {
+static struct net_device dev_ni52 = {
 	devicename,	/* "ni5210": device name inserted by net_init.c */
 	0, 0, 0, 0,
 	0x300, 9,	 /* I/O address, IRQ */
@@ -1349,7 +1349,7 @@
 /*
  * DUMP .. we expect a not running CMD unit and enough space
  */
-void ni52_dump(struct device *dev,void *ptr)
+void ni52_dump(struct net_device *dev,void *ptr)
 {
 	struct priv *p = (struct priv *) dev->priv;
 	struct dump_cmd_struct *dump_cmd = (struct dump_cmd_struct *) ptr;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/ni65.c linux/drivers/net/ni65.c
--- v2.3.13/linux/drivers/net/ni65.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/ni65.c	Wed Aug 18 11:36:42 1999
@@ -220,19 +220,19 @@
 	int features;
 };
 
-static int  ni65_probe1(struct device *dev,int);
+static int  ni65_probe1(struct net_device *dev,int);
 static void ni65_interrupt(int irq, void * dev_id, struct pt_regs *regs);
-static void ni65_recv_intr(struct device *dev,int);
-static void ni65_xmit_intr(struct device *dev,int);
-static int  ni65_open(struct device *dev);
-static int  ni65_lance_reinit(struct device *dev);
+static void ni65_recv_intr(struct net_device *dev,int);
+static void ni65_xmit_intr(struct net_device *dev,int);
+static int  ni65_open(struct net_device *dev);
+static int  ni65_lance_reinit(struct net_device *dev);
 static void ni65_init_lance(struct priv *p,unsigned char*,int,int);
-static int  ni65_send_packet(struct sk_buff *skb, struct device *dev);
-static int  ni65_close(struct device *dev);
-static int  ni65_alloc_buffer(struct device *dev);
+static int  ni65_send_packet(struct sk_buff *skb, struct net_device *dev);
+static int  ni65_close(struct net_device *dev);
+static int  ni65_alloc_buffer(struct net_device *dev);
 static void ni65_free_buffer(struct priv *p);
-static struct net_device_stats *ni65_get_stats(struct device *);
-static void set_multicast_list(struct device *dev);
+static struct net_device_stats *ni65_get_stats(struct net_device *);
+static void set_multicast_list(struct net_device *dev);
 
 static int irqtab[] __initdata = { 9,12,15,5 }; /* irq config-translate */
 static int dmatab[] __initdata = { 0,3,5,6,7 }; /* dma config-translate and autodetect */
@@ -265,7 +265,7 @@
 /*
  * open interface (up)
  */
-static int ni65_open(struct device *dev)
+static int ni65_open(struct net_device *dev)
 {
 	struct priv *p = (struct priv *) dev->priv;
 	int irqval = request_irq(dev->irq, &ni65_interrupt,0,
@@ -295,7 +295,7 @@
 /*
  * close interface (down)
  */
-static int ni65_close(struct device *dev)
+static int ni65_close(struct net_device *dev)
 {
 	struct priv *p = (struct priv *) dev->priv;
 
@@ -326,7 +326,7 @@
 #ifdef MODULE
 static
 #endif
-int __init ni65_probe(struct device *dev)
+int __init ni65_probe(struct net_device *dev)
 {
 	int *port;
 	static int ports[] = {0x360,0x300,0x320,0x340, 0};
@@ -348,7 +348,7 @@
 /*
  * this is the real card probe ..
  */
-static int __init ni65_probe1(struct device *dev,int ioaddr)
+static int __init ni65_probe1(struct net_device *dev,int ioaddr)
 {
 	int i,j;
 	struct priv *p;
@@ -531,7 +531,7 @@
 /*
  * allocate memory area and check the 16MB border
  */
-static void *ni65_alloc_mem(struct device *dev,char *what,int size,int type)
+static void *ni65_alloc_mem(struct net_device *dev,char *what,int size,int type)
 {
 	struct sk_buff *skb=NULL;
 	unsigned char *ptr;
@@ -569,7 +569,7 @@
 /*
  * allocate all memory structures .. send/recv buffers etc ...
  */
-static int ni65_alloc_buffer(struct device *dev)
+static int ni65_alloc_buffer(struct net_device *dev)
 {
 	unsigned char *ptr;
 	struct priv *p;
@@ -655,7 +655,7 @@
 /*
  * stop and (re)start lance .. e.g after an error
  */
-static void ni65_stop_start(struct device *dev,struct priv *p)
+static void ni65_stop_start(struct net_device *dev,struct priv *p)
 {
 	int csr0 = CSR0_INEA;
 
@@ -724,7 +724,7 @@
 /*
  * init lance (write init-values .. init-buffers) (open-helper)
  */
-static int ni65_lance_reinit(struct device *dev)
+static int ni65_lance_reinit(struct net_device *dev)
 {
 	 int i;
 	 struct priv *p = (struct priv *) dev->priv;
@@ -809,7 +809,7 @@
 static void ni65_interrupt(int irq, void * dev_id, struct pt_regs * regs)
 {
 	int csr0;
-	struct device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	struct priv *p;
 	int bcnt = 32;
 
@@ -925,7 +925,7 @@
  * We have received an Xmit-Interrupt ..
  * send a new packet if necessary
  */
-static void ni65_xmit_intr(struct device *dev,int csr0)
+static void ni65_xmit_intr(struct net_device *dev,int csr0)
 {
 	struct priv *p = (struct priv *) dev->priv;
 
@@ -990,7 +990,7 @@
 /*
  * We have received a packet
  */
-static void ni65_recv_intr(struct device *dev,int csr0)
+static void ni65_recv_intr(struct net_device *dev,int csr0)
 {
 	struct rmd *rmdp;
 	int rmdstat,len;
@@ -1082,7 +1082,7 @@
 /*
  * kick xmitter ..
  */
-static int ni65_send_packet(struct sk_buff *skb, struct device *dev)
+static int ni65_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
 	struct priv *p = (struct priv *) dev->priv;
 
@@ -1162,7 +1162,7 @@
 	return 0;
 }
 
-static struct net_device_stats *ni65_get_stats(struct device *dev)
+static struct net_device_stats *ni65_get_stats(struct net_device *dev)
 {
 
 #if 0
@@ -1179,7 +1179,7 @@
 	return &((struct priv *) dev->priv)->stats;
 }
 
-static void set_multicast_list(struct device *dev)
+static void set_multicast_list(struct net_device *dev)
 {
 	if(!ni65_lance_reinit(dev))
 		printk(KERN_ERR "%s: Can't switch card into MC mode!\n",dev->name);
@@ -1189,7 +1189,7 @@
 #ifdef MODULE
 static char devicename[9] = { 0, };
 
-static struct device dev_ni65 = {
+static struct net_device dev_ni65 = {
 	devicename,	/* "ni6510": device name inserted by net_init.c */
 	0, 0, 0, 0,
 	0x360, 9,	 /* I/O address, IRQ */
diff -u --recursive --new-file v2.3.13/linux/drivers/net/olympic.c linux/drivers/net/olympic.c
--- v2.3.13/linux/drivers/net/olympic.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/olympic.c	Wed Aug 18 16:24:11 1999
@@ -22,6 +22,9 @@
  *
  *  6/8/99  - Official Release 0.2.0   
  *            Merged into the kernel code 
+ *  8/18/99 - Updated driver for 2.3.13 kernel to use new pci
+ *	      resource. Driver also reports the card name returned by
+ *            the pci resource.
  *  
  *  To Do:
  *
@@ -83,7 +86,7 @@
  */
 
 static char *version = 
-"Olympic.c v0.2.0 6/8/99 - Peter De Schrijver & Mike Phillips" ; 
+"Olympic.c v0.3.0 8/18/99 - Peter De Schrijver & Mike Phillips" ; 
 
 static char *open_maj_error[]  = {"No error", "Lobe Media Test", "Physical Insertion",
 				   "Address Verification", "Neighbor Notification (Ring Poll)",
@@ -128,26 +131,26 @@
 
 MODULE_PARM(message_level, "1-" __MODULE_STRING(OLYMPIC_MAX_ADAPTERS) "i") ; 
 
-static int olympic_scan(struct device *dev);
-static int olympic_init(struct device *dev);
-static int olympic_open(struct device *dev);
-static int olympic_xmit(struct sk_buff *skb, struct device *dev);
-static int olympic_close(struct device *dev);
-static void olympic_set_rx_mode(struct device *dev);
+static int olympic_scan(struct net_device *dev);
+static int olympic_init(struct net_device *dev);
+static int olympic_open(struct net_device *dev);
+static int olympic_xmit(struct sk_buff *skb, struct net_device *dev);
+static int olympic_close(struct net_device *dev);
+static void olympic_set_rx_mode(struct net_device *dev);
 static void olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static struct net_device_stats * olympic_get_stats(struct device *dev);
-static int olympic_set_mac_address(struct device *dev, void *addr) ; 
-static void olympic_arb_cmd(struct device *dev);
-static int olympic_change_mtu(struct device *dev, int mtu);
-static void olympic_srb_bh(struct device *dev) ; 
-static void olympic_asb_bh(struct device *dev) ; 
+static struct net_device_stats * olympic_get_stats(struct net_device *dev);
+static int olympic_set_mac_address(struct net_device *dev, void *addr) ; 
+static void olympic_arb_cmd(struct net_device *dev);
+static int olympic_change_mtu(struct net_device *dev, int mtu);
+static void olympic_srb_bh(struct net_device *dev) ; 
+static void olympic_asb_bh(struct net_device *dev) ; 
 #if OLYMPIC_NETWORK_MONITOR
 #ifdef CONFIG_PROC_FS
-static int sprintf_info(char *buffer, struct device *dev) ; 
+static int sprintf_info(char *buffer, struct net_device *dev) ; 
 #endif
 #endif
 
-__initfunc(int olympic_probe(struct device *dev)) 
+__initfunc(int olympic_probe(struct net_device *dev)) 
 {
 	int cards_found;
 
@@ -155,7 +158,7 @@
 	return cards_found ? 0 : -ENODEV;
 }
 
-__initfunc(static int olympic_scan(struct device *dev)) 
+__initfunc(static int olympic_scan(struct net_device *dev)) 
 {
 	struct pci_dev *pci_device = NULL ;
 	struct olympic_private *olympic_priv;
@@ -169,7 +172,7 @@
 			/* Check to see if io has been allocated, if so, we've already done this card,
 			   so continue on the card discovery loop  */
 
-			if (check_region(pci_device->base_address[0] & (~3), OLYMPIC_IO_SPACE)) {
+			if (check_region(pci_device->resource[0].start, OLYMPIC_IO_SPACE)) {
 				card_no++ ; 
 				continue ; 
 			}
@@ -184,12 +187,13 @@
 			dev->priv=(void *)olympic_priv;
 #if OLYMPIC_DEBUG  
 			printk("pci_device: %p, dev:%p, dev->priv: %p\n", pci_device, dev, dev->priv);
-#endif 
+#endif
 			dev->irq=pci_device->irq;
-			dev->base_addr=pci_device->base_address[0] & (~3);
+			dev->base_addr=pci_device->resource[0].start;
 			dev->init=&olympic_init;
-			olympic_priv->olympic_mmio=ioremap(pci_device->base_address[1],256);
-			olympic_priv->olympic_lap=ioremap(pci_device->base_address[2],2048);
+			olympic_priv->olympic_card_name = (char *)pci_device->resource[0].name ; 
+			olympic_priv->olympic_mmio=ioremap(pci_device->resource[1].start,256);
+			olympic_priv->olympic_lap=ioremap(pci_device->resource[2].start,2048);
 			
 			if ((pkt_buf_sz[card_no] < 100) || (pkt_buf_sz[card_no] > 18000) )
 				olympic_priv->pkt_buf_sz = PKT_BUF_SZ ; 
@@ -222,7 +226,7 @@
 }
 
 
-__initfunc(static int olympic_init(struct device *dev)) 
+__initfunc(static int olympic_init(struct net_device *dev)) 
 {
     	struct olympic_private *olympic_priv;
 	__u8 *olympic_mmio, *init_srb,*adapter_addr;
@@ -233,7 +237,7 @@
 	olympic_mmio=olympic_priv->olympic_mmio;
 
 	printk("%s \n", version);
-	printk("%s: IBM PCI tokenring card. I/O at %hx, MMIO at %p, LAP at %p, using irq %d\n",dev->name, (unsigned int) dev->base_addr,olympic_priv->olympic_mmio, olympic_priv->olympic_lap, dev->irq);
+	printk("%s: %s. I/O at %hx, MMIO at %p, LAP at %p, using irq %d\n",dev->name, olympic_priv->olympic_card_name, (unsigned int) dev->base_addr,olympic_priv->olympic_mmio, olympic_priv->olympic_lap, dev->irq);
 
 	request_region(dev->base_addr, OLYMPIC_IO_SPACE, "olympic");
 	writel(readl(olympic_mmio+BCTL) | BCTL_SOFTRESET,olympic_mmio+BCTL);
@@ -337,7 +341,7 @@
 
 }
 
-static int olympic_open(struct device *dev) 
+static int olympic_open(struct net_device *dev) 
 {
 	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
 	__u8 *olympic_mmio=olympic_priv->olympic_mmio,*init_srb;
@@ -628,7 +632,7 @@
  *	of blindly processing the next frame.
  *	
  */
-static void olympic_rx(struct device *dev)
+static void olympic_rx(struct net_device *dev)
 {
 	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
 	__u8 *olympic_mmio=olympic_priv->olympic_mmio;
@@ -742,7 +746,7 @@
 
 static void olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs) 
 {
-	struct device *dev= (struct device *)dev_id;
+	struct net_device *dev= (struct net_device *)dev_id;
 	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
 	__u8 *olympic_mmio=olympic_priv->olympic_mmio;
 	__u32 sisr;
@@ -834,7 +838,7 @@
 
 }	
 
-static int olympic_xmit(struct sk_buff *skb, struct device *dev) 
+static int olympic_xmit(struct sk_buff *skb, struct net_device *dev) 
 {
 	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
     __u8 *olympic_mmio=olympic_priv->olympic_mmio;
@@ -864,7 +868,7 @@
 }
 	
 
-static int olympic_close(struct device *dev) 
+static int olympic_close(struct net_device *dev) 
 {
 	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
     	__u8 *olympic_mmio=olympic_priv->olympic_mmio,*srb;
@@ -928,7 +932,7 @@
 	
 }
 
-static void olympic_set_rx_mode(struct device *dev) 
+static void olympic_set_rx_mode(struct net_device *dev) 
 {
 	struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ; 
    	__u8 *olympic_mmio = olympic_priv->olympic_mmio ; 
@@ -1028,7 +1032,7 @@
 
 }
 
-static void olympic_srb_bh(struct device *dev) 
+static void olympic_srb_bh(struct net_device *dev) 
 { 
 	struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ; 
    	__u8 *olympic_mmio = olympic_priv->olympic_mmio ; 
@@ -1175,14 +1179,14 @@
 
 } 
 
-static struct net_device_stats * olympic_get_stats(struct device *dev)
+static struct net_device_stats * olympic_get_stats(struct net_device *dev)
 {
 	struct olympic_private *olympic_priv ;
 	olympic_priv=(struct olympic_private *) dev->priv;
 	return (struct net_device_stats *) &olympic_priv->olympic_stats; 
 }
 
-static int olympic_set_mac_address (struct device *dev, void *addr) 
+static int olympic_set_mac_address (struct net_device *dev, void *addr) 
 {
 	struct sockaddr *saddr = addr ; 
 	struct olympic_private *olympic_priv = (struct olympic_private *)dev->priv ; 
@@ -1204,7 +1208,7 @@
 	return 0 ; 
 }
 
-static void olympic_arb_cmd(struct device *dev)
+static void olympic_arb_cmd(struct net_device *dev)
 {
 	struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv;
     	__u8 *olympic_mmio=olympic_priv->olympic_mmio;
@@ -1394,7 +1398,7 @@
 		printk(KERN_WARNING "%s: Unknown arb command \n", dev->name);
 }
 
-static void olympic_asb_bh(struct device *dev) 
+static void olympic_asb_bh(struct net_device *dev) 
 {
 	struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ; 
 	__u8 *arb_block, *asb_block ; 
@@ -1434,7 +1438,7 @@
 	olympic_priv->asb_queued = 0 ; 
 }
  
-static int olympic_change_mtu(struct device *dev, int mtu) 
+static int olympic_change_mtu(struct net_device *dev, int mtu) 
 {
 	struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv;
 	__u16 max_mtu ; 
@@ -1465,7 +1469,7 @@
 	off_t pos=0;
 	int size;
 	
-	struct device *dev;
+	struct net_device *dev;
 
 
 	size = sprintf(buffer, 
@@ -1479,7 +1483,7 @@
 	
 		for (dev = dev_base; dev != NULL; dev = dev->next) 
 		{
-			if (dev->base_addr == (pci_device->base_address[0] & (~3)) ) { /* Yep, an Olympic device */	
+			if (dev->base_addr == pci_device->resource[0].start ) { /* Yep, an Olympic device */	
 				size = sprintf_info(buffer+len, dev);
 				len+=size;
 				pos=begin+len;
@@ -1502,7 +1506,7 @@
 	return len;
 }
 
-static int sprintf_info(char *buffer, struct device *dev)
+static int sprintf_info(char *buffer, struct net_device *dev)
 {
 	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
 	__u8 *oat = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ; 
@@ -1602,7 +1606,7 @@
 
 #ifdef MODULE
 
-static struct device* dev_olympic[OLYMPIC_MAX_ADAPTERS];
+static struct net_device* dev_olympic[OLYMPIC_MAX_ADAPTERS];
 
 int init_module(void)
 {
@@ -1625,7 +1629,7 @@
 		dev_olympic[i]->init      = &olympic_probe;
 
 	        if (register_trdev(dev_olympic[i]) != 0) {
-			kfree_s(dev_olympic[i], sizeof(struct device));
+			kfree_s(dev_olympic[i], sizeof(struct net_device));
 			dev_olympic[i] = NULL;
 		        if (i == 0) {
 			        printk("Olympic: No IBM PCI Token Ring cards found in system.\n");
@@ -1649,7 +1653,7 @@
 			 unregister_trdev(dev_olympic[i]);
 			 release_region(dev_olympic[i]->base_addr, OLYMPIC_IO_SPACE);
 			 kfree_s(dev_olympic[i]->priv, sizeof(struct olympic_private));
-			 kfree_s(dev_olympic[i], sizeof(struct device));
+			 kfree_s(dev_olympic[i], sizeof(struct net_device));
 			 dev_olympic[i] = NULL;
                 }
 
diff -u --recursive --new-file v2.3.13/linux/drivers/net/olympic.h linux/drivers/net/olympic.h
--- v2.3.13/linux/drivers/net/olympic.h	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/olympic.h	Wed Aug 18 16:24:11 1999
@@ -243,6 +243,7 @@
 
 	__u8 *olympic_mmio;
 	__u8 *olympic_lap;
+	char *olympic_card_name ; 
 
 	volatile int srb_queued;    /* True if an SRB is still posted */	
 	wait_queue_head_t srb_wait;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/pcnet32.c linux/drivers/net/pcnet32.c
--- v2.3.13/linux/drivers/net/pcnet32.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/pcnet32.c	Wed Aug 18 11:36:42 1999
@@ -45,7 +45,7 @@
 static int pcnet32_debug = 1;
 
 #ifdef MODULE
-static struct device *pcnet32_dev = NULL;
+static struct net_device *pcnet32_dev = NULL;
 #endif
 
 static const int max_interrupt_work = 20;
@@ -264,22 +264,22 @@
          full_duplex:1,                     /* full duplex possible */
          mii:1;                             /* mii port available */
 #ifdef MODULE
-    struct device *next;
+    struct net_device *next;
 #endif    
 };
 
-int  pcnet32_probe(struct device *);
-static int  pcnet32_probe1(struct device *, unsigned long, unsigned char, int, int);
-static int  pcnet32_open(struct device *);
-static int  pcnet32_init_ring(struct device *);
-static int  pcnet32_start_xmit(struct sk_buff *, struct device *);
-static int  pcnet32_rx(struct device *);
+int  pcnet32_probe(struct net_device *);
+static int  pcnet32_probe1(struct net_device *, 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 *);
+static int  pcnet32_rx(struct net_device *);
 static void pcnet32_interrupt(int, void *, struct pt_regs *);
-static int  pcnet32_close(struct device *);
-static struct net_device_stats *pcnet32_get_stats(struct device *);
-static void pcnet32_set_multicast_list(struct device *);
+static int  pcnet32_close(struct net_device *);
+static struct net_device_stats *pcnet32_get_stats(struct net_device *);
+static void pcnet32_set_multicast_list(struct net_device *);
 #ifdef HAVE_PRIVATE_IOCTL
-static int  pcnet32_mii_ioctl(struct device *, struct ifreq *, int);
+static int  pcnet32_mii_ioctl(struct net_device *, struct ifreq *, int);
 #endif
 
 enum pci_flags_bit {
@@ -291,7 +291,7 @@
     const char *name;
     u16 vendor_id, device_id, svid, sdid, flags;
     int io_size;
-    int (*probe1) (struct device *, unsigned long, unsigned char, int, int);
+    int (*probe1) (struct net_device *, unsigned long, unsigned char, int, int);
 };
 
 static struct pcnet32_pci_id_info pcnet32_tbl[] = {
@@ -419,7 +419,7 @@
 
 
 
-int __init pcnet32_probe (struct device *dev)
+int __init pcnet32_probe (struct net_device *dev)
 {
     unsigned long ioaddr = dev ? dev->base_addr: 0;
     unsigned int  irq_line = dev ? dev->irq : 0;
@@ -507,7 +507,7 @@
 
 /* pcnet32_probe1 */
 static int __init
-pcnet32_probe1(struct device *dev, unsigned long ioaddr, unsigned char irq_line, int shared, int card_idx)
+pcnet32_probe1(struct net_device *dev, unsigned long ioaddr, unsigned char irq_line, int shared, int card_idx)
 {
     struct pcnet32_private *lp;
     int i,media,fdx = 0, mii = 0;
@@ -699,7 +699,7 @@
 
 
 static int
-pcnet32_open(struct device *dev)
+pcnet32_open(struct net_device *dev)
 {
     struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv;
     unsigned long ioaddr = dev->base_addr;
@@ -807,7 +807,7 @@
  */
 
 static void 
-pcnet32_purge_tx_ring(struct device *dev)
+pcnet32_purge_tx_ring(struct net_device *dev)
 {
     struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv;
     int i;
@@ -823,7 +823,7 @@
 
 /* Initialize the PCNET32 Rx and Tx rings. */
 static int
-pcnet32_init_ring(struct device *dev)
+pcnet32_init_ring(struct net_device *dev)
 {
     struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv;
     int i;
@@ -861,7 +861,7 @@
 }
 
 static void
-pcnet32_restart(struct device *dev, unsigned int csr0_bits)
+pcnet32_restart(struct net_device *dev, unsigned int csr0_bits)
 {
     struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv;
     unsigned long ioaddr = dev->base_addr;
@@ -882,7 +882,7 @@
 }
 
 static int
-pcnet32_start_xmit(struct sk_buff *skb, struct device *dev)
+pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
     struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv;
     unsigned int ioaddr = dev->base_addr;
@@ -972,7 +972,7 @@
 static void
 pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
-    struct device *dev = (struct device *)dev_id;
+    struct net_device *dev = (struct net_device *)dev_id;
     struct pcnet32_private *lp;
     unsigned long ioaddr;
     u16 csr0,rap;
@@ -1104,7 +1104,7 @@
 }
 
 static int
-pcnet32_rx(struct device *dev)
+pcnet32_rx(struct net_device *dev)
 {
     struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv;
     int entry = lp->cur_rx & RX_RING_MOD_MASK;
@@ -1195,7 +1195,7 @@
 }
 
 static int
-pcnet32_close(struct device *dev)
+pcnet32_close(struct net_device *dev)
 {
     unsigned long ioaddr = dev->base_addr;
     struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv;
@@ -1241,7 +1241,7 @@
 }
 
 static struct net_device_stats *
-pcnet32_get_stats(struct device *dev)
+pcnet32_get_stats(struct net_device *dev)
 {
     struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv;
     unsigned long ioaddr = dev->base_addr;
@@ -1259,7 +1259,7 @@
 }
 
 /* taken from the sunlance driver, which it took from the depca driver */
-static void pcnet32_load_multicast (struct device *dev)
+static void pcnet32_load_multicast (struct net_device *dev)
 {
     struct pcnet32_private *lp = (struct pcnet32_private *) dev->priv;
     volatile struct pcnet32_init_block *ib = &lp->init_block;
@@ -1311,7 +1311,7 @@
 /*
  * Set or clear the multicast filter for this adaptor.
  */
-static void pcnet32_set_multicast_list(struct device *dev)
+static void pcnet32_set_multicast_list(struct net_device *dev)
 {
     unsigned long ioaddr = dev->base_addr;
     struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv;    
@@ -1331,7 +1331,7 @@
 }
 
 #ifdef HAVE_PRIVATE_IOCTL
-static int pcnet32_mii_ioctl(struct device *dev, struct ifreq *rq, int cmd)
+static int pcnet32_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
     unsigned long ioaddr = dev->base_addr;
     struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv;    
@@ -1387,7 +1387,7 @@
 void
 cleanup_module(void)
 {
-    struct device *next_dev;
+    struct net_device *next_dev;
 
     /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
     while (pcnet32_dev) {
diff -u --recursive --new-file v2.3.13/linux/drivers/net/plip.c linux/drivers/net/plip.c
--- v2.3.13/linux/drivers/net/plip.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/plip.c	Wed Aug 18 11:36:42 1999
@@ -143,20 +143,20 @@
 #define PAR_CONTROL(dev)	((dev)->base_addr+2)
 
 /* Bottom halfs */
-static void plip_kick_bh(struct device *dev);
-static void plip_bh(struct device *dev);
+static void plip_kick_bh(struct net_device *dev);
+static void plip_bh(struct net_device *dev);
 
 /* Interrupt handler */
 static void plip_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 
 /* Functions for DEV methods */
 static int plip_rebuild_header(struct sk_buff *skb);
-static int plip_tx_packet(struct sk_buff *skb, struct device *dev);
-static int plip_open(struct device *dev);
-static int plip_close(struct device *dev);
-static struct net_device_stats *plip_get_stats(struct device *dev);
-static int plip_config(struct device *dev, struct ifmap *map);
-static int plip_ioctl(struct device *dev, struct ifreq *ifr, int cmd);
+static int plip_tx_packet(struct sk_buff *skb, struct net_device *dev);
+static int plip_open(struct net_device *dev);
+static int plip_close(struct net_device *dev);
+static struct net_device_stats *plip_get_stats(struct net_device *dev);
+static int plip_config(struct net_device *dev, struct ifmap *map);
+static int plip_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
 static int plip_preempt(void *handle);
 static void plip_wakeup(void *handle);
 
@@ -229,12 +229,12 @@
 
    PLIP is rather weird, because of the way it interacts with the parport
    system.  It is _not_ initialised from Space.c.  Instead, plip_init()
-   is called, and that function makes up a "struct device" for each port, and
+   is called, and that function makes up a "struct net_device" for each port, and
    then calls us here.
 
    */
 int __init
-plip_init_dev(struct device *dev, struct parport *pb)
+plip_init_dev(struct net_device *dev, struct parport *pb)
 {
 	struct net_local *nl;
 	struct pardevice *pardev;
@@ -311,7 +311,7 @@
    This routine is kicked by do_timer().
    Request `plip_bh' to be invoked. */
 static void
-plip_kick_bh(struct device *dev)
+plip_kick_bh(struct net_device *dev)
 {
 	struct net_local *nl = (struct net_local *)dev->priv;
 
@@ -322,17 +322,17 @@
 }
 
 /* Forward declarations of internal routines */
-static int plip_none(struct device *, struct net_local *,
+static int plip_none(struct net_device *, struct net_local *,
 		     struct plip_local *, struct plip_local *);
-static int plip_receive_packet(struct device *, struct net_local *,
+static int plip_receive_packet(struct net_device *, struct net_local *,
 			       struct plip_local *, struct plip_local *);
-static int plip_send_packet(struct device *, struct net_local *,
+static int plip_send_packet(struct net_device *, struct net_local *,
 			    struct plip_local *, struct plip_local *);
-static int plip_connection_close(struct device *, struct net_local *,
+static int plip_connection_close(struct net_device *, struct net_local *,
 				 struct plip_local *, struct plip_local *);
-static int plip_error(struct device *, struct net_local *,
+static int plip_error(struct net_device *, struct net_local *,
 		      struct plip_local *, struct plip_local *);
-static int plip_bh_timeout_error(struct device *dev, struct net_local *nl,
+static int plip_bh_timeout_error(struct net_device *dev, struct net_local *nl,
 				 struct plip_local *snd,
 				 struct plip_local *rcv,
 				 int error);
@@ -342,7 +342,7 @@
 #define ERROR     2
 #define HS_TIMEOUT	3
 
-typedef int (*plip_func)(struct device *dev, struct net_local *nl,
+typedef int (*plip_func)(struct net_device *dev, struct net_local *nl,
 			 struct plip_local *snd, struct plip_local *rcv);
 
 static plip_func connection_state_table[] =
@@ -356,7 +356,7 @@
 
 /* Bottom half handler of PLIP. */
 static void
-plip_bh(struct device *dev)
+plip_bh(struct net_device *dev)
 {
 	struct net_local *nl = (struct net_local *)dev->priv;
 	struct plip_local *snd = &nl->snd_data;
@@ -374,7 +374,7 @@
 }
 
 static int
-plip_bh_timeout_error(struct device *dev, struct net_local *nl,
+plip_bh_timeout_error(struct net_device *dev, struct net_local *nl,
 		      struct plip_local *snd, struct plip_local *rcv,
 		      int error)
 {
@@ -450,7 +450,7 @@
 }
 
 static int
-plip_none(struct device *dev, struct net_local *nl,
+plip_none(struct net_device *dev, struct net_local *nl,
 	  struct plip_local *snd, struct plip_local *rcv)
 {
 	return OK;
@@ -509,7 +509,7 @@
 
 /* PLIP_RECEIVE_PACKET --- receive a packet */
 static int
-plip_receive_packet(struct device *dev, struct net_local *nl,
+plip_receive_packet(struct net_device *dev, struct net_local *nl,
 		    struct plip_local *snd, struct plip_local *rcv)
 {
 	unsigned short status_addr = PAR_STATUS(dev);
@@ -675,7 +675,7 @@
 
 /* PLIP_SEND_PACKET --- send a packet */
 static int
-plip_send_packet(struct device *dev, struct net_local *nl,
+plip_send_packet(struct net_device *dev, struct net_local *nl,
 		 struct plip_local *snd, struct plip_local *rcv)
 {
 	unsigned short data_addr = PAR_DATA(dev);
@@ -791,7 +791,7 @@
 }
 
 static int
-plip_connection_close(struct device *dev, struct net_local *nl,
+plip_connection_close(struct net_device *dev, struct net_local *nl,
 		      struct plip_local *snd, struct plip_local *rcv)
 {
 	spin_lock_irq(&nl->lock);
@@ -810,7 +810,7 @@
 
 /* PLIP_ERROR --- wait till other end settled */
 static int
-plip_error(struct device *dev, struct net_local *nl,
+plip_error(struct net_device *dev, struct net_local *nl,
 	   struct plip_local *snd, struct plip_local *rcv)
 {
 	unsigned char status;
@@ -838,7 +838,7 @@
 static void
 plip_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
-	struct device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	struct net_local *nl;
 	struct plip_local *rcv;
 	unsigned char c0;
@@ -897,7 +897,7 @@
 static int
 plip_rebuild_header(struct sk_buff *skb)
 {
-	struct device *dev = skb->dev;
+	struct net_device *dev = skb->dev;
 	struct net_local *nl = (struct net_local *)dev->priv;
 	struct ethhdr *eth = (struct ethhdr *)skb->data;
 
@@ -910,7 +910,7 @@
 }
 
 static int
-plip_tx_packet(struct sk_buff *skb, struct device *dev)
+plip_tx_packet(struct sk_buff *skb, struct net_device *dev)
 {
 	struct net_local *nl = (struct net_local *)dev->priv;
 	struct plip_local *snd = &nl->snd_data;
@@ -962,7 +962,7 @@
    its IRQ line.
  */
 static int
-plip_open(struct device *dev)
+plip_open(struct net_device *dev)
 {
 	struct net_local *nl = (struct net_local *)dev->priv;
 	struct in_device *in_dev;
@@ -1016,7 +1016,7 @@
 
 /* The inverse routine to plip_open (). */
 static int
-plip_close(struct device *dev)
+plip_close(struct net_device *dev)
 {
 	struct net_local *nl = (struct net_local *)dev->priv;
 	struct plip_local *snd = &nl->snd_data;
@@ -1059,7 +1059,7 @@
 static int
 plip_preempt(void *handle)
 {
-	struct device *dev = (struct device *)handle;
+	struct net_device *dev = (struct net_device *)handle;
 	struct net_local *nl = (struct net_local *)dev->priv;
 
 	/* Stand our ground if a datagram is on the wire */
@@ -1075,7 +1075,7 @@
 static void
 plip_wakeup(void *handle)
 {
-	struct device *dev = (struct device *)handle;
+	struct net_device *dev = (struct net_device *)handle;
 	struct net_local *nl = (struct net_local *)dev->priv;
 
 	if (nl->port_owner) {
@@ -1102,7 +1102,7 @@
 }
 
 static struct net_device_stats *
-plip_get_stats(struct device *dev)
+plip_get_stats(struct net_device *dev)
 {
 	struct net_local *nl = (struct net_local *)dev->priv;
 	struct net_device_stats *r = &nl->enet_stats;
@@ -1111,7 +1111,7 @@
 }
 
 static int
-plip_config(struct device *dev, struct ifmap *map)
+plip_config(struct net_device *dev, struct ifmap *map)
 {
 	struct net_local *nl = (struct net_local *) dev->priv;
 	struct pardevice *pardev = nl->pardev;
@@ -1132,7 +1132,7 @@
 }
 
 static int
-plip_ioctl(struct device *dev, struct ifreq *rq, int cmd)
+plip_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct net_local *nl = (struct net_local *) dev->priv;
 	struct plipconf *pc = (struct plipconf *) &rq->ifr_data;
@@ -1158,7 +1158,7 @@
 MODULE_PARM(parport, "1-" __MODULE_STRING(PLIP_MAX) "i");
 MODULE_PARM(timid, "1i");
 
-static struct device *dev_plip[PLIP_MAX] = { NULL, };
+static struct net_device *dev_plip[PLIP_MAX] = { NULL, };
 
 #ifdef MODULE
 void
@@ -1245,13 +1245,13 @@
 				printk(KERN_ERR "plip: too many devices\n");
 				break;
 			}
-			dev_plip[i] = kmalloc(sizeof(struct device),
+			dev_plip[i] = kmalloc(sizeof(struct net_device),
 					      GFP_KERNEL);
 			if (!dev_plip[i]) {
 				printk(KERN_ERR "plip: memory squeeze\n");
 				break;
 			}
-			memset(dev_plip[i], 0, sizeof(struct device));
+			memset(dev_plip[i], 0, sizeof(struct net_device));
 			dev_plip[i]->name = 
 				kmalloc(strlen("plipXXX"), GFP_KERNEL);
 			if (!dev_plip[i]->name) {
diff -u --recursive --new-file v2.3.13/linux/drivers/net/ppp.c linux/drivers/net/ppp.c
--- v2.3.13/linux/drivers/net/ppp.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/ppp.c	Wed Aug 18 11:36:42 1999
@@ -299,7 +299,7 @@
  * Called at boot time if the PPP driver is compiled into the kernel.
  */
 int
-ppp_init(struct device *dev)
+ppp_init(struct net_device *dev)
 {
 	static int first_time = 1;
 	int    answer = 0;
@@ -1450,12 +1450,12 @@
  * Network device driver callback routines
  */
 
-static int ppp_init_dev(struct device *dev);
-static int ppp_dev_open(struct device *);
-static int ppp_dev_ioctl(struct device *dev, struct ifreq *ifr, int cmd);
-static int ppp_dev_close(struct device *);
-static int ppp_dev_xmit(struct sk_buff *, struct device *);
-static struct net_device_stats *ppp_dev_stats (struct device *);
+static int ppp_init_dev(struct net_device *dev);
+static int ppp_dev_open(struct net_device *);
+static int ppp_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
+static int ppp_dev_close(struct net_device *);
+static int ppp_dev_xmit(struct sk_buff *, struct net_device *);
+static struct net_device_stats *ppp_dev_stats (struct net_device *);
 
 /*
  * Information for the protocol decoder
@@ -1493,7 +1493,7 @@
  * Called when the PPP network interface device is actually created.
  */
 static int
-ppp_init_dev (struct device *dev)
+ppp_init_dev (struct net_device *dev)
 {
 	dev->hard_header_len  = PPP_HDRLEN;
 
@@ -1520,7 +1520,7 @@
  */
 
 static int
-ppp_dev_open (struct device *dev)
+ppp_dev_open (struct net_device *dev)
 {
 	struct ppp *ppp = dev2ppp(dev);
 
@@ -1539,7 +1539,7 @@
  */
 
 static int
-ppp_dev_close (struct device *dev)
+ppp_dev_close (struct net_device *dev)
 {
 	struct ppp *ppp = dev2ppp (dev);
 
@@ -1567,7 +1567,7 @@
  * Callback from the network layer to process the sockioctl functions.
  */
 static int
-ppp_dev_ioctl (struct device *dev, struct ifreq *ifr, int cmd)
+ppp_dev_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	struct ppp *ppp = dev2ppp(dev);
 	int nb;
@@ -2611,7 +2611,7 @@
  * Returns 1 iff the frame was not accepted.
  */
 static int
-ppp_dev_xmit(struct sk_buff *skb, struct device *dev)
+ppp_dev_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ppp *ppp = dev2ppp(dev);
 	struct tty_struct *tty = ppp2tty(ppp);
@@ -2758,7 +2758,7 @@
  * Generate the statistic information for the /proc/net/dev listing.
  */
 static struct net_device_stats *
-ppp_dev_stats (struct device *dev)
+ppp_dev_stats (struct net_device *dev)
 {
 	struct ppp *ppp = dev2ppp (dev);
 
@@ -2799,7 +2799,7 @@
 {
 	int		if_num;
 	int		status;
-	struct device	*dev;
+	struct net_device	*dev;
 	struct ppp	*ppp;
 
 	/* try to find an free device */
diff -u --recursive --new-file v2.3.13/linux/drivers/net/ppp_generic.c linux/drivers/net/ppp_generic.c
--- v2.3.13/linux/drivers/net/ppp_generic.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/ppp_generic.c	Wed Aug 18 11:36:42 1999
@@ -94,7 +94,7 @@
 	void		*rc_state;	/* its internal state */
 	unsigned long	last_xmit;	/* jiffies when last pkt sent */
 	unsigned long	last_recv;	/* jiffies when last pkt rcvd */
-	struct device	dev;		/* network interface device */
+	struct net_device	dev;		/* network interface device */
 	struct net_device_stats stats;	/* statistics */
 };
 
@@ -575,7 +575,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 device *dev)
+ppp_init(struct net_device *dev)
 {
 	int err;
 #ifndef MODULE
@@ -605,7 +605,7 @@
  * Network interface unit routines.
  */
 static int
-ppp_start_xmit(struct sk_buff *skb, struct device *dev)
+ppp_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ppp *ppp = (struct ppp *) dev->priv;
 	int npi, proto;
@@ -678,7 +678,7 @@
 }
 
 static struct net_device_stats *
-ppp_net_stats(struct device *dev)
+ppp_net_stats(struct net_device *dev)
 {
 	struct ppp *ppp = (struct ppp *) dev->priv;
 
@@ -686,7 +686,7 @@
 }
 
 static int
-ppp_net_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
+ppp_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	struct ppp *ppp = dev->priv;
 	int err = -EFAULT;
@@ -729,7 +729,7 @@
 }
 
 int
-ppp_net_init(struct device *dev)
+ppp_net_init(struct net_device *dev)
 {
 	dev->hard_header_len = PPP_HDRLEN;
 	dev->mtu = PPP_MTU;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/ptifddi.c linux/drivers/net/ptifddi.c
--- v2.3.13/linux/drivers/net/ptifddi.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/ptifddi.c	Wed Aug 18 11:36:42 1999
@@ -108,48 +108,48 @@
 {
 }
 
-static inline void pti_tx(struct ptifddi *pp, struct device *dev)
+static inline void pti_tx(struct ptifddi *pp, struct net_device *dev)
 {
 }
 
-static inline void myri_rx(struct ptifddi *pp, struct device *dev)
+static inline void myri_rx(struct ptifddi *pp, struct net_device *dev)
 {
 }
 
 static void pti_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev		= (struct device *) dev_id;
+	struct net_device *dev		= (struct net_device *) dev_id;
 	struct ptifddi *pp		= (struct ptifddi *) dev->priv;
 
 }
 
-static int pti_open(struct device *dev)
+static int pti_open(struct net_device *dev)
 {
 	struct ptifddi *pp = (struct ptifddi *) dev->priv;
 
 	return pti_init(pp, in_interrupt());
 }
 
-static int pti_close(struct device *dev)
+static int pti_close(struct net_device *dev)
 {
 	struct ptifddi *pp = (struct ptifddi *) dev->priv;
 
 	return 0;
 }
 
-static int pti_start_xmit(struct sk_buff *skb, struct device *dev)
+static int pti_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ptifddi *pp = (struct ptifddi *) dev->priv;
 }
 
-static struct enet_statistics *pti_get_stats(struct device *dev)
+static struct enet_statistics *pti_get_stats(struct net_device *dev)
 { return &(((struct ptifddi *)dev->priv)->enet_stats); }
 
-static void pti_set_multicast(struct device *dev)
+static void pti_set_multicast(struct net_device *dev)
 {
 }
 
-static inline int pti_fddi_init(struct device *dev, struct linux_sbus_device *sdev, int num)
+static inline int pti_fddi_init(struct net_device *dev, struct linux_sbus_device *sdev, int num)
 {
 	static unsigned version_printed = 0;
 	struct ptifddi *pp;
@@ -213,7 +213,7 @@
 	pti_load_main_firmware(pp);
 }
 
-int __init ptifddi_sbus_probe(struct device *dev)
+int __init ptifddi_sbus_probe(struct net_device *dev)
 {
 	struct linux_sbus *bus;
 	struct linux_sbus_device *sdev = 0;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/ptifddi.h linux/drivers/net/ptifddi.h
--- v2.3.13/linux/drivers/net/ptifddi.h	Sat Nov 29 10:33:20 1997
+++ linux/drivers/net/ptifddi.h	Wed Aug 18 11:36:45 1999
@@ -70,7 +70,7 @@
 	struct dfddi_ram	*dpram;
 	unsigned char		*reset;
 	unsigned char		*unreset;
-	struct device		*dev;
+	struct net_device		*dev;
 	struct ptifddi		*next_module;
 };
 
diff -u --recursive --new-file v2.3.13/linux/drivers/net/rcpci45.c linux/drivers/net/rcpci45.c
--- v2.3.13/linux/drivers/net/rcpci45.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/rcpci45.c	Wed Aug 18 11:36:42 1999
@@ -127,7 +127,7 @@
      *    pointer to the device structure which is part
      * of the interface to the Linux kernel.
      */
-    struct device *dev;            
+    struct net_device *dev;            
      
     char devname[8];                /* "ethN" string */
     U8     id;                        /* the AdapterID */
@@ -136,7 +136,7 @@
     U32    function;
     struct timer_list timer;        /*  timer */
     struct enet_statistics  stats; /* the statistics structure */
-    struct device *next;            /* points to the next RC adapter */
+    struct net_device *next;            /* points to the next RC adapter */
     unsigned long numOutRcvBuffers;/* number of outstanding receive buffers*/
     unsigned char shutdown;
     unsigned char reboot;
@@ -157,31 +157,31 @@
 };
 
 
-static int RCinit(struct device *dev);
-static int RCscan(struct device *dev);
-static int RCfound_device(struct device *, int, int, int, int, int, int);
+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 RCopen(struct device *);
-static int RC_xmit_packet(struct sk_buff *, struct device *);
+static int RCopen(struct net_device *);
+static int RC_xmit_packet(struct sk_buff *, struct net_device *);
 static void RCinterrupt(int, void *, struct pt_regs *);
-static int RCclose(struct device *dev);
-static struct enet_statistics *RCget_stats(struct device *);
-static int RCioctl(struct device *, struct ifreq *, int);
-static int RCconfig(struct device *, struct ifmap *);
+static int RCclose(struct net_device *dev);
+static struct enet_statistics *RCget_stats(struct net_device *);
+static int RCioctl(struct net_device *, struct ifreq *, int);
+static int RCconfig(struct net_device *, struct ifmap *);
 static void RCxmit_callback(U32, U16, PU32, U16);
 static void RCrecv_callback(U32, U8, U32, PU32, U16);
 static void RCreset_callback(U32, U32, U32, U16);
 static void RCreboot_callback(U32, U32, U32, U16);
-static int RC_allocate_and_post_buffers(struct device *, int);
+static int RC_allocate_and_post_buffers(struct net_device *, int);
 
 
 /* A list of all installed RC devices, for removing the driver module. */
-static struct device *root_RCdev = NULL;
+static struct net_device *root_RCdev = NULL;
 
 #ifdef MODULE
 int init_module(void)
 #else
-int rcpci_probe(struct device *dev)
+int rcpci_probe(struct net_device *dev)
 #endif
 {
     int cards_found;
@@ -196,7 +196,7 @@
     return cards_found ? 0 : -ENODEV;
 }
 
-static int RCscan(struct device *dev)
+static int RCscan(struct net_device *dev)
 {
     int cards_found = 0;
     static int pci_index = 0;
@@ -251,7 +251,7 @@
     return cards_found;
 }
 
-static int RCinit(struct device *dev)
+static int RCinit(struct net_device *dev)
 {
     dev->open = &RCopen;
     dev->hard_start_xmit = &RC_xmit_packet;
@@ -263,7 +263,7 @@
 }
 
 static int
-RCfound_device(struct device *dev, int memaddr, int irq, 
+RCfound_device(struct net_device *dev, int memaddr, int irq, 
                int bus, int function, int product_index, int card_idx)
 {
     int dev_size = 32768;        
@@ -273,15 +273,15 @@
 
     /* 
      * Allocate and fill new device structure. 
-     * We need enough for struct device plus DPA plus the LAN API private
+     * We need enough for struct net_device plus DPA plus the LAN API private
      * area, which requires a minimum of 16KB.  The top of the allocated
-     * area will be assigned to struct device; the next chunk will be
+     * area will be assigned to struct net_device; the next chunk will be
      * assigned to DPA; and finally, the rest will be assigned to the
      * the LAN API layer.
      */
 
 #ifdef MODULE
-    dev = (struct device *) kmalloc(dev_size, GFP_DMA | GFP_KERNEL |GFP_ATOMIC);
+    dev = (struct net_device *) kmalloc(dev_size, GFP_DMA | GFP_KERNEL |GFP_ATOMIC);
     if (!dev)
     {
         printk("rc: unable to kmalloc dev\n");
@@ -291,10 +291,10 @@
     /*
      * dev->priv will point to the start of DPA.
      */
-    dev->priv = (void *)(((long)dev + sizeof(struct device) + 15) & ~15);
+    dev->priv = (void *)(((long)dev + sizeof(struct net_device) + 15) & ~15);
 #else
     dev->priv = 0;
-    dev->priv = (struct device *) kmalloc(dev_size, GFP_DMA | GFP_KERNEL |GFP_ATOMIC);
+    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");
@@ -405,7 +405,7 @@
 }
 
 static int
-RCopen(struct device *dev)
+RCopen(struct net_device *dev)
 {
     int post_buffers = MAX_NMBR_RCV_BUFFERS;
     PDPA pDpa = (PDPA) dev->priv;
@@ -470,7 +470,7 @@
 }
 
 static int
-RC_xmit_packet(struct sk_buff *skb, struct device *dev)
+RC_xmit_packet(struct sk_buff *skb, struct net_device *dev)
 {
 
     PDPA pDpa = (PDPA) dev->priv;
@@ -551,7 +551,7 @@
 {
     struct sk_buff *skb;
     PDPA pDpa;
-    struct device *dev;
+    struct net_device *dev;
 
         pDpa = PCIAdapters[AdapterID];
         if (!pDpa)
@@ -596,7 +596,7 @@
 RCreset_callback(U32 Status, U32 p1, U32 p2, U16 AdapterID)
 {
     PDPA pDpa;
-    struct device *dev;
+    struct net_device *dev;
      
     pDpa = PCIAdapters[AdapterID];
     dev = pDpa->dev;
@@ -696,7 +696,7 @@
     U32 len, count;
     PDPA pDpa;
     struct sk_buff *skb;
-    struct device *dev;
+    struct net_device *dev;
     singleTCB tcb;
     psingleTCB ptcb = &tcb;
 
@@ -852,7 +852,7 @@
 {
 
     PDPA pDpa;
-    struct device *dev = (struct device *)(dev_id);
+    struct net_device *dev = (struct net_device *)(dev_id);
 
     pDpa = (PDPA) (dev->priv);
      
@@ -878,7 +878,7 @@
 #define REBOOT_REINIT_RETRY_LIMIT 4
 static void rc_timer(unsigned long data)
 {
-    struct device *dev = (struct device *)data;
+    struct net_device *dev = (struct net_device *)data;
     PDPA pDpa = (PDPA) (dev->priv);
     int init_status;
     static int retry = 0;
@@ -961,7 +961,7 @@
 }
 
 static int
-RCclose(struct device *dev)
+RCclose(struct net_device *dev)
 {
 
     PDPA pDpa = (PDPA) dev->priv;
@@ -1000,7 +1000,7 @@
 }
 
 static struct enet_statistics *
-RCget_stats(struct device *dev)
+RCget_stats(struct net_device *dev)
 {
     RCLINKSTATS    RCstats;
    
@@ -1087,7 +1087,7 @@
     return 0;
 }
 
-static int RCioctl(struct device *dev, struct ifreq *rq, int cmd)
+static int RCioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
     RCuser_struct RCuser;
     PDPA pDpa = dev->priv;
@@ -1244,7 +1244,7 @@
     return 0;
 }
 
-static int RCconfig(struct device *dev, struct ifmap *map)
+static int RCconfig(struct net_device *dev, struct ifmap *map)
 {
     /*
      * To be completed ...
@@ -1268,7 +1268,7 @@
 cleanup_module(void)
 {
     PDPA pDpa;
-    struct device *next;
+    struct net_device *next;
 
 
 #ifdef RCDEBUG
@@ -1297,7 +1297,7 @@
 
 
 static int
-RC_allocate_and_post_buffers(struct device *dev, int numBuffers)
+RC_allocate_and_post_buffers(struct net_device *dev, int numBuffers)
 {
 
     int i;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/rrunner.c linux/drivers/net/rrunner.c
--- v2.3.13/linux/drivers/net/rrunner.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/rrunner.c	Wed Aug 18 11:36:42 1999
@@ -72,7 +72,7 @@
 
 static int probed __initdata = 0;
 
-int __init rr_hippi_probe (struct device *dev)
+int __init rr_hippi_probe (struct net_device *dev)
 {
 	int boards_found = 0;
 	int version_disp;	/* was version info already displayed? */
@@ -202,7 +202,7 @@
 #endif
 }
 
-static struct device *root_dev = NULL;
+static struct net_device *root_dev = NULL;
 
 #ifdef MODULE
 #if LINUX_VERSION_CODE > 0x20118
@@ -224,7 +224,7 @@
 void cleanup_module(void)
 {
 	struct rr_private *rr;
-	struct device *next;
+	struct net_device *next;
 
 	while (root_dev) {
 		next = ((struct rr_private *)root_dev->priv)->next;
@@ -286,7 +286,7 @@
  * Reset the board in a sensible manner. The NIC is already halted
  * when we get here and a spin-lock is held.
  */
-static int rr_reset(struct device *dev)
+static int rr_reset(struct net_device *dev)
 {
 	struct rr_private *rrpriv;
 	struct rr_regs *regs;
@@ -502,7 +502,7 @@
 }
 
 
-static int __init rr_init(struct device *dev)
+static int __init rr_init(struct net_device *dev)
 {
 	struct rr_private *rrpriv;
 	struct rr_regs *regs;
@@ -552,7 +552,7 @@
 }
 
 
-static int rr_init1(struct device *dev)
+static int rr_init1(struct net_device *dev)
 {
 	struct rr_private *rrpriv;
 	struct rr_regs *regs;
@@ -703,7 +703,7 @@
  * events) and are handled here, outside the main interrupt handler,
  * to reduce the size of the handler.
  */
-static u32 rr_handle_event(struct device *dev, u32 prodidx, u32 eidx)
+static u32 rr_handle_event(struct net_device *dev, u32 prodidx, u32 eidx)
 {
 	struct rr_private *rrpriv;
 	struct rr_regs *regs;
@@ -795,7 +795,7 @@
 }
 
 
-static void rx_int(struct device *dev, u32 rxlimit, u32 index)
+static void rx_int(struct net_device *dev, u32 rxlimit, u32 index)
 {
 	struct rr_private *rrpriv = (struct rr_private *)dev->priv;
 	u32 pkt_len;
@@ -866,7 +866,7 @@
 {
 	struct rr_private *rrpriv;
 	struct rr_regs *regs;
-	struct device *dev = (struct device *)dev_id;
+	struct net_device *dev = (struct net_device *)dev_id;
 	u32 prodidx, rxindex, eidx, txcsmr, rxlimit, txcon;
 	unsigned long flags;
 
@@ -930,7 +930,7 @@
 }
 
 
-static int rr_open(struct device *dev)
+static int rr_open(struct net_device *dev)
 {
 	struct rr_private *rrpriv;
 	struct rr_regs *regs;
@@ -995,7 +995,7 @@
 }
 
 
-static void rr_dump(struct device *dev)
+static void rr_dump(struct net_device *dev)
 {
 	struct rr_private *rrpriv;
 	struct rr_regs *regs;
@@ -1059,7 +1059,7 @@
 }
 
 
-static int rr_close(struct device *dev)
+static int rr_close(struct net_device *dev)
 {
 	struct rr_private *rrpriv;
 	struct rr_regs *regs;
@@ -1131,7 +1131,7 @@
 }
 
 
-static int rr_start_xmit(struct sk_buff *skb, struct device *dev)
+static int rr_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct rr_private *rrpriv = (struct rr_private *)dev->priv;
 	struct rr_regs *regs = rrpriv->regs;
@@ -1197,7 +1197,7 @@
 }
 
 
-static struct net_device_stats *rr_get_stats(struct device *dev)
+static struct net_device_stats *rr_get_stats(struct net_device *dev)
 {
 	struct rr_private *rrpriv;
 
@@ -1214,7 +1214,7 @@
  * This operation requires the NIC to be halted and is performed with
  * interrupts disabled and with the spinlock hold.
  */
-static int rr_load_firmware(struct device *dev)
+static int rr_load_firmware(struct net_device *dev)
 {
 	struct rr_private *rrpriv;
 	struct rr_regs *regs;
@@ -1319,7 +1319,7 @@
 }
 
 
-static int rr_ioctl(struct device *dev, struct ifreq *rq, int cmd)
+static int rr_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct rr_private *rrpriv;
 	unsigned char *image, *oldimage;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/rrunner.h linux/drivers/net/rrunner.h
--- v2.3.13/linux/drivers/net/rrunner.h	Sat Apr 24 17:51:48 1999
+++ linux/drivers/net/rrunner.h	Wed Aug 18 11:36:45 1999
@@ -805,7 +805,7 @@
 	struct rr_regs		*regs;		/* Register base */
 	struct ring_ctrl	*rx_ctrl;	/* Receive ring control */
 	struct rr_info		*info;		/* Shared info page */
-	struct device		*next;
+	struct net_device		*next;
 	spinlock_t		lock;
 	struct timer_list	timer;
 	u32			cur_rx, cur_cmd, cur_evt;
@@ -821,20 +821,20 @@
 /*
  * Prototypes
  */
-static int rr_init(struct device *dev);
-static int rr_init1(struct device *dev);
+static int rr_init(struct net_device *dev);
+static int rr_init1(struct net_device *dev);
 static void rr_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 
-static int rr_open(struct device *dev);
-static int rr_start_xmit(struct sk_buff *skb, struct device *dev);
-static int rr_close(struct device *dev);
-static struct net_device_stats *rr_get_stats(struct device *dev);
-static int rr_ioctl(struct device *dev, struct ifreq *rq, int cmd);
+static int rr_open(struct net_device *dev);
+static int rr_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int rr_close(struct net_device *dev);
+static struct net_device_stats *rr_get_stats(struct net_device *dev);
+static int rr_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static unsigned int rr_read_eeprom(struct rr_private *rrpriv,
 				   unsigned long offset,
 				   unsigned char *buf,
 				   unsigned long length);
 static u32 rr_read_eeprom_word(struct rr_private *rrpriv, void * offset);
-static int rr_load_firmware(struct device *dev);
+static int rr_load_firmware(struct net_device *dev);
 
 #endif /* _RRUNNER_H_ */
diff -u --recursive --new-file v2.3.13/linux/drivers/net/rtl8139.c linux/drivers/net/rtl8139.c
--- v2.3.13/linux/drivers/net/rtl8139.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/rtl8139.c	Wed Aug 18 11:36:42 1999
@@ -165,12 +165,12 @@
 	const char *name;
 	u16	vendor_id, device_id, device_id_mask, flags;
 	int io_size;
-	struct device *(*probe1)(int pci_bus, int pci_devfn, struct device *dev,
+	struct net_device *(*probe1)(int pci_bus, int pci_devfn, struct net_device *dev,
 							 long ioaddr, int irq, int chip_idx, int fnd_cnt);
 };
 
-static struct device * rtl8129_probe1(int pci_bus, int pci_devfn,
-									  struct device *dev, long ioaddr,
+static struct net_device * rtl8129_probe1(int pci_bus, int pci_devfn,
+									  struct net_device *dev, long ioaddr,
 									  int irq, int chp_idx, int fnd_cnt);
 
 static struct pci_id_info pci_tbl[] =
@@ -254,7 +254,7 @@
 struct rtl8129_private {
 	char devname[8];			/* Used only for kernel debugging. */
 	const char *product_name;
-	struct device *next_module;
+	struct net_device *next_module;
 	int chip_id;
 	int chip_revision;
 	unsigned char pci_bus, pci_devfn;
@@ -294,32 +294,32 @@
 #endif
 #endif
 
-static int rtl8129_open(struct device *dev);
+static int rtl8129_open(struct net_device *dev);
 static int read_eeprom(long ioaddr, int location);
-static int mdio_read(struct device *dev, int phy_id, int location);
-static void mdio_write(struct device *dev, int phy_id, int location, int val);
+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 val);
 static void rtl8129_timer(unsigned long data);
-static void rtl8129_tx_timeout(struct device *dev);
-static void rtl8129_init_ring(struct device *dev);
-static int rtl8129_start_xmit(struct sk_buff *skb, struct device *dev);
-static int rtl8129_rx(struct device *dev);
+static void rtl8129_tx_timeout(struct net_device *dev);
+static void rtl8129_init_ring(struct net_device *dev);
+static int rtl8129_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int rtl8129_rx(struct net_device *dev);
 static void rtl8129_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
-static int rtl8129_close(struct device *dev);
-static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd);
-static struct enet_statistics *rtl8129_get_stats(struct device *dev);
+static int rtl8129_close(struct net_device *dev);
+static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static struct enet_statistics *rtl8129_get_stats(struct net_device *dev);
 static inline u32 ether_crc(int length, unsigned char *data);
-static void set_rx_mode(struct device *dev);
+static void set_rx_mode(struct net_device *dev);
 
 
 /* A list of all installed RTL8129 devices, for removing the driver module. */
-static struct device *root_rtl8129_dev = NULL;
+static struct net_device *root_rtl8129_dev = NULL;
 
 /* Ideally we would detect all network cards in slot order.  That would
    be best done a central PCI probe dispatch, which wouldn't work
    well when dynamically adding drivers.  So instead we detect just the
    Rtl81*9 cards in slot order. */
 
-int rtl8139_probe(struct device *dev)
+int rtl8139_probe(struct net_device *dev)
 {
 	int cards_found = 0;
 	int pci_index = 0;
@@ -405,8 +405,8 @@
 	return cards_found ? 0 : -ENODEV;
 }
 
-static struct device *rtl8129_probe1(int pci_bus, int pci_devfn,
-									 struct device *dev, long ioaddr,
+static struct net_device *rtl8129_probe1(int pci_bus, int pci_devfn,
+									 struct net_device *dev, long ioaddr,
 									 int irq, int chip_idx, int found_cnt)
 {
 	static int did_version = 0;			/* Already printed version info. */
@@ -596,7 +596,7 @@
 	}
 	return;
 }
-static int mdio_read(struct device *dev, int phy_id, int location)
+static int mdio_read(struct net_device *dev, int phy_id, int location)
 {
 	long mdio_addr = dev->base_addr + MII_SMI;
 	int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
@@ -629,7 +629,7 @@
 	return (retval>>1) & 0xffff;
 }
 
-static void mdio_write(struct device *dev, int phy_id, int location, int value)
+static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
 {
 	long mdio_addr = dev->base_addr + MII_SMI;
 	int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;
@@ -662,7 +662,7 @@
 
 
 static int
-rtl8129_open(struct device *dev)
+rtl8129_open(struct net_device *dev)
 {
 	struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -760,7 +760,7 @@
 
 static void rtl8129_timer(unsigned long data)
 {
-	struct device *dev = (struct device *)data;
+	struct net_device *dev = (struct net_device *)data;
 	struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
 	long ioaddr = dev->base_addr;
 	int next_tick = 60*HZ;
@@ -856,7 +856,7 @@
 	add_timer(&tp->timer);
 }
 
-static void rtl8129_tx_timeout(struct device *dev)
+static void rtl8129_tx_timeout(struct net_device *dev)
 {
 	struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -939,7 +939,7 @@
 
 /* Initialize the Rx and Tx rings, along with various 'dev' bits. */
 static void
-rtl8129_init_ring(struct device *dev)
+rtl8129_init_ring(struct net_device *dev)
 {
 	struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
 	int i;
@@ -955,7 +955,7 @@
 }
 
 static int
-rtl8129_start_xmit(struct sk_buff *skb, struct device *dev)
+rtl8129_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -1000,7 +1000,7 @@
    after the Tx thread. */
 static void rtl8129_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 {
-	struct device *dev = (struct device *)dev_instance;
+	struct net_device *dev = (struct net_device *)dev_instance;
 	struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
 	int boguscnt = max_interrupt_work;
 	int status, link_changed = 0;
@@ -1173,7 +1173,7 @@
 
 /* The data sheet doesn't describe the Rx ring at all, so I'm guessing at the
    field alignments and semantics. */
-static int rtl8129_rx(struct device *dev)
+static int rtl8129_rx(struct net_device *dev)
 {
 	struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -1283,7 +1283,7 @@
 }
 
 static int
-rtl8129_close(struct device *dev)
+rtl8129_close(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
 	struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
@@ -1328,7 +1328,7 @@
 	return 0;
 }
 
-static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd)
+static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
 	u16 *data = (u16 *)&rq->ifr_data;
@@ -1351,7 +1351,7 @@
 }
 
 static struct enet_statistics *
-rtl8129_get_stats(struct device *dev)
+rtl8129_get_stats(struct net_device *dev)
 {
 	struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -1388,7 +1388,7 @@
 	AcceptMulticast=0x04, AcceptMyPhys=0x02, AcceptAllPhys=0x01,
 };
 
-static void set_rx_mode(struct device *dev)
+static void set_rx_mode(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
 	u32 mc_filter[2];		 /* Multicast hash filter */
@@ -1433,7 +1433,7 @@
 void
 cleanup_module(void)
 {
-	struct device *next_dev;
+	struct net_device *next_dev;
 
 	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
 	while (root_rtl8129_dev) {
diff -u --recursive --new-file v2.3.13/linux/drivers/net/sdla.c linux/drivers/net/sdla.c
--- v2.3.13/linux/drivers/net/sdla.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/sdla.c	Wed Aug 18 11:36:42 1999
@@ -83,7 +83,7 @@
 
 #define SDLA_WINDOW(dev,addr) outb((((addr) >> 13) & 0x1F), (dev)->base_addr + SDLA_REG_Z80_WINDOW)
 
-static void sdla_read(struct device *dev, int addr, void *buf, short len)
+static void sdla_read(struct net_device *dev, int addr, void *buf, short len)
 {
 	unsigned long flags;
 	char          *temp, *base;
@@ -108,7 +108,7 @@
 	}  
 }
 
-static void sdla_write(struct device *dev, int addr, void *buf, short len)
+static void sdla_write(struct net_device *dev, int addr, void *buf, short len)
 {
 	unsigned long flags;
 	char          *temp, *base;
@@ -131,7 +131,7 @@
 	}
 }
 
-static void sdla_clear(struct device *dev)
+static void sdla_clear(struct net_device *dev)
 {
 	unsigned long flags;
 	char          *base;
@@ -155,7 +155,7 @@
 	restore_flags(flags);
 }
 
-static char sdla_byte(struct device *dev, int addr)
+static char sdla_byte(struct net_device *dev, int addr)
 {
 	unsigned long flags;
 	char          byte, *temp;
@@ -171,7 +171,7 @@
 	return(byte);
 }
 
-void sdla_stop(struct device *dev)
+void sdla_stop(struct net_device *dev)
 {
 	struct frad_local *flp;
 
@@ -198,7 +198,7 @@
 	}
 }
 
-void sdla_start(struct device *dev)
+void sdla_start(struct net_device *dev)
 {
 	struct frad_local *flp;
 
@@ -236,7 +236,7 @@
  *
  ***************************************************/
 
-int sdla_z80_poll(struct device *dev, int z80_addr, int jiffs, char resp1, char resp2)
+int sdla_z80_poll(struct net_device *dev, int z80_addr, int jiffs, char resp1, char resp2)
 {
 	unsigned long start, done, now;
 	char          resp, *temp;
@@ -266,7 +266,7 @@
 #define Z80_SCC_OK 		'3'	/* SCC is on board */
 #define Z80_SCC_BAD	 	'4'	/* SCC was not found */
 
-static int sdla_cpuspeed(struct device *dev, struct ifreq *ifr)
+static int sdla_cpuspeed(struct net_device *dev, struct ifreq *ifr)
 {
 	int  jiffs;
 	char data;
@@ -328,7 +328,7 @@
 	struct _dlci_stat dlcis[SDLA_MAX_DLCI];
 };
 
-static void sdla_errors(struct device *dev, int cmd, int dlci, int ret, int len, void *data) 
+static void sdla_errors(struct net_device *dev, int cmd, int dlci, int ret, int len, void *data) 
 {
 	struct _dlci_stat *pstatus;
 	short             *pdlci;
@@ -411,7 +411,7 @@
 	}
 }
 
-static int sdla_cmd(struct device *dev, int cmd, short dlci, short flags, 
+static int sdla_cmd(struct net_device *dev, int cmd, short dlci, short flags, 
                         void *inbuf, short inlen, void *outbuf, short *outlen)
 {
 	static struct _frad_stat status;
@@ -492,9 +492,9 @@
  *
  ***********************************************/
 
-static int sdla_reconfig(struct device *dev);
+static int sdla_reconfig(struct net_device *dev);
 
-int sdla_activate(struct device *slave, struct device *master)
+int sdla_activate(struct net_device *slave, struct net_device *master)
 {
 	struct frad_local *flp;
 	int i;
@@ -516,7 +516,7 @@
 	return(0);
 }
 
-int sdla_deactivate(struct device *slave, struct device *master)
+int sdla_deactivate(struct net_device *slave, struct net_device *master)
 {
 	struct frad_local *flp;
 	int               i;
@@ -538,7 +538,7 @@
 	return(0);
 }
 
-int sdla_assoc(struct device *slave, struct device *master)
+int sdla_assoc(struct net_device *slave, struct net_device *master)
 {
 	struct frad_local *flp;
 	int               i;
@@ -575,7 +575,7 @@
 	return(0);
 }
 
-int sdla_deassoc(struct device *slave, struct device *master)
+int sdla_deassoc(struct net_device *slave, struct net_device *master)
 {
 	struct frad_local *flp;
 	int               i;
@@ -604,7 +604,7 @@
 	return(0);
 }
 
-int sdla_dlci_conf(struct device *slave, struct device *master, int get)
+int sdla_dlci_conf(struct net_device *slave, struct net_device *master, int get)
 {
 	struct frad_local *flp;
 	struct dlci_local *dlp;
@@ -643,7 +643,7 @@
  **************************/
 
 /* NOTE: the DLCI driver deals with freeing the SKB!! */
-static int sdla_transmit(struct sk_buff *skb, struct device *dev)
+static int sdla_transmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct frad_local *flp;
 	int               ret, addr, accept;
@@ -742,9 +742,9 @@
 	return(ret);
 }
 
-static void sdla_receive(struct device *dev)
+static void sdla_receive(struct net_device *dev)
 {
-	struct device	  *master;
+	struct net_device	  *master;
 	struct frad_local *flp;
 	struct dlci_local *dlp;
 	struct sk_buff	 *skb;
@@ -872,7 +872,7 @@
 
 static void sdla_isr(int irq, void *dev_id, struct pt_regs * regs)
 {
-	struct device     *dev;
+	struct net_device     *dev;
 	struct frad_local *flp;
 	char              byte;
 
@@ -930,10 +930,10 @@
 
 static void sdla_poll(unsigned long device)
 {
-	struct device	  *dev;
+	struct net_device	  *dev;
 	struct frad_local *flp;
 
-	dev = (struct device *) device;
+	dev = (struct net_device *) device;
 	flp = dev->priv;
 
 	if (sdla_byte(dev, SDLA_502_RCV_BUF))
@@ -943,7 +943,7 @@
 	add_timer(&flp->timer);
 }
 
-static int sdla_close(struct device *dev)
+static int sdla_close(struct net_device *dev)
 {
 	struct frad_local *flp;
 	struct intr_info  intr;
@@ -1005,7 +1005,7 @@
 	short            dlci[CONFIG_DLCI_MAX];
 };
 
-static int sdla_open(struct device *dev)
+static int sdla_open(struct net_device *dev)
 {
 	struct frad_local *flp;
 	struct dlci_local *dlp;
@@ -1105,7 +1105,7 @@
 	return(0);
 }
 
-static int sdla_config(struct device *dev, struct frad_conf *conf, int get)
+static int sdla_config(struct net_device *dev, struct frad_conf *conf, int get)
 {
 	struct frad_local *flp;
 	struct conf_data  data;
@@ -1203,7 +1203,7 @@
 	return(0);
 }
 
-static int sdla_xfer(struct device *dev, struct sdla_mem *info, int read)
+static int sdla_xfer(struct net_device *dev, struct sdla_mem *info, int read)
 {
 	struct sdla_mem mem;
 	char	*temp;
@@ -1234,7 +1234,7 @@
 	return(0);
 }
 
-static int sdla_reconfig(struct device *dev)
+static int sdla_reconfig(struct net_device *dev)
 {
 	struct frad_local *flp;
 	struct conf_data  data;
@@ -1258,7 +1258,7 @@
 	return(0);
 }
 
-static int sdla_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
+static int sdla_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	struct frad_local *flp;
 
@@ -1325,7 +1325,7 @@
 	return(0);
 }
 
-int sdla_change_mtu(struct device *dev, int new_mtu)
+int sdla_change_mtu(struct net_device *dev, int new_mtu)
 {
 	struct frad_local *flp;
 
@@ -1338,7 +1338,7 @@
 	return(-EOPNOTSUPP);
 }
 
-int sdla_set_config(struct device *dev, struct ifmap *map)
+int sdla_set_config(struct net_device *dev, struct ifmap *map)
 {
 	struct frad_local *flp;
 	int               i;
@@ -1616,7 +1616,7 @@
 	return(0);
 }
  
-static struct net_device_stats *sdla_stats(struct device *dev)
+static struct net_device_stats *sdla_stats(struct net_device *dev)
 {
 	struct frad_local *flp;
 	flp = dev->priv;
@@ -1624,7 +1624,7 @@
 	return(&flp->stats);
 }
 
-int __init sdla_init(struct device *dev)
+int __init sdla_init(struct net_device *dev)
 {
 	struct frad_local *flp;
 
@@ -1673,7 +1673,7 @@
 }
 
 #ifdef MODULE
-static struct device sdla0 = {"sdla0", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, sdla_init};
+static struct net_device sdla0 = {"sdla0", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, sdla_init};
 
 int init_module(void)
 {
diff -u --recursive --new-file v2.3.13/linux/drivers/net/sdla_fr.c linux/drivers/net/sdla_fr.c
--- v2.3.13/linux/drivers/net/sdla_fr.c	Mon Jan  4 11:37:29 1999
+++ linux/drivers/net/sdla_fr.c	Wed Aug 18 11:36:42 1999
@@ -136,7 +136,7 @@
 
 /****** Data Structures *****************************************************/
 
-/* This is an extention of the 'struct device' we create for each network
+/* This is an extention of the 'struct net_device' we create for each network
  * interface to keep the rest of channel-specific data.
  */
 typedef struct fr_channel {
@@ -239,20 +239,20 @@
 
 /* WAN link driver entry points. These are called by the WAN router module. */
 static int update(wan_device_t * wandev);
-static int new_if(wan_device_t * wandev, struct device *dev,
+static int new_if(wan_device_t * wandev, struct net_device *dev,
 		  wanif_conf_t * conf);
-static int del_if(wan_device_t * wandev, struct device *dev);
+static int del_if(wan_device_t * wandev, struct net_device *dev);
 /* WANPIPE-specific entry points */
 static int wpf_exec(struct sdla *card, void *u_cmd, void *u_data);
 /* Network device interface */
-static int if_init(struct device *dev);
-static int if_open(struct device *dev);
-static int if_close(struct device *dev);
-static int if_header(struct sk_buff *skb, struct device *dev,
+static int if_init(struct net_device *dev);
+static int if_open(struct net_device *dev);
+static int if_close(struct net_device *dev);
+static int if_header(struct sk_buff *skb, struct net_device *dev,
 	    unsigned short type, void *daddr, void *saddr, unsigned len);
 static int if_rebuild_hdr(struct sk_buff *skb);
-static int if_send(struct sk_buff *skb, struct device *dev);
-static struct net_device_stats *if_stats(struct device *dev);
+static int if_send(struct sk_buff *skb, struct net_device *dev);
+static struct net_device_stats *if_stats(struct net_device *dev);
 /* Interrupt handlers */
 static void fr502_isr(sdla_t * card);
 static void fr508_isr(sdla_t * card);
@@ -281,9 +281,9 @@
 static int fr_modem_failure(sdla_t * card, fr_mbox_t * mbox);
 static int fr_dlci_change(sdla_t * card, fr_mbox_t * mbox);
 /* Miscellaneous functions */
-static int update_chan_state(struct device *dev);
-static void set_chan_state(struct device *dev, int state);
-static struct device *find_channel(sdla_t * card, unsigned dlci);
+static int update_chan_state(struct net_device *dev);
+static void set_chan_state(struct net_device *dev, int state);
+static struct net_device *find_channel(sdla_t * card, unsigned dlci);
 static int is_tx_ready(sdla_t * card, fr_channel_t * chan);
 static unsigned int dec_to_uint(unsigned char *str, int len);
 static int reply_udp(unsigned char *data, unsigned int mbox_len);
@@ -292,8 +292,8 @@
 static void init_global_statistics(sdla_t * card);
 static void read_DLCI_IB_mapping(sdla_t * card, fr_channel_t * chan);
 /* Udp management functions */
-static int process_udp_mgmt_pkt(char udp_pkt_src, sdla_t * card, struct sk_buff *skb, struct device *dev, int dlci, fr_channel_t * chan);
-static int process_udp_driver_call(char udp_pkt_src, sdla_t * card, struct sk_buff *skb, struct device *dev, int dlci, fr_channel_t * chan);
+static int process_udp_mgmt_pkt(char udp_pkt_src, sdla_t * card, struct sk_buff *skb, struct net_device *dev, int dlci, fr_channel_t * chan);
+static int process_udp_driver_call(char udp_pkt_src, sdla_t * card, struct sk_buff *skb, struct net_device *dev, int dlci, fr_channel_t * chan);
 static int udp_pkt_type(struct sk_buff *skb, sdla_t * card);
 /* IPX functions */
 static void switch_net_numbers(unsigned char *sendpacket, unsigned long network_number, unsigned char incoming);
@@ -499,7 +499,7 @@
  *		< 0	failure (channel will not be created)
  */
 
-static int new_if(wan_device_t * wandev, struct device *dev, wanif_conf_t * conf)
+static int new_if(wan_device_t * wandev, struct net_device *dev, wanif_conf_t * conf)
 {
 	sdla_t *card = wandev->private;
 	fr_channel_t *chan;
@@ -570,7 +570,7 @@
 /*============================================================================
  * Delete logical channel.
  */
-static int del_if(wan_device_t * wandev, struct device *dev)
+static int del_if(wan_device_t * wandev, struct net_device *dev)
 {
 	if (dev->priv) 
 	{
@@ -627,7 +627,7 @@
  * interface registration.  Returning anything but zero will fail interface
  * registration.
  */
-static int if_init(struct device *dev)
+static int if_init(struct net_device *dev)
 {
 	fr_channel_t *chan = dev->priv;
 	sdla_t *card = chan->card;
@@ -668,11 +668,11 @@
  * Return 0 if O.k. or errno.
  */
 
-static int if_open(struct device *dev)
+static int if_open(struct net_device *dev)
 {
 	fr_channel_t *chan = dev->priv;
 	sdla_t *card = chan->card;
-	struct device *dev2;
+	struct net_device *dev2;
 	int err = 0;
 	fr508_flags_t *flags = card->flags;
 	struct timeval tv;
@@ -797,7 +797,7 @@
  * o reset flags.
  */
 
-static int if_close(struct device *dev)
+static int if_close(struct net_device *dev)
 {
 	fr_channel_t *chan = dev->priv;
 	sdla_t *card = chan->card;
@@ -826,7 +826,7 @@
  * Return:	media header length.
  */
 
-static int if_header(struct sk_buff *skb, struct device *dev,
+static int if_header(struct sk_buff *skb, struct net_device *dev,
 	     unsigned short type, void *daddr, void *saddr, unsigned len)
 {
 	int hdr_len = 0;
@@ -852,7 +852,7 @@
 
 static int if_rebuild_hdr(struct sk_buff *skb)
 {
-	struct device *dev=skb->dev;
+	struct net_device *dev=skb->dev;
 	fr_channel_t *chan = dev->priv;
 	sdla_t *card = chan->card;
 	printk(KERN_INFO "%s: rebuild_header() called for interface %s!\n",
@@ -879,13 +879,13 @@
  *    protocol stack and can be used for flow control with protocol layer.
  */
 
-static int if_send(struct sk_buff *skb, struct device *dev)
+static int if_send(struct sk_buff *skb, struct net_device *dev)
 {
 	fr_channel_t *chan = dev->priv;
 	sdla_t *card = chan->card;
 	int retry = 0, err;
 	unsigned char *sendpacket;
-	struct device *dev2;
+	struct net_device *dev2;
 	unsigned long check_braddr, check_mcaddr;
 	fr508_flags_t *adptr_flags = card->flags;
 	int udp_type, send_data;
@@ -1230,7 +1230,7 @@
  * Return a pointer to struct net_device_stats.
  */
 
-static struct net_device_stats *if_stats(struct device *dev)
+static struct net_device_stats *if_stats(struct net_device *dev)
 {
 	fr_channel_t *chan = dev->priv;
 	if(chan==NULL)
@@ -1270,8 +1270,8 @@
 	fr508_flags_t *flags = card->flags;
 	fr_buf_ctl_t *bctl;
 	char *ptr = &flags->iflag;
-	struct device *dev = card->wandev.dev;
-	struct device *dev2;
+	struct net_device *dev = card->wandev.dev;
+	struct net_device *dev2;
 	int i;
 	unsigned long host_cpu_flags;
 	unsigned disable_tx_intr = 1;
@@ -1429,7 +1429,7 @@
 {
 	fr_mbox_t *mbox = card->rxmb;
 	struct sk_buff *skb;
-	struct device *dev;
+	struct net_device *dev;
 	fr_channel_t *chan;
 	unsigned dlci, len;
 	void *buf;
@@ -1517,7 +1517,7 @@
 {
 	fr_buf_ctl_t *frbuf = card->rxmb;
 	struct sk_buff *skb;
-	struct device *dev;
+	struct net_device *dev;
 	fr_channel_t *chan;
 	unsigned dlci, len, offs;
 	void *buf;
@@ -1653,7 +1653,7 @@
  */
 static void tx_intr(sdla_t * card)
 {
-	struct device *dev = card->wandev.dev;
+	struct net_device *dev = card->wandev.dev;
 	if (card->intr_mode == BUFFER_INTR_MODE) 
 	{
 		for (; dev; dev = dev->slave) 
@@ -1801,7 +1801,7 @@
 
 static void wpf_poll(sdla_t * card)
 {
-/*      struct device* dev = card->wandev.dev;  */
+/*      struct net_device* dev = card->wandev.dev;  */
 	fr508_flags_t *flags = card->flags;
 	unsigned long host_cpu_flags;
 	++card->statistics.poll_entry;
@@ -2246,11 +2246,11 @@
 	int cnt = mbox->cmd.length / sizeof(dlci_status_t);
 	fr_dlc_conf_t cfg;
 	fr_channel_t *chan;
-	struct device *dev2;
+	struct net_device *dev2;
 	for (; cnt; --cnt, ++status) 
 	{
 		unsigned short dlci = status->dlci;
-		struct device *dev = find_channel(card, dlci);
+		struct net_device *dev = find_channel(card, dlci);
 		if (dev == NULL) 
 		{
 			printk(KERN_INFO
@@ -2325,7 +2325,7 @@
 /*============================================================================
  * Update channel state. 
  */
-static int update_chan_state(struct device *dev)
+static int update_chan_state(struct net_device *dev)
 {
 	fr_channel_t *chan = dev->priv;
 	sdla_t *card = chan->card;
@@ -2365,7 +2365,7 @@
 /*============================================================================
  * Set channel state.
  */
-static void set_chan_state(struct device *dev, int state)
+static void set_chan_state(struct net_device *dev, int state)
 {
 	fr_channel_t *chan = dev->priv;
 	sdla_t *card = chan->card;
@@ -2402,9 +2402,9 @@
 /*============================================================================
  * Find network device by its channel number.
  */
-static struct device *find_channel(sdla_t * card, unsigned dlci)
+static struct net_device *find_channel(sdla_t * card, unsigned dlci)
 {
-	struct device *dev;
+	struct net_device *dev;
 	for (dev = card->wandev.dev; dev; dev = dev->slave)
 		if (((fr_channel_t *) dev->priv)->dlci == dlci)
 			break;
@@ -2454,7 +2454,7 @@
  * Process UDP call of type FPIPE8ND
  */
 
-static int process_udp_mgmt_pkt(char udp_pkt_src, sdla_t * card, struct sk_buff *skb, struct device *dev, int dlci, fr_channel_t * chan)
+static int process_udp_mgmt_pkt(char udp_pkt_src, sdla_t * card, struct sk_buff *skb, struct net_device *dev, int dlci, fr_channel_t * chan)
 {
 	int c_retry = MAX_CMD_RETRY;
 	unsigned char *data;
@@ -2818,7 +2818,7 @@
 /*============================================================================
  * Process UDP call of type DRVSTATS.  
  */
-static int process_udp_driver_call(char udp_pkt_src, sdla_t * card, struct sk_buff *skb, struct device *dev, int dlci, fr_channel_t * chan)
+static int process_udp_driver_call(char udp_pkt_src, sdla_t * card, struct sk_buff *skb, struct net_device *dev, int dlci, fr_channel_t * chan)
 {
 	int c_retry = MAX_CMD_RETRY;
 	unsigned char *sendpacket;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/sdla_ppp.c linux/drivers/net/sdla_ppp.c
--- v2.3.13/linux/drivers/net/sdla_ppp.c	Mon Jan  4 11:37:29 1999
+++ linux/drivers/net/sdla_ppp.c	Wed Aug 18 11:36:42 1999
@@ -147,20 +147,20 @@
 
 /* WAN link driver entry points. These are called by the WAN router module. */
 static int update(wan_device_t * wandev);
-static int new_if(wan_device_t * wandev, struct device *dev,
+static int new_if(wan_device_t * wandev, struct net_device *dev,
 		  wanif_conf_t * conf);
-static int del_if(wan_device_t * wandev, struct device *dev);
+static int del_if(wan_device_t * wandev, struct net_device *dev);
 /* WANPIPE-specific entry points */
 static int wpp_exec(struct sdla *card, void *u_cmd, void *u_data);
 /* Network device interface */
-static int if_init(struct device *dev);
-static int if_open(struct device *dev);
-static int if_close(struct device *dev);
-static int if_header(struct sk_buff *skb, struct device *dev,
+static int if_init(struct net_device *dev);
+static int if_open(struct net_device *dev);
+static int if_close(struct net_device *dev);
+static int if_header(struct sk_buff *skb, struct net_device *dev,
 	    unsigned short type, void *daddr, void *saddr, unsigned len);
 static int if_rebuild_hdr(struct sk_buff *skb);
-static int if_send(struct sk_buff *skb, struct device *dev);
-static struct enet_statistics *if_stats(struct device *dev);
+static int if_send(struct sk_buff *skb, struct net_device *dev);
+static struct enet_statistics *if_stats(struct net_device *dev);
 /* PPP firmware interface functions */
 static int ppp_read_version(sdla_t * card, char *str);
 static int ppp_configure(sdla_t * card, void *data);
@@ -185,8 +185,8 @@
 static void show_disc_cause(sdla_t * card, unsigned cause);
 static unsigned char bps_to_speed_code(unsigned long bps);
 static int reply_udp(unsigned char *data, unsigned int mbox_len);
-static int process_udp_mgmt_pkt(char udp_pkt_src, sdla_t * card, struct sk_buff *skb, struct device *dev, ppp_private_area_t * ppp_priv_area);
-static int process_udp_driver_call(char udp_pkt_src, sdla_t * card, struct sk_buff *skb, struct device *dev, ppp_private_area_t * ppp_priv_area);
+static int process_udp_mgmt_pkt(char udp_pkt_src, sdla_t * card, struct sk_buff *skb, struct net_device *dev, ppp_private_area_t * ppp_priv_area);
+static int process_udp_driver_call(char udp_pkt_src, sdla_t * card, struct sk_buff *skb, struct net_device *dev, ppp_private_area_t * ppp_priv_area);
 static void init_ppp_tx_rx_buff(sdla_t * card);
 static int intr_test(sdla_t * card);
 static int udp_pkt_type(struct sk_buff *skb, sdla_t * card);
@@ -310,7 +310,7 @@
  *		< 0	failure (channel will not be created)
  */
 
-static int new_if(wan_device_t * wandev, struct device *dev, wanif_conf_t * conf)
+static int new_if(wan_device_t * wandev, struct net_device *dev, wanif_conf_t * conf)
 {
 	sdla_t *card = wandev->private;
 	ppp_private_area_t *ppp_priv_area;
@@ -343,7 +343,7 @@
  * Delete logical channel.
  */
 
-static int del_if(wan_device_t * wandev, struct device *dev)
+static int del_if(wan_device_t * wandev, struct net_device *dev)
 {
 	if (dev->priv) {
 		kfree(dev->priv);
@@ -391,7 +391,7 @@
  * registration.
  */
 
-static int if_init(struct device *dev)
+static int if_init(struct net_device *dev)
 {
 	ppp_private_area_t *ppp_priv_area = dev->priv;
 	sdla_t *card = ppp_priv_area->card;
@@ -429,7 +429,7 @@
  * Return 0 if O.k. or errno.
  */
 
-static int if_open(struct device *dev)
+static int if_open(struct net_device *dev)
 {
 	ppp_private_area_t *ppp_priv_area = dev->priv;
 	sdla_t *card = ppp_priv_area->card;
@@ -487,7 +487,7 @@
  * o reset flags.
  */
 
-static int if_close(struct device *dev)
+static int if_close(struct net_device *dev)
 {
 	ppp_private_area_t *ppp_priv_area = dev->priv;
 	sdla_t *card = ppp_priv_area->card;
@@ -512,7 +512,7 @@
  * Return:	media header length.
  */
 
-static int if_header(struct sk_buff *skb, struct device *dev,
+static int if_header(struct sk_buff *skb, struct net_device *dev,
 	     unsigned short type, void *daddr, void *saddr, unsigned len)
 {
 	switch (type) 
@@ -536,7 +536,7 @@
 
 static int if_rebuild_hdr(struct sk_buff *skb)
 {
-	struct device *dev=skb->dev;
+	struct net_device *dev=skb->dev;
 	ppp_private_area_t *ppp_priv_area = dev->priv;
 	sdla_t *card = ppp_priv_area->card;
 	printk(KERN_INFO "%s: rebuild_header() called for interface %s!\n",
@@ -562,7 +562,7 @@
  *    protocol stack and can be used for flow control with protocol layer.
  */
 
-static int if_send(struct sk_buff *skb, struct device *dev)
+static int if_send(struct sk_buff *skb, struct net_device *dev)
 {
 	ppp_private_area_t *ppp_priv_area = dev->priv;
 	sdla_t *card = ppp_priv_area->card;
@@ -846,7 +846,7 @@
  * Return a pointer to struct enet_statistics.
  */
 
-static struct enet_statistics *if_stats(struct device *dev)
+static struct enet_statistics *if_stats(struct net_device *dev)
 {
 	ppp_private_area_t *ppp_priv_area = dev->priv;
 	sdla_t *card;
@@ -1052,7 +1052,7 @@
 	ppp_flags_t *flags = card->flags;
 	char *ptr = &flags->iflag;
 	unsigned long host_cpu_flags;
-	struct device *dev = card->wandev.dev;
+	struct net_device *dev = card->wandev.dev;
 	int i;
 	card->in_isr = 1;
 	++card->statistics.isr_entry;
@@ -1123,7 +1123,7 @@
 static void rx_intr(sdla_t * card)
 {
 	ppp_buf_ctl_t *rxbuf = card->rxmb;
-	struct device *dev = card->wandev.dev;
+	struct net_device *dev = card->wandev.dev;
 	ppp_private_area_t *ppp_priv_area;
 	struct sk_buff *skb;
 	unsigned len;
@@ -1227,7 +1227,7 @@
 
 static void tx_intr(sdla_t * card)
 {
-	struct device *dev = card->wandev.dev;
+	struct net_device *dev = card->wandev.dev;
 	if (!dev || !dev->start) {
 		++card->statistics.tx_intr_dev_not_started;
 		return;
@@ -1332,7 +1332,7 @@
 
 static void wpp_poll(sdla_t * card)
 {
-	struct device *dev = card->wandev.dev;
+	struct net_device *dev = card->wandev.dev;
 	ppp_flags_t *adptr_flags = card->flags;
 	unsigned long host_cpu_flags;
 	++card->statistics.poll_entry;
@@ -1430,7 +1430,7 @@
 
 static void poll_disconnected(sdla_t * card)
 {
-	struct device *dev = card->wandev.dev;
+	struct net_device *dev = card->wandev.dev;
 	if (dev && dev->start &&
 	    ((jiffies - card->state_tick) > HOLD_DOWN_TIME)) {
 		wanpipe_set_state(card, WAN_CONNECTING);
@@ -1591,7 +1591,7 @@
  * Process UDP call of type DRVSTATS.  
  */
 
-static int process_udp_driver_call(char udp_pkt_src, sdla_t * card, struct sk_buff *skb, struct device *dev, ppp_private_area_t * ppp_priv_area)
+static int process_udp_driver_call(char udp_pkt_src, sdla_t * card, struct sk_buff *skb, struct net_device *dev, ppp_private_area_t * ppp_priv_area)
 {
 	unsigned char *sendpacket;
 	unsigned char buf2[5];
@@ -1776,7 +1776,7 @@
  */
 
 static int process_udp_mgmt_pkt(char udp_pkt_src, sdla_t * card,
-				struct sk_buff *skb, struct device *dev,
+				struct sk_buff *skb, struct net_device *dev,
 				ppp_private_area_t * ppp_priv_area)
 {
 	unsigned char *sendpacket;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/sdla_x25.c linux/drivers/net/sdla_x25.c
--- v2.3.13/linux/drivers/net/sdla_x25.c	Mon Jan  4 11:37:29 1999
+++ linux/drivers/net/sdla_x25.c	Wed Aug 18 11:36:42 1999
@@ -70,7 +70,7 @@
 
 /****** Data Structures *****************************************************/
 
-/* This is an extention of the 'struct device' we create for each network
+/* This is an extention of the 'struct net_device' we create for each network
  * interface to keep the rest of X.25 channel-specific data.
  */
 typedef struct x25_channel
@@ -114,22 +114,22 @@
 
 /* WAN link driver entry points. These are called by the WAN router module. */
 static int update (wan_device_t* wandev);
-static int new_if (wan_device_t* wandev, struct device* dev,
+static int new_if (wan_device_t* wandev, struct net_device* dev,
 	wanif_conf_t* conf);
-static int del_if (wan_device_t* wandev, struct device* dev);
+static int del_if (wan_device_t* wandev, struct net_device* dev);
 
 /* WANPIPE-specific entry points */
 static int wpx_exec (struct sdla* card, void* u_cmd, void* u_data);
 
 /* Network device interface */
-static int if_init   (struct device* dev);
-static int if_open   (struct device* dev);
-static int if_close  (struct device* dev);
-static int if_header (struct sk_buff* skb, struct device* dev,
+static int if_init   (struct net_device* dev);
+static int if_open   (struct net_device* dev);
+static int if_close  (struct net_device* dev);
+static int if_header (struct sk_buff* skb, struct net_device* dev,
 	unsigned short type, void* daddr, void* saddr, unsigned len);
 static int if_rebuild_hdr (struct sk_buff* skb);
-static int if_send (struct sk_buff* skb, struct device* dev);
-static struct net_device_stats * if_stats (struct device* dev);
+static int if_send (struct sk_buff* skb, struct net_device* dev);
+static struct net_device_stats * if_stats (struct net_device* dev);
 
 /* Interrupt handlers */
 static void wpx_isr	(sdla_t* card);
@@ -173,11 +173,11 @@
 /* Miscellaneous functions */
 static int connect (sdla_t* card);
 static int disconnect (sdla_t* card);
-static struct device* get_dev_by_lcn(wan_device_t* wandev, unsigned lcn);
-static int chan_connect (struct device* dev);
-static int chan_disc (struct device* dev);
-static void set_chan_state (struct device* dev, int state);
-static int chan_send (struct device* dev, struct sk_buff* skb);
+static struct net_device* get_dev_by_lcn(wan_device_t* wandev, unsigned lcn);
+static int chan_connect (struct net_device* dev);
+static int chan_disc (struct net_device* dev);
+static void set_chan_state (struct net_device* dev, int state);
+static int chan_send (struct net_device* dev, struct sk_buff* skb);
 static unsigned char bps_to_speed_code (unsigned long bps);
 static unsigned int dec_to_uint (unsigned char* str, int len);
 static unsigned int hex_to_uint (unsigned char* str, int len);
@@ -394,7 +394,7 @@
  * Return:	0	o.k.
  *		< 0	failure (channel will not be created)
  */
-static int new_if (wan_device_t* wandev, struct device* dev, wanif_conf_t* conf)
+static int new_if (wan_device_t* wandev, struct net_device* dev, wanif_conf_t* conf)
 {
 	sdla_t* card = wandev->private;
 	x25_channel_t* chan;
@@ -470,7 +470,7 @@
 /*============================================================================
  * Delete logical channel.
  */
-static int del_if (wan_device_t* wandev, struct device* dev)
+static int del_if (wan_device_t* wandev, struct net_device* dev)
 {
 	if (dev->priv)
 	{
@@ -531,7 +531,7 @@
  * interface registration.  Returning anything but zero will fail interface
  * registration.
  */
-static int if_init (struct device* dev)
+static int if_init (struct net_device* dev)
 {
 	x25_channel_t* chan = dev->priv;
 	sdla_t* card = chan->card;
@@ -577,7 +577,7 @@
  *
  * Return 0 if O.k. or errno.
  */
-static int if_open (struct device* dev)
+static int if_open (struct net_device* dev)
 {
 	x25_channel_t* chan = dev->priv;
 	sdla_t* card = chan->card;
@@ -605,7 +605,7 @@
  * o reset flags.
  * o if there's no more open channels then disconnect physical link.
  */
-static int if_close (struct device* dev)
+static int if_close (struct net_device* dev)
 {
 	x25_channel_t* chan = dev->priv;
 	sdla_t* card = chan->card;
@@ -637,7 +637,7 @@
  *
  * Return:	media header length.
  */
-static int if_header (struct sk_buff* skb, struct device* dev,
+static int if_header (struct sk_buff* skb, struct net_device* dev,
 	unsigned short type, void* daddr, void* saddr, unsigned len)
 {
 	x25_channel_t* chan = dev->priv;
@@ -665,7 +665,7 @@
  
 static int if_rebuild_hdr (struct sk_buff* skb)
 {
-	struct device *dev=skb->dev;
+	struct net_device *dev=skb->dev;
 	x25_channel_t* chan = dev->priv;
 	sdla_t* card = chan->card;
 
@@ -692,11 +692,11 @@
  *    protocol stack and can be used for flow control with protocol layer.
  */
 
-static int if_send (struct sk_buff* skb, struct device* dev)
+static int if_send (struct sk_buff* skb, struct net_device* dev)
 {
 	x25_channel_t* chan = dev->priv;
 	sdla_t* card = chan->card;
-	struct device *dev2;
+	struct net_device *dev2;
 	TX25Status* status = card->flags;
 	unsigned long host_cpu_flags;
 
@@ -823,7 +823,7 @@
  * Return a pointer to struct net_device_stats
  */
  
-static struct net_device_stats* if_stats (struct device* dev)
+static struct net_device_stats* if_stats (struct net_device* dev)
 {
 	x25_channel_t* chan = dev->priv;
 	if(chan==NULL)
@@ -840,7 +840,7 @@
 static void wpx_isr (sdla_t* card)
 {
 	TX25Status* status = card->flags;
-	struct device *dev;
+	struct net_device *dev;
 	unsigned long host_cpu_flags;
 
 	card->in_isr = 1;
@@ -933,7 +933,7 @@
 	unsigned len = rxmb->cmd.length;	/* packet length */
 	unsigned qdm = rxmb->cmd.qdm;		/* Q,D and M bits */
 	wan_device_t* wandev = &card->wandev;
-	struct device* dev = get_dev_by_lcn(wandev, lcn);
+	struct net_device* dev = get_dev_by_lcn(wandev, lcn);
 	x25_channel_t* chan;
 	struct sk_buff* skb;
 	void* bufptr;
@@ -1041,7 +1041,7 @@
 
 static void tx_intr (sdla_t* card)
 {
-	struct device *dev;
+	struct net_device *dev;
 
 	/* unbusy all devices and then dev_tint(); */
 	for(dev = card->wandev.dev; dev; dev = dev->slave)
@@ -1165,7 +1165,7 @@
  */
 static void poll_active (sdla_t* card)
 {
-	struct device* dev;
+	struct net_device* dev;
 
 	/* Fetch X.25 asynchronous events */
 	x25_fetch_events(card);
@@ -1745,7 +1745,7 @@
 {
 	wan_device_t* wandev = &card->wandev;
 	int new_lcn = mb->cmd.lcn;
-	struct device* dev = get_dev_by_lcn(wandev, new_lcn);
+	struct net_device* dev = get_dev_by_lcn(wandev, new_lcn);
 	x25_channel_t* chan = NULL;
 	int accept = 0;		/* set to '1' if o.k. to accept call */
 	x25_call_info_t* info;
@@ -1855,7 +1855,7 @@
 static int call_accepted (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
 {
 	unsigned new_lcn = mb->cmd.lcn;
-	struct device* dev = get_dev_by_lcn(&card->wandev, new_lcn);
+	struct net_device* dev = get_dev_by_lcn(&card->wandev, new_lcn);
 	x25_channel_t* chan;
 
 	printk(KERN_INFO "%s: X.25 call accepted on LCN %d!\n",
@@ -1887,7 +1887,7 @@
 static int call_cleared (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
 {
 	unsigned new_lcn = mb->cmd.lcn;
-	struct device* dev = get_dev_by_lcn(&card->wandev, new_lcn);
+	struct net_device* dev = get_dev_by_lcn(&card->wandev, new_lcn);
 
 	printk(KERN_INFO "%s: X.25 clear request on LCN %d! Cause:0x%02X "
 		"Diagn:0x%02X\n",
@@ -1905,7 +1905,7 @@
 static int restart_event (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
 {
 	wan_device_t* wandev = &card->wandev;
-	struct device* dev;
+	struct net_device* dev;
 
 	printk(KERN_INFO
 		"%s: X.25 restart request! Cause:0x%02X Diagn:0x%02X\n",
@@ -1926,7 +1926,7 @@
 
 	if (mb->cmd.pktType == 0x05)	/* call request time out */
 	{
-		struct device* dev = get_dev_by_lcn(&card->wandev, new_lcn);
+		struct net_device* dev = get_dev_by_lcn(&card->wandev, new_lcn);
 
 		printk(KERN_INFO "%s: X.25 call timed timeout on LCN %d!\n",
 			card->devname, new_lcn);
@@ -1976,9 +1976,9 @@
 /*============================================================================
  * Find network device by its channel number.
  */
-static struct device* get_dev_by_lcn (wan_device_t* wandev, unsigned lcn)
+static struct net_device* get_dev_by_lcn (wan_device_t* wandev, unsigned lcn)
 {
-	struct device* dev;
+	struct net_device* dev;
 
 	for (dev = wandev->dev; dev; dev = dev->slave)
 		if (((x25_channel_t*)dev->priv)->lcn == lcn)
@@ -1995,7 +1995,7 @@
  *		>0	connection in progress
  *		<0	failure
  */
-static int chan_connect (struct device* dev)
+static int chan_connect (struct net_device* dev)
 {
 	x25_channel_t* chan = dev->priv;
 	sdla_t* card = chan->card;
@@ -2024,7 +2024,7 @@
  * Disconnect logical channel.
  * o if SVC then clear X.25 call
  */
-static int chan_disc (struct device* dev)
+static int chan_disc (struct net_device* dev)
 {
 	x25_channel_t* chan = dev->priv;
 
@@ -2037,7 +2037,7 @@
 /*============================================================================
  * Set logical channel state.
  */
-static void set_chan_state (struct device* dev, int state)
+static void set_chan_state (struct net_device* dev, int state)
 {
 	x25_channel_t* chan = dev->priv;
 	sdla_t* card = chan->card;
@@ -2092,7 +2092,7 @@
  * 2. When transmission is complete, an event notification should be issued
  *    to the router.
  */
-static int chan_send (struct device* dev, struct sk_buff* skb)
+static int chan_send (struct net_device* dev, struct sk_buff* skb)
 {
 	x25_channel_t* chan = dev->priv;
 	sdla_t* card = chan->card;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/sealevel.c linux/drivers/net/sealevel.c
--- v2.3.13/linux/drivers/net/sealevel.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/sealevel.c	Wed Aug 18 11:36:42 1999
@@ -73,7 +73,7 @@
  *	We've been placed in the UP state
  */ 
  
-static int sealevel_open(struct device *d)
+static int sealevel_open(struct net_device *d)
 {
 	struct slvl_device *slvl=d->priv;
 	int err = -1;
@@ -123,7 +123,7 @@
 	return 0;
 }
 
-static int sealevel_close(struct device *d)
+static int sealevel_close(struct net_device *d)
 {
 	struct slvl_device *slvl=d->priv;
 	int unit = slvl->channel;
@@ -156,14 +156,14 @@
 	return 0;
 }
 
-static int sealevel_ioctl(struct device *d, struct ifreq *ifr, int cmd)
+static int sealevel_ioctl(struct net_device *d, struct ifreq *ifr, int cmd)
 {
 	/* struct slvl_device *slvl=d->priv;
 	   z8530_ioctl(d,&slvl->sync.chanA,ifr,cmd) */
 	return sppp_do_ioctl(d, ifr,cmd);
 }
 
-static struct enet_statistics *sealevel_get_stats(struct device *d)
+static struct enet_statistics *sealevel_get_stats(struct net_device *d)
 {
 	struct slvl_device *slvl=d->priv;
 	if(slvl)
@@ -176,7 +176,7 @@
  *	Passed PPP frames, fire them downwind.
  */
  
-static int sealevel_queue_xmit(struct sk_buff *skb, struct device *d)
+static int sealevel_queue_xmit(struct sk_buff *skb, struct net_device *d)
 {
 	struct slvl_device *slvl=d->priv;
 	return z8530_queue_xmit(slvl->chan, skb);
@@ -192,7 +192,7 @@
 	return 0;
 }
 
-static int sealevel_neigh_setup_dev(struct device *dev, struct neigh_parms *p)
+static int sealevel_neigh_setup_dev(struct net_device *dev, struct neigh_parms *p)
 {
 	if (p->tbl->family == AF_INET) {
 		p->neigh_setup = sealevel_neigh_setup;
@@ -204,7 +204,7 @@
 
 #else
 
-static int return_0(struct device *d)
+static int return_0(struct net_device *d)
 {
 	return 0;
 }
@@ -342,7 +342,7 @@
 			sprintf(sv->name,"hdlc%d", i);
 			if(dev_get(sv->name)==NULL)
 			{
-				struct device *d=sv->chan->netdevice;
+				struct net_device *d=sv->chan->netdevice;
 	
 				/* 
 				 *	Initialise the PPP components
diff -u --recursive --new-file v2.3.13/linux/drivers/net/seeq8005.c linux/drivers/net/seeq8005.c
--- v2.3.13/linux/drivers/net/seeq8005.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/seeq8005.c	Wed Aug 18 11:36:42 1999
@@ -78,22 +78,22 @@
 
 /* Index to functions, as function prototypes. */
 
-extern int seeq8005_probe(struct device *dev);
+extern int seeq8005_probe(struct net_device *dev);
 
-static int seeq8005_probe1(struct device *dev, int ioaddr);
-static int seeq8005_open(struct device *dev);
-static int seeq8005_send_packet(struct sk_buff *skb, struct device *dev);
+static int seeq8005_probe1(struct net_device *dev, int ioaddr);
+static int seeq8005_open(struct net_device *dev);
+static int seeq8005_send_packet(struct sk_buff *skb, struct net_device *dev);
 static void seeq8005_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void seeq8005_rx(struct device *dev);
-static int seeq8005_close(struct device *dev);
-static struct net_device_stats *seeq8005_get_stats(struct device *dev);
-static void set_multicast_list(struct device *dev);
+static void seeq8005_rx(struct net_device *dev);
+static int seeq8005_close(struct net_device *dev);
+static struct net_device_stats *seeq8005_get_stats(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
 
 /* Example routines you must write ;->. */
 #define tx_done(dev)	(inw(SEEQ_STATUS) & SEEQSTAT_TX_ON)
-static void hardware_send_packet(struct device *dev, char *buf, int length);
-extern void seeq8005_init(struct device *dev, int startp);
-static inline void wait_for_buffer(struct device *dev);
+static void hardware_send_packet(struct net_device *dev, char *buf, int length);
+extern void seeq8005_init(struct net_device *dev, int startp);
+static inline void wait_for_buffer(struct net_device *dev);
 
 
 /* Check for a network adaptor of this type, and return '0' iff one exists.
@@ -109,7 +109,7 @@
 {"seeq8005", seeq8005_probe1, SEEQ8005_IO_EXTENT, seeq8005_portlist};
 #else
 int __init 
-seeq8005_probe(struct device *dev)
+seeq8005_probe(struct net_device *dev)
 {
 	int i;
 	int base_addr = dev ? dev->base_addr : 0;
@@ -135,7 +135,7 @@
    probes on the ISA bus.  A good device probes avoids doing writes, and
    verifies that the correct device exists and functions.  */
 
-static int __init seeq8005_probe1(struct device *dev, int ioaddr)
+static int __init seeq8005_probe1(struct net_device *dev, int ioaddr)
 {
 	static unsigned version_printed = 0;
 	int i,j;
@@ -344,7 +344,7 @@
    there is non-reboot way to recover if something goes wrong.
    */
 static int
-seeq8005_open(struct device *dev)
+seeq8005_open(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 
@@ -369,7 +369,7 @@
 }
 
 static int
-seeq8005_send_packet(struct sk_buff *skb, struct device *dev)
+seeq8005_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
 	int ioaddr = dev->base_addr;
 	struct net_local *lp = (struct net_local *)dev->priv;
@@ -412,7 +412,7 @@
 static void
 seeq8005_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
-	struct device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	struct net_local *lp;
 	int ioaddr, status, boguscount = 0;
 
@@ -462,7 +462,7 @@
 
 /* We have a good packet(s), get it/them out of the buffers. */
 static void
-seeq8005_rx(struct device *dev)
+seeq8005_rx(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int boguscount = 10;
@@ -561,7 +561,7 @@
 
 /* The inverse routine to net_open(). */
 static int
-seeq8005_close(struct device *dev)
+seeq8005_close(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -584,7 +584,7 @@
 
 /* Get the current statistics.	This may be called with the card open or
    closed. */
-static struct net_device_stats *seeq8005_get_stats(struct device *dev)
+static struct net_device_stats *seeq8005_get_stats(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 
@@ -598,7 +598,7 @@
 			best-effort filtering.
  */
 static void
-set_multicast_list(struct device *dev)
+set_multicast_list(struct net_device *dev)
 {
 /*
  * I _could_ do up to 6 addresses here, but won't (yet?)
@@ -620,7 +620,7 @@
 #endif
 }
 
-void seeq8005_init(struct device *dev, int startp)
+void seeq8005_init(struct net_device *dev, int startp)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -677,7 +677,7 @@
 }	
 
 
-static void hardware_send_packet(struct device * dev, char *buf, int length)
+static void hardware_send_packet(struct net_device * dev, char *buf, int length)
 {
 	int ioaddr = dev->base_addr;
 	int status = inw(SEEQ_STATUS);
@@ -722,7 +722,7 @@
  * This routine waits for the SEEQ chip to assert that the FIFO is ready
  * by checking for a window interrupt, and then clearing it
  */
-inline void wait_for_buffer(struct device * dev)
+inline void wait_for_buffer(struct net_device * dev)
 {
 	int ioaddr = dev->base_addr;
 	int tmp;
@@ -740,7 +740,7 @@
 
 static char devicename[9] = { 0, };
 
-static struct device dev_seeq =
+static struct net_device dev_seeq =
 {
 	devicename, /* device name is inserted by linux/drivers/net/net_init.c */
 	0, 0, 0, 0,
diff -u --recursive --new-file v2.3.13/linux/drivers/net/sgiseeq.c linux/drivers/net/sgiseeq.c
--- v2.3.13/linux/drivers/net/sgiseeq.c	Wed Jun 30 13:38:20 1999
+++ linux/drivers/net/sgiseeq.c	Wed Aug 18 11:36:42 1999
@@ -134,7 +134,7 @@
 	hregs->rx_ctrl = HPC3_ERXCTRL_ACTIVE;
 }
 
-static inline void seeq_load_eaddr(struct device *dev,
+static inline void seeq_load_eaddr(struct net_device *dev,
 				   volatile struct sgiseeq_regs *sregs)
 {
 	int i;
@@ -148,7 +148,7 @@
 #define RCNTCFG_INIT  (HPCDMA_OWN | HPCDMA_EORP | HPCDMA_XIE)
 #define RCNTINFO_INIT (RCNTCFG_INIT | (PKT_BUF_SZ & HPCDMA_BCNT))
 
-static void seeq_init_ring(struct device *dev)
+static void seeq_init_ring(struct net_device *dev)
 {
 	struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv;
 	volatile struct sgiseeq_init_block *ib = &sp->srings;
@@ -196,7 +196,7 @@
 
 #ifdef DEBUG
 static struct sgiseeq_private *gpriv;
-static struct device *gdev;
+static struct net_device *gdev;
 
 void sgiseeq_dump_rings(void)
 {
@@ -241,7 +241,7 @@
 #define TSTAT_INIT_EDLC ((TSTAT_INIT_SEEQ) | SEEQ_TCMD_RB2)
 #define RDMACFG_INIT    (HPC3_ERXDCFG_FRXDC | HPC3_ERXDCFG_FEOP | HPC3_ERXDCFG_FIRQ)
 
-static void init_seeq(struct device *dev, struct sgiseeq_private *sp,
+static void init_seeq(struct net_device *dev, struct sgiseeq_private *sp,
 		      volatile struct sgiseeq_regs *sregs)
 {
 	volatile struct hpc3_ethregs *hregs = sp->hregs;
@@ -294,7 +294,7 @@
 				!((rd)->rdma.cntinfo & HPCDMA_OWN); \
 				(rd) = &(sp)->srings.rx_desc[(sp)->rx_new])
 
-static inline void sgiseeq_rx(struct device *dev, struct sgiseeq_private *sp,
+static inline void sgiseeq_rx(struct net_device *dev, struct sgiseeq_private *sp,
 			      volatile struct hpc3_ethregs *hregs,
 			      volatile struct sgiseeq_regs *sregs)
 {
@@ -371,7 +371,7 @@
 	}
 }
 
-static inline void sgiseeq_tx(struct device *dev, struct sgiseeq_private *sp,
+static inline void sgiseeq_tx(struct net_device *dev, struct sgiseeq_private *sp,
 			      volatile struct hpc3_ethregs *hregs,
 			      volatile struct sgiseeq_regs *sregs)
 {
@@ -412,7 +412,7 @@
 }
 
 static inline void tx_maybe_unbusy(struct sgiseeq_private *sp,
-				   struct device *dev)
+				   struct net_device *dev)
 {
 	if((TX_BUFFS_AVAIL(sp) >= 0) && dev->tbusy) {
 		dev->tbusy = 0;
@@ -422,7 +422,7 @@
 
 static void sgiseeq_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev = (struct device *) dev_id;
+	struct net_device *dev = (struct net_device *) dev_id;
 	struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv;
 	volatile struct hpc3_ethregs *hregs = sp->hregs;
 	volatile struct sgiseeq_regs *sregs = sp->sregs;
@@ -442,7 +442,7 @@
 	dev->interrupt = 0;
 }
 
-static int sgiseeq_open(struct device *dev)
+static int sgiseeq_open(struct net_device *dev)
 {
 	struct sgiseeq_private *sp = (struct sgiseeq_private *)dev->priv;
 	volatile struct sgiseeq_regs *sregs = sp->sregs;
@@ -464,7 +464,7 @@
 	return 0;
 }
 
-static int sgiseeq_close(struct device *dev)
+static int sgiseeq_close(struct net_device *dev)
 {
 	struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv;
 	volatile struct sgiseeq_regs *sregs = sp->sregs;
@@ -480,7 +480,7 @@
 	return 0;
 }
 
-static inline int sgiseeq_reset(struct device *dev)
+static inline int sgiseeq_reset(struct net_device *dev)
 {
 	struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv;
 	volatile struct sgiseeq_regs *sregs = sp->sregs;
@@ -502,7 +502,7 @@
 }
 
 static inline int verify_tx(struct sgiseeq_private *sp,
-			    struct device *dev,
+			    struct net_device *dev,
 			    struct sk_buff *skb)
 {
 	/* Are we bolixed? */
@@ -529,7 +529,7 @@
 	return 0;
 }
 
-static int sgiseeq_start_xmit(struct sk_buff *skb, struct device *dev)
+static int sgiseeq_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv;
 	volatile struct hpc3_ethregs *hregs = sp->hregs;
@@ -585,14 +585,14 @@
 	return 0;
 }
 
-static struct enet_statistics *sgiseeq_get_stats(struct device *dev)
+static struct enet_statistics *sgiseeq_get_stats(struct net_device *dev)
 {
 	struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv;
 
 	return &sp->stats;
 }
 
-static void sgiseeq_set_multicast(struct device *dev)
+static void sgiseeq_set_multicast(struct net_device *dev)
 {
 }
 
@@ -625,7 +625,7 @@
 
 #define ALIGNED(x)  ((((unsigned long)(x)) + 0xf) & ~(0xf))
 
-int sgiseeq_init(struct device *dev, struct sgiseeq_regs *sregs,
+int sgiseeq_init(struct net_device *dev, struct sgiseeq_regs *sregs,
 		 struct hpc3_ethregs *hregs, int irq)
 {
 	static unsigned version_printed = 0;
@@ -721,7 +721,7 @@
 	}
 }
 
-int sgiseeq_probe(struct device *dev)
+int sgiseeq_probe(struct net_device *dev)
 {
 	static int initialized;
 	char *ep;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/shaper.c linux/drivers/net/shaper.c
--- v2.3.13/linux/drivers/net/shaper.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/shaper.c	Wed Aug 18 11:36:42 1999
@@ -378,7 +378,7 @@
  *	bind.
  */
 
-static int shaper_open(struct device *dev)
+static int shaper_open(struct net_device *dev)
 {
 	struct shaper *shaper=dev->priv;
 	
@@ -400,7 +400,7 @@
  *	Closing a shaper flushes the queues.
  */
  
-static int shaper_close(struct device *dev)
+static int shaper_close(struct net_device *dev)
 {
 	struct shaper *shaper=dev->priv;
 	shaper_flush(shaper);
@@ -418,19 +418,19 @@
  */
 
 
-static int shaper_start_xmit(struct sk_buff *skb, struct device *dev)
+static int shaper_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct shaper *sh=dev->priv;
 	return shaper_qframe(sh, skb);
 }
 
-static struct net_device_stats *shaper_get_stats(struct device *dev)
+static struct net_device_stats *shaper_get_stats(struct net_device *dev)
 {
      	struct shaper *sh=dev->priv;
 	return &sh->stats;
 }
 
-static int shaper_header(struct sk_buff *skb, struct device *dev, 
+static int shaper_header(struct sk_buff *skb, struct net_device *dev, 
 	unsigned short type, void *daddr, void *saddr, unsigned len)
 {
 	struct shaper *sh=dev->priv;
@@ -446,7 +446,7 @@
 static int shaper_rebuild_header(struct sk_buff *skb)
 {
 	struct shaper *sh=skb->dev->priv;
-	struct device *dev=skb->dev;
+	struct net_device *dev=skb->dev;
 	int v;
 	if(sh_debug)
 		printk("Shaper rebuild header\n");
@@ -460,7 +460,7 @@
 static int shaper_cache(struct neighbour *neigh, struct hh_cache *hh)
 {
 	struct shaper *sh=neigh->dev->priv;
-	struct device *tmp;
+	struct net_device *tmp;
 	int ret;
 	if(sh_debug)
 		printk("Shaper header cache bind\n");
@@ -471,7 +471,7 @@
 	return ret;
 }
 
-static void shaper_cache_update(struct hh_cache *hh, struct device *dev,
+static void shaper_cache_update(struct hh_cache *hh, struct net_device *dev,
 	unsigned char *haddr)
 {
 	struct shaper *sh=dev->priv;
@@ -490,7 +490,7 @@
 	return 0;
 }
 
-static int shaper_neigh_setup_dev(struct device *dev, struct neigh_parms *p)
+static int shaper_neigh_setup_dev(struct net_device *dev, struct neigh_parms *p)
 {
 	if (p->tbl->family == AF_INET) {
 		p->neigh_setup = shaper_neigh_setup;
@@ -500,7 +500,7 @@
 	return 0;
 }
 
-static int shaper_attach(struct device *shdev, struct shaper *sh, struct device *dev)
+static int shaper_attach(struct net_device *shdev, struct shaper *sh, struct net_device *dev)
 {
 	sh->dev = dev;
 	sh->hard_start_xmit=dev->hard_start_xmit;
@@ -553,7 +553,7 @@
 	return 0;
 }
 
-static int shaper_ioctl(struct device *dev,  struct ifreq *ifr, int cmd)
+static int shaper_ioctl(struct net_device *dev,  struct ifreq *ifr, int cmd)
 {
 	struct shaperconf *ss= (struct shaperconf *)&ifr->ifr_data;
 	struct shaper *sh=dev->priv;
@@ -561,7 +561,7 @@
 	{
 		case SHAPER_SET_DEV:
 		{
-			struct device *them=dev_get(ss->ss_name);
+			struct net_device *them=dev_get(ss->ss_name);
 			if(them==NULL)
 				return -ENODEV;
 			if(sh->dev)
@@ -584,7 +584,7 @@
 	}
 }
 
-static struct shaper *shaper_alloc(struct device *dev)
+static struct shaper *shaper_alloc(struct net_device *dev)
 {
 	struct shaper *sh=kmalloc(sizeof(struct shaper), GFP_KERNEL);
 	if(sh==NULL)
@@ -602,7 +602,7 @@
  *	Add a shaper device to the system
  */
  
-int __init shaper_probe(struct device *dev)
+int __init shaper_probe(struct net_device *dev)
 {
 	/*
 	 *	Set up the shaper.
@@ -655,7 +655,7 @@
 
 static char devicename[9];
 
-static struct device dev_shape = 
+static struct net_device dev_shape = 
 {
 	devicename,
 	0, 0, 0, 0,
@@ -696,7 +696,7 @@
 
 #else
 
-static struct device dev_sh0 = 
+static struct net_device dev_sh0 = 
 {
 	"shaper0",
 	0, 0, 0, 0,
@@ -705,7 +705,7 @@
 };
 
 
-static struct device dev_sh1 = 
+static struct net_device dev_sh1 = 
 {
 	"shaper1",
 	0, 0, 0, 0,
@@ -714,7 +714,7 @@
 };
 
 
-static struct device dev_sh2 = 
+static struct net_device dev_sh2 = 
 {
 	"shaper2",
 	0, 0, 0, 0,
@@ -722,7 +722,7 @@
 	0, 0, 0, NULL, shaper_probe 
 };
 
-static struct device dev_sh3 = 
+static struct net_device dev_sh3 = 
 {
 	"shaper3",
 	0, 0, 0, 0,
diff -u --recursive --new-file v2.3.13/linux/drivers/net/sk_g16.c linux/drivers/net/sk_g16.c
--- v2.3.13/linux/drivers/net/sk_g16.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/sk_g16.c	Wed Aug 18 11:36:42 1999
@@ -466,28 +466,28 @@
  * See for short explanation of each function its definitions header.
  */
 
-int          SK_init(struct device *dev);
-static int   SK_probe(struct device *dev, short ioaddr);
+int          SK_init(struct net_device *dev);
+static int   SK_probe(struct net_device *dev, short ioaddr);
 
-static int   SK_open(struct device *dev);
-static int   SK_send_packet(struct sk_buff *skb, struct device *dev);
+static int   SK_open(struct net_device *dev);
+static int   SK_send_packet(struct sk_buff *skb, struct net_device *dev);
 static void  SK_interrupt(int irq, void *dev_id, struct pt_regs * regs);
-static void  SK_rxintr(struct device *dev);
-static void  SK_txintr(struct device *dev);
-static int   SK_close(struct device *dev);
+static void  SK_rxintr(struct net_device *dev);
+static void  SK_txintr(struct net_device *dev);
+static int   SK_close(struct net_device *dev);
 
-static struct net_device_stats *SK_get_stats(struct device *dev);
+static struct net_device_stats *SK_get_stats(struct net_device *dev);
 
 unsigned int SK_rom_addr(void);
 
-static void set_multicast_list(struct device *dev);
+static void set_multicast_list(struct net_device *dev);
 
 /*
  * LANCE Functions
  * ---------------
  */
 
-static int SK_lance_init(struct device *dev, unsigned short mode);
+static int SK_lance_init(struct net_device *dev, unsigned short mode);
 void   SK_reset_board(void);
 void   SK_set_RAP(int reg_number);
 int    SK_read_reg(int reg_number);
@@ -499,9 +499,9 @@
  * -------------------
  */
 
-void SK_print_pos(struct device *dev, char *text);
-void SK_print_dev(struct device *dev, char *text);
-void SK_print_ram(struct device *dev);
+void SK_print_pos(struct net_device *dev, char *text);
+void SK_print_dev(struct net_device *dev, char *text);
+void SK_print_ram(struct net_device *dev);
 
 
 /*-
@@ -513,7 +513,7 @@
  *                  This function gets called by dev_init which initializes
  *                  all Network devices.
  *
- * Parameters     : I : struct device *dev - structure preconfigured 
+ * Parameters     : I : struct net_device *dev - structure preconfigured 
  *                                           from Space.c
  * Return Value   : 0 = Driver Found and initialized 
  * Errors         : ENODEV - no device found
@@ -531,7 +531,7 @@
  *                         (detachable devices only).
  */
 
-int __init SK_init(struct device *dev)
+int __init SK_init(struct net_device *dev)
 {
 	int ioaddr         = 0;            /* I/O port address used for POS regs */
 	int *port, ports[] = SK_IO_PORTS;  /* SK_G16 supported ports */
@@ -603,7 +603,7 @@
  * Description    : This function is called by SK_init and 
  *                  does the main part of initialization.
  *                  
- * Parameters     : I : struct device *dev - SK_G16 device structure
+ * Parameters     : I : struct net_device *dev - SK_G16 device structure
  *                  I : short ioaddr       - I/O Port address where POS is.
  * Return Value   : 0 = Initialization done             
  * Errors         : ENODEV - No SK_G16 found
@@ -614,7 +614,7 @@
  *     94/06/30  pwe  SK_ADDR now checked and at the correct place
 -*/
 
-int __init SK_probe(struct device *dev, short ioaddr)
+int __init SK_probe(struct net_device *dev, short ioaddr)
 {
     int i,j;                /* Counters */
     int sk_addr_flag = 0;   /* SK ADDR correct? 1 - no, 0 - yes */
@@ -832,7 +832,7 @@
  *
  *                  (Called by dev_open() /net/inet/dev.c)
  *
- * Parameters     : I : struct device *dev - SK_G16 device structure
+ * Parameters     : I : struct net_device *dev - SK_G16 device structure
  * Return Value   : 0 - Device opened
  * Errors         : -EAGAIN - Open failed
  * Side Effects   : None
@@ -840,7 +840,7 @@
  *     YY/MM/DD  uid  Description
 -*/
 
-static int SK_open(struct device *dev)
+static int SK_open(struct net_device *dev)
 {
     int i = 0;
     int irqval = 0;
@@ -994,7 +994,7 @@
  * Description    : Reset LANCE chip, fill RMD, TMD structures with
  *                  start values and Start LANCE.
  *
- * Parameters     : I : struct device *dev - SK_G16 device structure
+ * Parameters     : I : struct net_device *dev - SK_G16 device structure
  *                  I : int mode - put LANCE into "mode" see data-sheet for
  *                                 more info.
  * Return Value   : 0  - Init done
@@ -1003,7 +1003,7 @@
  *     YY/MM/DD  uid  Description
 -*/
 
-static int SK_lance_init(struct device *dev, unsigned short mode)
+static int SK_lance_init(struct net_device *dev, unsigned short mode)
 {
     int i;
     unsigned long flags;
@@ -1161,7 +1161,7 @@
  *                  and starts transmission.
  *
  * Parameters     : I : struct sk_buff *skb - packet to transfer
- *                  I : struct device *dev  - SK_G16 device structure
+ *                  I : struct net_device *dev  - SK_G16 device structure
  * Return Value   : 0 - OK
  *                  1 - Could not transmit (dev_queue_xmit will queue it)
  *                      and try to sent it later
@@ -1171,7 +1171,7 @@
  *     YY/MM/DD  uid  Description
 -*/
 
-static int SK_send_packet(struct sk_buff *skb, struct device *dev)
+static int SK_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
     struct priv *p = (struct priv *) dev->priv;
     struct tmd *tmdp;
@@ -1278,7 +1278,7 @@
 static void SK_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
     int csr0;
-    struct device *dev = dev_id;
+    struct net_device *dev = dev_id;
     struct priv *p = (struct priv *) dev->priv;
 
 
@@ -1342,7 +1342,7 @@
  *                  statistics and relinquish ownership of transmit 
  *                  descriptor ring.
  *
- * Parameters     : I : struct device *dev - SK_G16 device structure
+ * Parameters     : I : struct net_device *dev - SK_G16 device structure
  * Return Value   : None
  * Errors         : None
  * Globals        : None
@@ -1350,7 +1350,7 @@
  *     YY/MM/DD  uid  Description
 -*/
 
-static void SK_txintr(struct device *dev)
+static void SK_txintr(struct net_device *dev)
 {
     int tmdstat;
     struct tmd *tmdp;
@@ -1470,7 +1470,7 @@
  *     YY/MM/DD  uid  Description
 -*/
 
-static void SK_rxintr(struct device *dev)
+static void SK_rxintr(struct net_device *dev)
 {
 
     struct rmd *rmdp;
@@ -1607,7 +1607,7 @@
  * Description    : close gets called from dev_close() and should
  *                  deinstall the card (free_irq, mem etc).
  *
- * Parameters     : I : struct device *dev - our device structure
+ * Parameters     : I : struct net_device *dev - our device structure
  * Return Value   : 0 - closed device driver
  * Errors         : None
  * Globals        : None
@@ -1619,7 +1619,7 @@
  * down' the system stops. So I don't shut set card to init state.
  */
 
-static int SK_close(struct device *dev)
+static int SK_close(struct net_device *dev)
 {
 
     PRINTK(("## %s: SK_close(). CSR0: %#06x\n", 
@@ -1648,7 +1648,7 @@
  * Description    : Return current status structure to upper layers.
  *                  It is called by sprintf_stats (dev.c).
  *
- * Parameters     : I : struct device *dev   - our device structure
+ * Parameters     : I : struct net_device *dev   - our device structure
  * Return Value   : struct net_device_stats * - our current statistics
  * Errors         : None
  * Side Effects   : None
@@ -1656,7 +1656,7 @@
  *     YY/MM/DD  uid  Description
 -*/
 
-static struct net_device_stats *SK_get_stats(struct device *dev)
+static struct net_device_stats *SK_get_stats(struct net_device *dev)
 {
 
     struct priv *p = (struct priv *) dev->priv;
@@ -1684,7 +1684,7 @@
  *                  but it is also a security problem. You have to remember
  *                  that all information on the net is not encrypted.
  *
- * Parameters     : I : struct device *dev - SK_G16 device Structure
+ * Parameters     : I : struct net_device *dev - SK_G16 device Structure
  * Return Value   : None
  * Errors         : None
  * Globals        : None
@@ -1697,7 +1697,7 @@
 /* Set or clear the multicast filter for SK_G16.
  */
 
-static void set_multicast_list(struct device *dev)
+static void set_multicast_list(struct net_device *dev)
 {
 
     if (dev->flags&IFF_PROMISC)
@@ -1949,7 +1949,7 @@
  * Description    : This function prints out the 4 POS (Programmable
  *                  Option Select) Registers. Used mainly to debug operation.
  *
- * Parameters     : I : struct device *dev - SK_G16 device structure
+ * Parameters     : I : struct net_device *dev - SK_G16 device structure
  *                  I : char * - Text which will be printed as title
  * Return Value   : None
  * Errors         : None
@@ -1957,7 +1957,7 @@
  *     YY/MM/DD  uid  Description
 -*/
 
-void SK_print_pos(struct device *dev, char *text)
+void SK_print_pos(struct net_device *dev, char *text)
 {
     int ioaddr = dev->base_addr;
 
@@ -1984,7 +1984,7 @@
  * Description    : This function simply prints out the important fields
  *                  of the device structure.
  *
- * Parameters     : I : struct device *dev  - SK_G16 device structure
+ * Parameters     : I : struct net_device *dev  - SK_G16 device structure
  *                  I : char *text - Title for printing
  * Return Value   : None
  * Errors         : None
@@ -1992,7 +1992,7 @@
  *     YY/MM/DD  uid  Description
 -*/
 
-void SK_print_dev(struct device *dev, char *text)
+void SK_print_dev(struct net_device *dev, char *text)
 {
     if (dev == NULL)
     {
@@ -2027,7 +2027,7 @@
  *                  It contains a minor bug in printing, but has no effect to the values
  *                  only newlines are not correct.
  *
- * Parameters     : I : struct device *dev - SK_G16 device structure
+ * Parameters     : I : struct net_device *dev - SK_G16 device structure
  * Return Value   : None
  * Errors         : None
  * Globals        : None
@@ -2035,7 +2035,7 @@
  *     YY/MM/DD  uid  Description
 -*/
 
-void SK_print_ram(struct device *dev)
+void SK_print_ram(struct net_device *dev)
 {
 
     int i;    
diff -u --recursive --new-file v2.3.13/linux/drivers/net/sk_mca.c linux/drivers/net/sk_mca.c
--- v2.3.13/linux/drivers/net/sk_mca.c	Mon Jun  7 14:34:46 1999
+++ linux/drivers/net/sk_mca.c	Wed Aug 18 11:36:42 1999
@@ -110,7 +110,7 @@
 /* dump parts of shared memory - only needed during debugging */
 
 #ifdef DEBUG
-static void dumpmem(struct device *dev, u32 start, u32 len)
+static void dumpmem(struct net_device *dev, u32 start, u32 len)
 {
   int z;
 
@@ -199,7 +199,7 @@
 
 /* reset the whole board */
 
-static void ResetBoard(struct device *dev)
+static void ResetBoard(struct net_device *dev)
 {
   skmca_priv *priv = (skmca_priv*) dev->priv;
 
@@ -210,7 +210,7 @@
 
 /* set LANCE register - must be atomic */
 
-static void SetLANCE(struct device *dev, u16 addr, u16 value)
+static void SetLANCE(struct net_device *dev, u16 addr, u16 value)
 {
   skmca_priv *priv = (skmca_priv*) dev->priv;
   unsigned long flags;
@@ -247,7 +247,7 @@
 
 /* get LANCE register */
 
-static u16 GetLANCE(struct device *dev, u16 addr)
+static u16 GetLANCE(struct net_device *dev, u16 addr)
 {
   skmca_priv *priv = (skmca_priv*) dev->priv;
   unsigned long flags;
@@ -287,7 +287,7 @@
 
 /* build up descriptors in shared RAM */
 
-static void InitDscrs(struct device *dev)
+static void InitDscrs(struct net_device *dev)
 {
   u32 bufaddr;
 
@@ -381,7 +381,7 @@
 
 /* feed ready-built initialization block into LANCE */
 
-static void InitLANCE(struct device *dev)
+static void InitLANCE(struct net_device *dev)
 {
   skmca_priv *priv = (skmca_priv*) dev->priv;
 
@@ -420,7 +420,7 @@
 
 /* stop the LANCE so we can reinitialize it */
 
-static void StopLANCE(struct device *dev)
+static void StopLANCE(struct net_device *dev)
 {
   /* can't take frames any more */
 
@@ -433,7 +433,7 @@
 
 /* initialize card and LANCE for proper operation */
 
-static void InitBoard(struct device *dev)
+static void InitBoard(struct net_device *dev)
 {
   LANCE_InitBlock block;
 
@@ -458,7 +458,7 @@
 
 /* deinitialize card and LANCE */
 
-static void DeinitBoard(struct device *dev)
+static void DeinitBoard(struct net_device *dev)
 {
   /* stop LANCE */
 
@@ -475,7 +475,7 @@
 
 /* LANCE has read initializazion block -> start it */
 
-static u16 irqstart_handler(struct device *dev, u16 oldcsr0)
+static u16 irqstart_handler(struct net_device *dev, u16 oldcsr0)
 {
   /* now we're ready to transmit */
 
@@ -489,7 +489,7 @@
 
 /* receive interrupt */
 
-static u16 irqrx_handler(struct device *dev, u16 oldcsr0)
+static u16 irqrx_handler(struct net_device *dev, u16 oldcsr0)
 {
   skmca_priv *priv = (skmca_priv*) dev->priv;
   LANCE_RxDescr descr;
@@ -575,7 +575,7 @@
 
 /* transmit interrupt */
 
-static u16 irqtx_handler(struct device *dev, u16 oldcsr0)
+static u16 irqtx_handler(struct net_device *dev, u16 oldcsr0)
 {
   skmca_priv *priv = (skmca_priv*) dev->priv;
   LANCE_TxDescr descr;
@@ -653,7 +653,7 @@
 
 static void irq_handler(int irq, void *device, struct pt_regs *regs)
 {
-  struct device *dev = (struct device*) device;
+  struct net_device *dev = (struct net_device*) device;
   u16 csr0val;
 
   /* read CSR0 to get interrupt cause */
@@ -692,7 +692,7 @@
 static int skmca_getinfo(char *buf, int slot, void *d)
 {
   int len = 0, i;
-  struct device *dev = (struct device*) d;
+  struct net_device *dev = (struct net_device*) d;
   skmca_priv *priv;
   
   /* can't say anything about an uninitialized device... */
@@ -721,7 +721,7 @@
 
 /* open driver.  Means also initialization and start of LANCE */
 
-static int skmca_open(struct device *dev)
+static int skmca_open(struct net_device *dev)
 {
   int result;
   skmca_priv *priv = (skmca_priv*) dev->priv;
@@ -748,7 +748,7 @@
 
 /* close driver.  Shut down board and free allocated resources */
 
-static int skmca_close(struct device *dev)
+static int skmca_close(struct net_device *dev)
 {
   /* turn off board */
   DeinitBoard(dev);
@@ -767,7 +767,7 @@
 
 /* transmit a block. */
 
-static int skmca_tx(struct sk_buff *skb, struct device *dev)
+static int skmca_tx(struct sk_buff *skb, struct net_device *dev)
 {
   skmca_priv *priv = (skmca_priv*) dev->priv;
   LANCE_TxDescr descr;
@@ -864,7 +864,7 @@
 
 /* return pointer to Ethernet statistics */
 
-static struct enet_statistics *skmca_stats(struct device *dev)
+static struct enet_statistics *skmca_stats(struct net_device *dev)
 {
   skmca_priv *priv = (skmca_priv*) dev->priv;
 
@@ -874,7 +874,7 @@
 /* we don't support runtime reconfiguration, since am MCA card can
    be unambigously identified by its POS registers. */
 
-static int skmca_config(struct device *dev, struct ifmap *map)
+static int skmca_config(struct net_device *dev, struct ifmap *map)
 {
   return 0;
 }
@@ -882,7 +882,7 @@
 /* switch receiver mode.  We use the LANCE's multicast filter to prefilter
    multicast addresses. */
 
-static void skmca_set_multicast_list(struct device *dev)
+static void skmca_set_multicast_list(struct net_device *dev)
 {
   LANCE_InitBlock block;
 
@@ -929,7 +929,7 @@
 #define startslot 0   /* otherwise a dummy, since there is only eth0 in-kern*/
 #endif
 
-int skmca_probe(struct device *dev)
+int skmca_probe(struct net_device *dev)
 {
   int force_detect = 0;
   int junior, slot, i;
@@ -1082,7 +1082,7 @@
 #define DEVMAX 5
 
 static char NameSpace[8 * DEVMAX];
-static struct device moddevs[DEVMAX] =
+static struct net_device moddevs[DEVMAX] =
        {{NameSpace +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
         {NameSpace +  8, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
         {NameSpace + 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
@@ -1110,7 +1110,7 @@
 
 void cleanup_module(void)
 {
-  struct device *dev;
+  struct net_device *dev;
   skmca_priv *priv;
   int z;
 
diff -u --recursive --new-file v2.3.13/linux/drivers/net/sk_mca.h linux/drivers/net/sk_mca.h
--- v2.3.13/linux/drivers/net/sk_mca.h	Mon Jun  7 14:34:46 1999
+++ linux/drivers/net/sk_mca.h	Wed Aug 18 11:36:45 1999
@@ -168,7 +168,7 @@
 
 #endif /* _SK_MCA_DRIVER_ */
 
-extern int skmca_probe(struct device *);
+extern int skmca_probe(struct net_device *);
 
 
 #endif /* _SK_MCA_INCLUDE_ */
diff -u --recursive --new-file v2.3.13/linux/drivers/net/skeleton.c linux/drivers/net/skeleton.c
--- v2.3.13/linux/drivers/net/skeleton.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/skeleton.c	Wed Aug 18 11:36:42 1999
@@ -96,21 +96,21 @@
 
 /* Index to functions, as function prototypes. */
 
-extern int netcard_probe(struct device *dev);
+extern int netcard_probe(struct net_device *dev);
 
-static int	netcard_probe1(struct device *dev, int ioaddr);
-static int	net_open(struct device *dev);
-static int	net_send_packet(struct sk_buff *skb, struct device *dev);
+static int	netcard_probe1(struct net_device *dev, int ioaddr);
+static int	net_open(struct net_device *dev);
+static int	net_send_packet(struct sk_buff *skb, struct net_device *dev);
 static void	net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void	net_rx(struct device *dev);
-static int	net_close(struct device *dev);
-static struct	net_device_stats *net_get_stats(struct device *dev);
-static void	set_multicast_list(struct device *dev);
+static void	net_rx(struct net_device *dev);
+static int	net_close(struct net_device *dev);
+static struct	net_device_stats *net_get_stats(struct net_device *dev);
+static void	set_multicast_list(struct net_device *dev);
 
 /* Example routines you must write ;->. */
 #define tx_done(dev) 1
 extern void	hardware_send_packet(short ioaddr, char *buf, int length);
-extern void 	chipset_init(struct device *dev, int startp);
+extern void 	chipset_init(struct net_device *dev, int startp);
 
 /*
  * Check for a network adaptor of this type, and return '0' iff one exists.
@@ -128,7 +128,7 @@
 {cardname, netcard_probe1, NETCARD_IO_EXTENT, netcard_portlist};
 #else
 int __init 
-netcard_probe(struct device *dev)
+netcard_probe(struct net_device *dev)
 {
 	int i;
 	int base_addr = dev ? dev->base_addr : 0;
@@ -155,7 +155,7 @@
  * probes on the ISA bus. A good device probes avoids doing writes, and
  * verifies that the correct device exists and functions.
  */
-static int __init netcard_probe1(struct device *dev, int ioaddr)
+static int __init netcard_probe1(struct net_device *dev, int ioaddr)
 {
 	static unsigned version_printed = 0;
 	int i;
@@ -306,7 +306,7 @@
  * there is non-reboot way to recover if something goes wrong.
  */
 static int
-net_open(struct device *dev)
+net_open(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -340,7 +340,7 @@
 	return 0;
 }
 
-static int net_send_packet(struct sk_buff *skb, struct device *dev)
+static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -389,7 +389,7 @@
  */
 static void net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
-	struct device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	struct net_local *lp;
 	int ioaddr, status, boguscount = 0;
 
@@ -425,7 +425,7 @@
 
 /* We have a good packet(s), get it/them out of the buffers. */
 static void
-net_rx(struct device *dev)
+net_rx(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -480,7 +480,7 @@
 
 /* The inverse routine to net_open(). */
 static int
-net_close(struct device *dev)
+net_close(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -512,7 +512,7 @@
  * Get the current statistics.
  * This may be called with the card open or closed.
  */
-static struct net_device_stats *net_get_stats(struct device *dev)
+static struct net_device_stats *net_get_stats(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	short ioaddr = dev->base_addr;
@@ -533,7 +533,7 @@
  *			and do best-effort filtering.
  */
 static void
-set_multicast_list(struct device *dev)
+set_multicast_list(struct net_device *dev)
 {
 	short ioaddr = dev->base_addr;
 	if (dev->flags&IFF_PROMISC)
@@ -562,7 +562,7 @@
 #ifdef MODULE
 
 static char devicename[9] = { 0, };
-static struct device this_device = {
+static struct net_device this_device = {
 	devicename, /* will be inserted by linux/drivers/net/net_init.c */
 	0, 0, 0, 0,
 	0, 0,  /* I/O address, IRQ */
diff -u --recursive --new-file v2.3.13/linux/drivers/net/sktr.c linux/drivers/net/sktr.c
--- v2.3.13/linux/drivers/net/sktr.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/sktr.c	Wed Aug 18 11:36:42 1999
@@ -116,63 +116,63 @@
  */
 
 /* "B" */
-static int      sktr_bringup_diags(struct device *dev);
+static int      sktr_bringup_diags(struct net_device *dev);
 /* "C" */
 static void	sktr_cancel_tx_queue(struct net_local* tp);
-static int 	sktr_chipset_init(struct device *dev);
-static void 	sktr_chk_irq(struct device *dev);
-static unsigned char sktr_chk_frame(struct device *dev, unsigned char *Addr);
-static void 	sktr_chk_outstanding_cmds(struct device *dev);
+static int 	sktr_chipset_init(struct net_device *dev);
+static void 	sktr_chk_irq(struct net_device *dev);
+static unsigned char sktr_chk_frame(struct net_device *dev, unsigned char *Addr);
+static void 	sktr_chk_outstanding_cmds(struct net_device *dev);
 static void 	sktr_chk_src_addr(unsigned char *frame, unsigned char *hw_addr);
 static unsigned char sktr_chk_ssb(struct net_local *tp, unsigned short IrqType);
-static int 	sktr_close(struct device *dev);
-static void 	sktr_cmd_status_irq(struct device *dev);
+static int 	sktr_close(struct net_device *dev);
+static void 	sktr_cmd_status_irq(struct net_device *dev);
 /* "D" */
-static void 	sktr_disable_interrupts(struct device *dev);
+static void 	sktr_disable_interrupts(struct net_device *dev);
 static void 	sktr_dump(unsigned char *Data, int length);
 /* "E" */
-static void 	sktr_enable_interrupts(struct device *dev);
-static void 	sktr_exec_cmd(struct device *dev, unsigned short Command);
-static void 	sktr_exec_sifcmd(struct device *dev, unsigned int WriteValue);
+static void 	sktr_enable_interrupts(struct net_device *dev);
+static void 	sktr_exec_cmd(struct net_device *dev, unsigned short Command);
+static void 	sktr_exec_sifcmd(struct net_device *dev, unsigned int WriteValue);
 /* "F" */
 static unsigned char *sktr_fix_srouting(unsigned char *buf, short *FrameLen);
 /* "G" */
-static struct enet_statistics *sktr_get_stats(struct device *dev);
+static struct enet_statistics *sktr_get_stats(struct net_device *dev);
 /* "H" */
-static void 	sktr_hardware_send_packet(struct device *dev,
+static void 	sktr_hardware_send_packet(struct net_device *dev,
 			struct net_local* tp);
 /* "I" */
-static int 	sktr_init_adapter(struct device *dev);
-static int 	sktr_init_card(struct device *dev);
+static int 	sktr_init_adapter(struct net_device *dev);
+static int 	sktr_init_card(struct net_device *dev);
 static void 	sktr_init_ipb(struct net_local *tp);
-static void 	sktr_init_net_local(struct device *dev);
+static void 	sktr_init_net_local(struct net_device *dev);
 static void 	sktr_init_opb(struct net_local *tp);
 static void 	sktr_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static int 	sktr_isa_chk_card(struct device *dev, int ioaddr);
+static int 	sktr_isa_chk_card(struct net_device *dev, int ioaddr);
 static int      sktr_isa_chk_ioaddr(int ioaddr);
 /* "O" */
-static int 	sktr_open(struct device *dev);
-static void	sktr_open_adapter(struct device *dev);
+static int 	sktr_open(struct net_device *dev);
+static void	sktr_open_adapter(struct net_device *dev);
 /* "P" */
-static int 	sktr_pci_chk_card(struct device *dev);
-int 		sktr_probe(struct device *dev);
-static int 	sktr_probe1(struct device *dev, int ioaddr);
+static int 	sktr_pci_chk_card(struct net_device *dev);
+int 		sktr_probe(struct net_device *dev);
+static int 	sktr_probe1(struct net_device *dev, int ioaddr);
 /* "R" */
-static void 	sktr_rcv_status_irq(struct device *dev);
-static void 	sktr_read_addr(struct device *dev, unsigned char *Address);
-static void 	sktr_read_ptr(struct device *dev);
-static void 	sktr_read_ram(struct device *dev, unsigned char *Data,
+static void 	sktr_rcv_status_irq(struct net_device *dev);
+static void 	sktr_read_addr(struct net_device *dev, unsigned char *Address);
+static void 	sktr_read_ptr(struct net_device *dev);
+static void 	sktr_read_ram(struct net_device *dev, unsigned char *Data,
 			unsigned short Address, int Length);
-static int 	sktr_reset_adapter(struct device *dev);
-static void 	sktr_reset_interrupt(struct device *dev);
-static void 	sktr_ring_status_irq(struct device *dev);
+static int 	sktr_reset_adapter(struct net_device *dev);
+static void 	sktr_reset_interrupt(struct net_device *dev);
+static void 	sktr_ring_status_irq(struct net_device *dev);
 /* "S" */
-static int 	sktr_send_packet(struct sk_buff *skb, struct device *dev);
-static void 	sktr_set_multicast_list(struct device *dev);
+static int 	sktr_send_packet(struct sk_buff *skb, struct net_device *dev);
+static void 	sktr_set_multicast_list(struct net_device *dev);
 /* "T" */
 static void 	sktr_timer_chk(unsigned long data);
 static void 	sktr_timer_end_wait(unsigned long data);
-static void 	sktr_tx_status_irq(struct device *dev);
+static void 	sktr_tx_status_irq(struct net_device *dev);
 /* "U" */
 static void 	sktr_update_rcv_stats(struct net_local *tp,
 			unsigned char DataPtr[], unsigned int Length);
@@ -186,7 +186,7 @@
  * If dev->base_addr == 0, probe all likely locations.
  * If dev->base_addr == 1, always return failure.
  */
-int __init sktr_probe(struct device *dev)
+int __init sktr_probe(struct net_device *dev)
 {
 	int i;
 	int base_addr = dev ? dev->base_addr : 0;
@@ -217,7 +217,7 @@
 /*
  * Detect and setup the PCI SysKonnect TR cards in slot order.
  */
-static int __init sktr_pci_chk_card(struct device *dev)
+static int __init sktr_pci_chk_card(struct net_device *dev)
 {
 	static int pci_index = 0;
 	unsigned char pci_bus, pci_device_fn;
@@ -295,7 +295,7 @@
 /*
  * Detect and setup the ISA SysKonnect TR cards.
  */
-static int __init sktr_isa_chk_card(struct device *dev, int ioaddr)
+static int __init sktr_isa_chk_card(struct net_device *dev, int ioaddr)
 {
 	int i, err;
 	unsigned long flags;
@@ -386,7 +386,7 @@
 	return (0);
 }
 
-static int __init sktr_probe1(struct device *dev, int ioaddr)
+static int __init sktr_probe1(struct net_device *dev, int ioaddr)
 {
 	static unsigned version_printed = 0;
 	struct net_local *tp;
@@ -428,7 +428,7 @@
 }
 
 /* Dummy function */
-static int __init sktr_init_card(struct device *dev)
+static int __init sktr_init_card(struct net_device *dev)
 {
 	if(sktr_debug > 3)
 		printk("%s: sktr_init_card\n", dev->name);
@@ -480,7 +480,7 @@
  * registers that "should" only need to be set once at boot, so that
  * there is non-reboot way to recover if something goes wrong.
  */
-static int sktr_open(struct device *dev)
+static int sktr_open(struct net_device *dev)
 {
 	struct net_local *tp = (struct net_local *)dev->priv;
 	int err;
@@ -549,7 +549,7 @@
  */
 static void sktr_timer_end_wait(unsigned long data)
 {
-	struct device *dev = (struct device*)data;
+	struct net_device *dev = (struct net_device*)data;
 	struct net_local *tp = (struct net_local *)dev->priv;
 
 	if(tp->Sleeping)
@@ -564,7 +564,7 @@
 /*
  * Initialize the chipset
  */
-static int sktr_chipset_init(struct device *dev)
+static int sktr_chipset_init(struct net_device *dev)
 {
 	struct net_local *tp = (struct net_local *)dev->priv;
 	unsigned char PosReg, Tmp;
@@ -621,7 +621,7 @@
 /*
  * Initializes the net_local structure.
  */
-static void sktr_init_net_local(struct device *dev)
+static void sktr_init_net_local(struct net_device *dev)
 {
 	struct net_local *tp = (struct net_local *)dev->priv;
 	int i;
@@ -778,7 +778,7 @@
 /*
  * Send OPEN command to adapter
  */
-static void sktr_open_adapter(struct device *dev)
+static void sktr_open_adapter(struct net_device *dev)
 {
 	struct net_local *tp = (struct net_local *)dev->priv;
 
@@ -795,7 +795,7 @@
  * Clear the adapter's interrupt flag. Clear system interrupt enable
  * (SINTEN): disable adapter to system interrupts.
  */
-static void sktr_disable_interrupts(struct device *dev)
+static void sktr_disable_interrupts(struct net_device *dev)
 {
 	outb(0, dev->base_addr + SIFACL);
 
@@ -806,7 +806,7 @@
  * Set the adapter's interrupt flag. Set system interrupt enable
  * (SINTEN): enable adapter to system interrupts.
  */
-static void sktr_enable_interrupts(struct device *dev)
+static void sktr_enable_interrupts(struct net_device *dev)
 {
 	outb(ACL_SINTEN, dev->base_addr + SIFACL);
 
@@ -816,7 +816,7 @@
 /*
  * Put command in command queue, try to execute it.
  */
-static void sktr_exec_cmd(struct device *dev, unsigned short Command)
+static void sktr_exec_cmd(struct net_device *dev, unsigned short Command)
 {
 	struct net_local *tp = (struct net_local *)dev->priv;
 
@@ -855,7 +855,7 @@
 /*
  * Gets skb from system, queues it and checks if it can be sent
  */
-static int sktr_send_packet(struct sk_buff *skb, struct device *dev)
+static int sktr_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
 	struct net_local *tp = (struct net_local *)dev->priv;
 
@@ -906,7 +906,7 @@
 /*
  * Move frames from internal skb queue into adapter tx queue
  */
-static void sktr_hardware_send_packet(struct device *dev, struct net_local* tp)
+static void sktr_hardware_send_packet(struct net_device *dev, struct net_local* tp)
 {
 	TPL *tpl;
 	short length;
@@ -1014,7 +1014,7 @@
  */
 static void sktr_timer_chk(unsigned long data)
 {
-	struct device *dev = (struct device*)data;
+	struct net_device *dev = (struct net_device*)data;
 	struct net_local *tp = (struct net_local*)dev->priv;
 
 	if(tp->HaltInProgress)
@@ -1045,7 +1045,7 @@
  */
 static void sktr_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	struct net_local *tp;
 	int ioaddr;
 	unsigned short irq_type;
@@ -1139,7 +1139,7 @@
 /*
  *  Reset the INTERRUPT SYSTEM bit and issue SSB CLEAR command.
  */
-static void sktr_reset_interrupt(struct device *dev)
+static void sktr_reset_interrupt(struct net_device *dev)
 {
 	struct net_local *tp = (struct net_local *)dev->priv;
 	SSB *ssb = &tp->ssb;
@@ -1225,7 +1225,7 @@
 /*
  * Evaluates the command results status in the SSB status field.
  */
-static void sktr_cmd_status_irq(struct device *dev)
+static void sktr_cmd_status_irq(struct net_device *dev)
 {
 	struct net_local *tp = (struct net_local *)dev->priv;
 	unsigned short ssb_cmd, ssb_parm_0;
@@ -1422,7 +1422,7 @@
 /*
  * The inverse routine to sktr_open().
  */
-static int sktr_close(struct device *dev)
+static int sktr_close(struct net_device *dev)
 {
 	struct net_local *tp = (struct net_local *)dev->priv;
 
@@ -1473,7 +1473,7 @@
  * Get the current statistics. This may be called with the card open
  * or closed.
  */
-static struct enet_statistics *sktr_get_stats(struct device *dev)
+static struct enet_statistics *sktr_get_stats(struct net_device *dev)
 {
 	struct net_local *tp = (struct net_local *)dev->priv;
 
@@ -1483,7 +1483,7 @@
 /*
  * Set or clear the multicast filter for this adapter.
  */
-static void sktr_set_multicast_list(struct device *dev)
+static void sktr_set_multicast_list(struct net_device *dev)
 {
 	struct net_local *tp = (struct net_local *)dev->priv;
 	unsigned int OpenOptions;
@@ -1539,7 +1539,7 @@
 /*
  * Write a command value to the SIFCMD register
  */
-static void sktr_exec_sifcmd(struct device *dev, unsigned int WriteValue)
+static void sktr_exec_sifcmd(struct net_device *dev, unsigned int WriteValue)
 {
 	int ioaddr = dev->base_addr;
 	unsigned short cmd;
@@ -1561,7 +1561,7 @@
  * Processes adapter hardware reset, halts adapter and downloads firmware,
  * clears the halt bit.
  */
-static int sktr_reset_adapter(struct device *dev)
+static int sktr_reset_adapter(struct net_device *dev)
 {
 	struct net_local *tp = (struct net_local *)dev->priv;
 	unsigned short *fw_ptr = (unsigned short *)&sktr_code;
@@ -1630,7 +1630,7 @@
  * Starts bring up diagnostics of token ring adapter and evaluates
  * diagnostic results.
  */
-static int sktr_bringup_diags(struct device *dev)
+static int sktr_bringup_diags(struct net_device *dev)
 {
 	int loop_cnt, retry_cnt;
 	unsigned short Status;
@@ -1685,7 +1685,7 @@
  * Copy initialisation data to adapter memory, beginning at address
  * 1:0A00; Starting DMA test and evaluating result bits.
  */
-static int sktr_init_adapter(struct device *dev)
+static int sktr_init_adapter(struct net_device *dev)
 {
 	struct net_local *tp = (struct net_local *)dev->priv;
 
@@ -1787,7 +1787,7 @@
  * Check for outstanding commands in command queue and tries to execute
  * command immediately. Corresponding command flag in command queue is cleared.
  */
-static void sktr_chk_outstanding_cmds(struct device *dev)
+static void sktr_chk_outstanding_cmds(struct net_device *dev)
 {
 	struct net_local *tp = (struct net_local *)dev->priv;
 	unsigned long Addr = 0;
@@ -1967,7 +1967,7 @@
  * error counter overflow (255); opened adapter is the only station in ring.
  * After some of the IRQs the adapter is closed!
  */
-static void sktr_ring_status_irq(struct device *dev)
+static void sktr_ring_status_irq(struct net_device *dev)
 {
 	struct net_local *tp = (struct net_local *)dev->priv;
 
@@ -2037,7 +2037,7 @@
  * Issued if adapter has encountered an unrecoverable hardware
  * or software error.
  */
-static void sktr_chk_irq(struct device *dev)
+static void sktr_chk_irq(struct net_device *dev)
 {
 	int i;
 	unsigned short AdapterCheckBlock[4];
@@ -2196,7 +2196,7 @@
  * Internal adapter pointer to RAM data are copied from adapter into
  * host system.
  */
-static void sktr_read_ptr(struct device *dev)
+static void sktr_read_ptr(struct net_device *dev)
 {
 	struct net_local *tp = (struct net_local *)dev->priv;
 	unsigned short adapterram;
@@ -2215,7 +2215,7 @@
 /*
  * Reads a number of bytes from adapter to system memory.
  */
-static void sktr_read_ram(struct device *dev, unsigned char *Data,
+static void sktr_read_ram(struct net_device *dev, unsigned char *Data,
 				unsigned short Address, int Length)
 {
 	int i;
@@ -2256,7 +2256,7 @@
 /*
  * Reads MAC address from adapter ROM.
  */
-static void sktr_read_addr(struct device *dev, unsigned char *Address)
+static void sktr_read_addr(struct net_device *dev, unsigned char *Address)
 {
 	int i, In;
 	unsigned short ioaddr = dev->base_addr;
@@ -2322,7 +2322,7 @@
  * adapter. For a command complete interrupt, it is checked if we have to
  * issue a new transmit command or not.
  */
-static void sktr_tx_status_irq(struct device *dev)
+static void sktr_tx_status_irq(struct net_device *dev)
 {
 	struct net_local *tp = (struct net_local *)dev->priv;
 	unsigned char HighByte, HighAc, LowAc;
@@ -2396,7 +2396,7 @@
  * Called if a frame receive interrupt is generated by the adapter.
  * Check if the frame is valid and indicate it to system.
  */
-static void sktr_rcv_status_irq(struct device *dev)
+static void sktr_rcv_status_irq(struct net_device *dev)
 {
 	struct net_local *tp = (struct net_local *)dev->priv;
 	unsigned char *ReceiveDataPtr;
@@ -2599,7 +2599,7 @@
  * Check if it is a frame of myself. Compare source address with my current
  * address in reverse direction, and mask out the TR_RII.
  */
-static unsigned char sktr_chk_frame(struct device *dev, unsigned char *Addr)
+static unsigned char sktr_chk_frame(struct net_device *dev, unsigned char *Addr)
 {
 	int i;
 
@@ -2635,7 +2635,7 @@
 
 #ifdef MODULE
 
-static struct device* dev_sktr[SKTR_MAX_ADAPTERS];
+static struct net_device* dev_sktr[SKTR_MAX_ADAPTERS];
 static int io[SKTR_MAX_ADAPTERS]	= { 0, 0 };
 static int irq[SKTR_MAX_ADAPTERS] 	= { 0, 0 };
 static int mem[SKTR_MAX_ADAPTERS] 	= { 0, 0 };
@@ -2664,7 +2664,7 @@
 
                 if(register_trdev(dev_sktr[i]) != 0)
 		{
-                        kfree_s(dev_sktr[i], sizeof(struct device));
+                        kfree_s(dev_sktr[i], sizeof(struct net_device));
                         dev_sktr[i] = NULL;
                         if(i == 0)
 			{
@@ -2695,7 +2695,7 @@
 				free_dma(dev_sktr[i]->dma);
 			if(dev_sktr[i]->priv)
 				kfree_s(dev_sktr[i]->priv, sizeof(struct net_local));
-			kfree_s(dev_sktr[i], sizeof(struct device));
+			kfree_s(dev_sktr[i], sizeof(struct net_device));
 			dev_sktr[i] = NULL;
                 }
 	}
diff -u --recursive --new-file v2.3.13/linux/drivers/net/slip.c linux/drivers/net/slip.c
--- v2.3.13/linux/drivers/net/slip.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/slip.c	Wed Aug 18 11:36:42 1999
@@ -91,7 +91,7 @@
 typedef struct slip_ctrl {
 	char		if_name[8];	/* "sl0\0" .. "sl99999\0"	*/
 	struct slip	ctrl;		/* SLIP things			*/
-	struct device	dev;		/* the device			*/
+	struct net_device	dev;		/* the device			*/
 } slip_ctrl_t;
 static slip_ctrl_t	**slip_ctrls = NULL;
 
@@ -109,7 +109,7 @@
 #ifdef CONFIG_SLIP_SMART
 static void sl_keepalive(unsigned long sls);
 static void sl_outfill(unsigned long sls);
-static int sl_ioctl(struct device *dev,struct ifreq *rq,int cmd);
+static int sl_ioctl(struct net_device *dev,struct ifreq *rq,int cmd);
 #endif
 
 /********************************
@@ -233,7 +233,7 @@
 static int sl_realloc_bufs(struct slip *sl, int mtu)
 {
 	int err = 0;
-	struct device *dev = sl->dev;
+	struct net_device *dev = sl->dev;
 	unsigned char *xbuff, *rbuff;
 #ifdef SL_INCLUDE_CSLIP
 	unsigned char *cbuff;
@@ -473,7 +473,7 @@
 
 /* Encapsulate an IP datagram and kick it into a TTY queue. */
 static int
-sl_xmit(struct sk_buff *skb, struct device *dev)
+sl_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct slip *sl = (struct slip*)(dev->priv);
 
@@ -536,7 +536,7 @@
 /* Netdevice UP -> DOWN routine */
 
 static int
-sl_close(struct device *dev)
+sl_close(struct net_device *dev)
 {
 	struct slip *sl = (struct slip*)(dev->priv);
 
@@ -557,7 +557,7 @@
 
 /* Netdevice DOWN -> UP routine */
 
-static int sl_open(struct device *dev)
+static int sl_open(struct net_device *dev)
 {
 	struct slip *sl = (struct slip*)(dev->priv);
 
@@ -573,7 +573,7 @@
 
 /* Netdevice change MTU request */
 
-static int sl_change_mtu(struct device *dev, int new_mtu)
+static int sl_change_mtu(struct net_device *dev, int new_mtu)
 {
 	struct slip *sl = (struct slip*)(dev->priv);
 
@@ -588,7 +588,7 @@
 /* Netdevice get statistics request */
 
 static struct net_device_stats *
-sl_get_stats(struct device *dev)
+sl_get_stats(struct net_device *dev)
 {
 	static struct net_device_stats stats;
 	struct slip *sl = (struct slip*)(dev->priv);
@@ -624,7 +624,7 @@
 
 /* Netdevice register callback */
 
-static int sl_init(struct device *dev)
+static int sl_init(struct net_device *dev)
 {
 	struct slip *sl = (struct slip*)(dev->priv);
 
@@ -1243,7 +1243,7 @@
    to allow get/set outfill/keepalive parameter
    by ifconfig                                 */
 
-static int sl_ioctl(struct device *dev,struct ifreq *rq,int cmd)
+static int sl_ioctl(struct net_device *dev,struct ifreq *rq,int cmd)
 {
 	struct slip *sl = (struct slip*)(dev->priv);
 
@@ -1318,7 +1318,7 @@
 #ifdef MODULE
 static int slip_init_ctrl_dev(void)
 #else	/* !MODULE */
-int __init slip_init_ctrl_dev(struct device *dummy)
+int __init slip_init_ctrl_dev(struct net_device *dummy)
 #endif	/* !MODULE */
 {
 	int status;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/slip.h linux/drivers/net/slip.h
--- v2.3.13/linux/drivers/net/slip.h	Sun Mar  1 14:40:39 1998
+++ linux/drivers/net/slip.h	Wed Aug 18 11:36:45 1999
@@ -52,7 +52,7 @@
 
   /* Various fields. */
   struct tty_struct	*tty;		/* ptr to TTY structure		*/
-  struct device		*dev;		/* easy for intr handling	*/
+  struct net_device		*dev;		/* easy for intr handling	*/
 #ifdef SL_INCLUDE_CSLIP
   struct slcompress	*slcomp;	/* for header compression 	*/
   unsigned char		*cbuff;		/* compression buffer		*/
@@ -118,6 +118,6 @@
 
 #define SLIP_MAGIC 0x5302
 
-extern int slip_init(struct device *dev);
+extern int slip_init(struct net_device *dev);
 
 #endif	/* _LINUX_SLIP.H */
diff -u --recursive --new-file v2.3.13/linux/drivers/net/smc-mca.c linux/drivers/net/smc-mca.c
--- v2.3.13/linux/drivers/net/smc-mca.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/smc-mca.c	Wed Aug 18 11:36:42 1999
@@ -42,20 +42,20 @@
 #include "smc-mca.h"
 #include <linux/mca.h>
 
-int ultramca_probe(struct device *dev);
+int ultramca_probe(struct net_device *dev);
 
-static int ultramca_open(struct device *dev);
-static void ultramca_reset_8390(struct device *dev);
-static void ultramca_get_8390_hdr(struct device *dev,
+static int ultramca_open(struct net_device *dev);
+static void ultramca_reset_8390(struct net_device *dev);
+static void ultramca_get_8390_hdr(struct net_device *dev,
                                   struct e8390_pkt_hdr *hdr,
                                   int ring_page);
-static void ultramca_block_input(struct device *dev, int count,
+static void ultramca_block_input(struct net_device *dev, int count,
                                  struct sk_buff *skb,
                                  int ring_offset);
-static void ultramca_block_output(struct device *dev, int count,
+static void ultramca_block_output(struct net_device *dev, int count,
                                   const unsigned char *buf,
                                   const int start_page);
-static int ultramca_close_card(struct device *dev);
+static int ultramca_close_card(struct net_device *dev);
 
 #define START_PG        0x00    /* First page of TX buffer */
 
@@ -66,7 +66,7 @@
 #define ULTRA_IO_EXTENT 32
 #define EN0_ERWCNT      0x08  /* Early receive warning count. */
 
-int __init ultramca_probe(struct device *dev)
+int __init ultramca_probe(struct net_device *dev)
 {
 	unsigned short ioaddr;
 	unsigned char reg4, num_pages;
@@ -190,7 +190,7 @@
 	return 0;
 }
 
-static int ultramca_open(struct device *dev)
+static int ultramca_open(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
 
@@ -217,7 +217,7 @@
 	return 0;
 }
 
-static void ultramca_reset_8390(struct device *dev)
+static void ultramca_reset_8390(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
 
@@ -237,7 +237,7 @@
    we don't need to be concerned with ring wrap as the header will be at
    the start of a page, so we optimize accordingly. */
 
-static void ultramca_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+static void ultramca_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 {
 	unsigned long hdr_start = dev->mem_start + ((ring_page - START_PG)<<8);
 
@@ -252,7 +252,7 @@
 /* Block input and output are easy on shared memory ethercards, the only
    complication is when the ring buffer wraps. */
 
-static void ultramca_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
+static void ultramca_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
 {
 	unsigned long xfer_start = dev->mem_start + ring_offset - (START_PG<<8);
 
@@ -272,7 +272,7 @@
 
 }
 
-static void ultramca_block_output(struct device *dev, int count, const unsigned char *buf,
+static void ultramca_block_output(struct net_device *dev, int count, const unsigned char *buf,
                 int start_page)
 {
 	unsigned long shmem = dev->mem_start + ((start_page - START_PG)<<8);
@@ -280,7 +280,7 @@
 	memcpy_toio(shmem, buf, count);
 }
 
-static int ultramca_close_card(struct device *dev)
+static int ultramca_close_card(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
 
@@ -310,7 +310,7 @@
 #define NAMELEN     8   /* # of chars for storing dev->name */
 static char namelist[NAMELEN * MAX_ULTRAMCA_CARDS] = { 0, };
 
-static struct device dev_ultra[MAX_ULTRAMCA_CARDS] =
+static struct net_device dev_ultra[MAX_ULTRAMCA_CARDS] =
 {
 	{
 		NULL,       /* assign a chunk of namelist[] below */
@@ -335,7 +335,7 @@
 
 	for (this_dev = 0; this_dev < MAX_ULTRAMCA_CARDS; this_dev++)
 	{
-		struct device *dev = &dev_ultra[this_dev];
+		struct net_device *dev = &dev_ultra[this_dev];
 		dev->name = namelist+(NAMELEN*this_dev);
 		dev->irq = irq[this_dev];
 		dev->base_addr = io[this_dev];
@@ -367,7 +367,7 @@
 
 	for (this_dev = 0; this_dev < MAX_ULTRAMCA_CARDS; this_dev++)
 	{
-		struct device *dev = &dev_ultra[this_dev];
+		struct net_device *dev = &dev_ultra[this_dev];
         	if (dev->priv != NULL)
         	{
 			void *priv = dev->priv;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/smc-ultra.c linux/drivers/net/smc-ultra.c
--- v2.3.13/linux/drivers/net/smc-ultra.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/smc-ultra.c	Wed Aug 18 11:36:42 1999
@@ -66,24 +66,24 @@
 static unsigned int ultra_portlist[] __initdata =
 {0x200, 0x220, 0x240, 0x280, 0x300, 0x340, 0x380, 0};
 
-int ultra_probe(struct device *dev);
-int ultra_probe1(struct device *dev, int ioaddr);
+int ultra_probe(struct net_device *dev);
+int ultra_probe1(struct net_device *dev, int ioaddr);
 
-static int ultra_open(struct device *dev);
-static void ultra_reset_8390(struct device *dev);
-static void ultra_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
+static int ultra_open(struct net_device *dev);
+static void ultra_reset_8390(struct net_device *dev);
+static void ultra_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
 						int ring_page);
-static void ultra_block_input(struct device *dev, int count,
+static void ultra_block_input(struct net_device *dev, int count,
 						  struct sk_buff *skb, int ring_offset);
-static void ultra_block_output(struct device *dev, int count,
+static void ultra_block_output(struct net_device *dev, int count,
 							const unsigned char *buf, const int start_page);
-static void ultra_pio_get_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
+static void ultra_pio_get_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
 						int ring_page);
-static void ultra_pio_input(struct device *dev, int count,
+static void ultra_pio_input(struct net_device *dev, int count,
 						  struct sk_buff *skb, int ring_offset);
-static void ultra_pio_output(struct device *dev, int count,
+static void ultra_pio_output(struct net_device *dev, int count,
 							 const unsigned char *buf, const int start_page);
-static int ultra_close_card(struct device *dev);
+static int ultra_close_card(struct net_device *dev);
 
 
 #define START_PG		0x00	/* First page of TX buffer */
@@ -106,7 +106,7 @@
 {"ultra", ultra_probe1, NETCARD_IO_EXTENT, netcard_portlist};
 #else
 
-int __init ultra_probe(struct device *dev)
+int __init ultra_probe(struct net_device *dev)
 {
 	int i;
 	int base_addr = dev ? dev->base_addr : 0;
@@ -128,7 +128,7 @@
 }
 #endif
 
-int __init ultra_probe1(struct device *dev, int ioaddr)
+int __init ultra_probe1(struct net_device *dev, int ioaddr)
 {
 	int i;
 	int checksum = 0;
@@ -250,7 +250,7 @@
 }
 
 static int
-ultra_open(struct device *dev)
+ultra_open(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
 	unsigned char irq2reg[] = {0, 0, 0x04, 0x08, 0, 0x0C, 0, 0x40,
@@ -281,7 +281,7 @@
 }
 
 static void
-ultra_reset_8390(struct device *dev)
+ultra_reset_8390(struct net_device *dev)
 {
 	int cmd_port = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC base addr */
 
@@ -305,7 +305,7 @@
    the start of a page, so we optimize accordingly. */
 
 static void
-ultra_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+ultra_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 {
 	unsigned long hdr_start = dev->mem_start + ((ring_page - START_PG)<<8);
 
@@ -323,7 +323,7 @@
    complication is when the ring buffer wraps. */
 
 static void
-ultra_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
+ultra_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
 {
 	unsigned long xfer_start = dev->mem_start + ring_offset - (START_PG<<8);
 
@@ -345,7 +345,7 @@
 }
 
 static void
-ultra_block_output(struct device *dev, int count, const unsigned char *buf,
+ultra_block_output(struct net_device *dev, int count, const unsigned char *buf,
 				int start_page)
 {
 	unsigned long shmem = dev->mem_start + ((start_page - START_PG)<<8);
@@ -366,7 +366,7 @@
    and must be always be rewritten between each read/write direction change.
    This is no problem for us, as the 8390 code ensures that we are single
    threaded. */
-static void ultra_pio_get_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
+static void ultra_pio_get_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
 						int ring_page)
 {
 	int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
@@ -375,7 +375,7 @@
 	insw(ioaddr + IOPD, hdr, sizeof(struct e8390_pkt_hdr)>>1);
 }
 
-static void ultra_pio_input(struct device *dev, int count,
+static void ultra_pio_input(struct net_device *dev, int count,
 						  struct sk_buff *skb, int ring_offset)
 {
 	int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
@@ -388,7 +388,7 @@
 	insw(ioaddr + IOPD, buf, (count+1)>>1);
 }
 
-static void ultra_pio_output(struct device *dev, int count,
+static void ultra_pio_output(struct net_device *dev, int count,
 							const unsigned char *buf, const int start_page)
 {
 	int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
@@ -399,7 +399,7 @@
 }
 
 static int
-ultra_close_card(struct device *dev)
+ultra_close_card(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* CMDREG */
 
@@ -427,7 +427,7 @@
 #define MAX_ULTRA_CARDS	4	/* Max number of Ultra cards per module */
 #define NAMELEN		8	/* # of chars for storing dev->name */
 static char namelist[NAMELEN * MAX_ULTRA_CARDS] = { 0, };
-static struct device dev_ultra[MAX_ULTRA_CARDS] = {
+static struct net_device dev_ultra[MAX_ULTRA_CARDS] = {
 	{
 		NULL,		/* assign a chunk of namelist[] below */
 		0, 0, 0, 0,
@@ -452,7 +452,7 @@
 	int this_dev, found = 0;
 
 	for (this_dev = 0; this_dev < MAX_ULTRA_CARDS; this_dev++) {
-		struct device *dev = &dev_ultra[this_dev];
+		struct net_device *dev = &dev_ultra[this_dev];
 		dev->name = namelist+(NAMELEN*this_dev);
 		dev->irq = irq[this_dev];
 		dev->base_addr = io[this_dev];
@@ -478,7 +478,7 @@
 	int this_dev;
 
 	for (this_dev = 0; this_dev < MAX_ULTRA_CARDS; this_dev++) {
-		struct device *dev = &dev_ultra[this_dev];
+		struct net_device *dev = &dev_ultra[this_dev];
 		if (dev->priv != NULL) {
 			/* NB: ultra_close_card() does free_irq + irq2dev */
 			int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/smc-ultra32.c linux/drivers/net/smc-ultra32.c
--- v2.3.13/linux/drivers/net/smc-ultra32.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/smc-ultra32.c	Wed Aug 18 11:36:42 1999
@@ -60,18 +60,18 @@
 #include <linux/etherdevice.h>
 #include "8390.h"
 
-int ultra32_probe(struct device *dev);
-int ultra32_probe1(struct device *dev, int ioaddr);
-static int ultra32_open(struct device *dev);
-static void ultra32_reset_8390(struct device *dev);
-static void ultra32_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
+int ultra32_probe(struct net_device *dev);
+int ultra32_probe1(struct net_device *dev, int ioaddr);
+static int ultra32_open(struct net_device *dev);
+static void ultra32_reset_8390(struct net_device *dev);
+static void ultra32_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
 				 int ring_page);
-static void ultra32_block_input(struct device *dev, int count,
+static void ultra32_block_input(struct net_device *dev, int count,
 				struct sk_buff *skb, int ring_offset);
-static void ultra32_block_output(struct device *dev, int count,
+static void ultra32_block_output(struct net_device *dev, int count,
 				 const unsigned char *buf,
 				 const int start_page);
-static int ultra32_close(struct device *dev);
+static int ultra32_close(struct net_device *dev);
 
 #define ULTRA32_CMDREG	0	/* Offset to ASIC command register. */
 #define	 ULTRA32_RESET	0x80	/* Board reset, in ULTRA32_CMDREG. */
@@ -103,7 +103,7 @@
 	following.
 */
 
-int __init ultra32_probe(struct device *dev)
+int __init ultra32_probe(struct net_device *dev)
 {
 	const char *ifmap[] = {"UTP No Link", "", "UTP/AUI", "UTP/BNC"};
 	int ioaddr, edge, media;
@@ -126,7 +126,7 @@
 	return ENODEV;
 }
 
-int __init ultra32_probe1(struct device *dev, int ioaddr)
+int __init ultra32_probe1(struct net_device *dev, int ioaddr)
 {
 	int i;
 	int checksum = 0;
@@ -240,7 +240,7 @@
 	return 0;
 }
 
-static int ultra32_open(struct device *dev)
+static int ultra32_open(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr - ULTRA32_NIC_OFFSET; /* ASIC addr */
 	int irq_flags = (inb(ioaddr + ULTRA32_CFG5) & 0x08) ? 0 : SA_SHIRQ;
@@ -261,7 +261,7 @@
 	return 0;
 }
 
-static int ultra32_close(struct device *dev)
+static int ultra32_close(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr - ULTRA32_NIC_OFFSET; /* CMDREG */
 
@@ -282,7 +282,7 @@
 	return 0;
 }
 
-static void ultra32_reset_8390(struct device *dev)
+static void ultra32_reset_8390(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr - ULTRA32_NIC_OFFSET; /* ASIC base addr */
 
@@ -302,7 +302,7 @@
    we don't need to be concerned with ring wrap as the header will be at
    the start of a page, so we optimize accordingly. */
 
-static void ultra32_get_8390_hdr(struct device *dev,
+static void ultra32_get_8390_hdr(struct net_device *dev,
 				 struct e8390_pkt_hdr *hdr,
 				 int ring_page)
 {
@@ -325,7 +325,7 @@
    packet spans an 8KB boundary. Note that the current 8KB segment is
    already set by the get_8390_hdr routine. */
 
-static void ultra32_block_input(struct device *dev,
+static void ultra32_block_input(struct net_device *dev,
 				int count,
 				struct sk_buff *skb,
 				int ring_offset)
@@ -353,7 +353,7 @@
 	}
 }
 
-static void ultra32_block_output(struct device *dev,
+static void ultra32_block_output(struct net_device *dev,
 				 int count,
 				 const unsigned char *buf,
 				 int start_page)
@@ -371,7 +371,7 @@
 #define MAX_ULTRA32_CARDS   4	/* Max number of Ultra cards per module */
 #define NAMELEN		    8	/* # of chars for storing dev->name */
 static char namelist[NAMELEN * MAX_ULTRA32_CARDS] = { 0, };
-static struct device dev_ultra[MAX_ULTRA32_CARDS] = {
+static struct net_device dev_ultra[MAX_ULTRA32_CARDS] = {
 	{
 		NULL,		/* assign a chunk of namelist[] below */
 		0, 0, 0, 0,
@@ -385,7 +385,7 @@
 	int this_dev, found = 0;
 
 	for (this_dev = 0; this_dev < MAX_ULTRA32_CARDS; this_dev++) {
-		struct device *dev = &dev_ultra[this_dev];
+		struct net_device *dev = &dev_ultra[this_dev];
 		dev->name = namelist+(NAMELEN*this_dev);
 		dev->init = ultra32_probe;
 		if (register_netdev(dev) != 0) {
@@ -407,7 +407,7 @@
 	int this_dev;
 
 	for (this_dev = 0; this_dev < MAX_ULTRA32_CARDS; this_dev++) {
-		struct device *dev = &dev_ultra[this_dev];
+		struct net_device *dev = &dev_ultra[this_dev];
 		if (dev->priv != NULL) {
 			int ioaddr = dev->base_addr - ULTRA32_NIC_OFFSET;
 			void *priv = dev->priv;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/smc9194.c linux/drivers/net/smc9194.c
--- v2.3.13/linux/drivers/net/smc9194.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/smc9194.c	Wed Aug 18 11:36:42 1999
@@ -208,43 +208,43 @@
  .
  . NB:This shouldn't be static since it is referred to externally.
 */
-int smc_init(struct device *dev);
+int smc_init(struct net_device *dev);
 
 /*
  . The kernel calls this function when someone wants to use the device,
  . typically 'ifconfig ethX up'.
 */
-static int smc_open(struct device *dev);
+static int smc_open(struct net_device *dev);
 
 /*
  . This is called by the kernel to send a packet out into the net.  it's
  . responsible for doing a best-effort send, but if it's simply not possible
  . to send it, the packet gets dropped.
 */
-static int smc_send_packet(struct sk_buff *skb, struct device *dev);
+static int smc_send_packet(struct sk_buff *skb, struct net_device *dev);
 
 /*
  . This is called by the kernel in response to 'ifconfig ethX down'.  It
  . is responsible for cleaning up everything that the open routine
  . does, and maybe putting the card into a powerdown state.
 */
-static int smc_close(struct device *dev);
+static int smc_close(struct net_device *dev);
 
 /*
  . This routine allows the proc file system to query the driver's
  . statistics.
 */
-static struct net_device_stats * smc_query_statistics( struct device *dev);
+static struct net_device_stats * smc_query_statistics( struct net_device *dev);
 
 /*
  . Finally, a call to set promiscuous mode ( for TCPDUMP and related
  . programs ) and multicast modes.
 */
 #ifdef SUPPORT_OLD_KERNEL
-static void smc_set_multicast_list(struct device *dev, int num_addrs,
+static void smc_set_multicast_list(struct net_device *dev, int num_addrs,
 				 void *addrs);
 #else
-static void smc_set_multicast_list(struct device *dev);
+static void smc_set_multicast_list(struct net_device *dev);
 #endif
 
 /*---------------------------------------------------------------
@@ -265,12 +265,12 @@
  . This is a separate procedure to handle the receipt of a packet, to
  . leave the interrupt code looking slightly cleaner
 */
-inline static void smc_rcv( struct device *dev );
+inline static void smc_rcv( struct net_device *dev );
 /*
  . This handles a TX interrupt, which is only called when an error
  . relating to a packet is sent.
 */
-inline static void smc_tx( struct device * dev );
+inline static void smc_tx( struct net_device * dev );
 
 /*
  ------------------------------------------------------------
@@ -292,7 +292,7 @@
  . of a device parameter.
  . It will give an error if it can't initialize the card.
 */
-static int smc_initcard( struct device *, int ioaddr );
+static int smc_initcard( struct net_device *, int ioaddr );
 
 /*
  . A rather simple routine to print out a packet for debugging purposes.
@@ -304,13 +304,13 @@
 #define tx_done(dev) 1
 
 /* this is called to actually send the packet to the chip */
-static void smc_hardware_send_packet( struct device * dev );
+static void smc_hardware_send_packet( struct net_device * dev );
 
 /* Since I am not sure if I will have enough room in the chip's ram
  . to store the packet, I call this routine, which either sends it
  . now, or generates an interrupt when the card is ready for the
  . packet */
-static int  smc_wait_to_send_packet( struct sk_buff * skb, struct device *dev );
+static int  smc_wait_to_send_packet( struct sk_buff * skb, struct net_device *dev );
 
 /* this does a soft reset on the device */
 static void smc_reset( int ioaddr );
@@ -337,7 +337,7 @@
 #endif
 
 #ifdef SUPPORT_OLD_KERNEL
-extern struct device *init_etherdev(struct device *dev, int sizeof_private,
+extern struct net_device *init_etherdev(struct net_device *dev, int sizeof_private,
  			unsigned long *mem_startp );
 #endif
 
@@ -529,7 +529,7 @@
 
 
 /*
- . Function: smc_wait_to_send_packet( struct sk_buff * skb, struct device * )
+ . Function: smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * )
  . Purpose:
  .    Attempt to allocate memory for a packet, if chip-memory is not
  .    available, then tell the card to generate an interrupt when it
@@ -544,7 +544,7 @@
  . o 	(NO): Enable interrupts and let the interrupt handler deal with it.
  . o	(YES):Send it now.
 */
-static int smc_wait_to_send_packet( struct sk_buff * skb, struct device * dev )
+static int smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * dev )
 {
 	struct smc_local *lp 	= (struct smc_local *)dev->priv;
 	unsigned short ioaddr 	= dev->base_addr;
@@ -621,7 +621,7 @@
 }
 
 /*
- . Function:  smc_hardware_send_packet(struct device * )
+ . Function:  smc_hardware_send_packet(struct net_device * )
  . Purpose:
  .	This sends the actual packet to the SMC9xxx chip.
  .
@@ -638,7 +638,7 @@
  .	Enable the transmit interrupt, so I know if it failed
  . 	Free the kernel data if I actually sent it.
 */
-static void smc_hardware_send_packet( struct device * dev )
+static void smc_hardware_send_packet( struct net_device * dev )
 {
 	struct smc_local *lp = (struct smc_local *)dev->priv;
 	byte	 		packet_no;
@@ -737,7 +737,7 @@
 
 /*-------------------------------------------------------------------------
  |
- | smc_init( struct device * dev )
+ | smc_init( struct net_device * dev )
  |   Input parameters:
  |	dev->base_addr == 0, try to find all possible locations
  |	dev->base_addr == 1, return failure code
@@ -750,7 +750,7 @@
  |
  ---------------------------------------------------------------------------
 */
-int __init smc_init(struct device *dev)
+int __init smc_init(struct net_device *dev)
 {
 	int i;
 	int base_addr = dev ? dev->base_addr : 0;
@@ -942,7 +942,7 @@
  . o  GRAB the region
  .-----------------------------------------------------------------
 */
-static int __init smc_initcard(struct device *dev, int ioaddr)
+static int __init smc_initcard(struct net_device *dev, int ioaddr)
 {
 	int i;
 
@@ -1165,7 +1165,7 @@
  * Set up everything, reset the card, etc ..
  *
  */
-static int smc_open(struct device *dev)
+static int smc_open(struct net_device *dev)
 {
 	int	ioaddr = dev->base_addr;
 
@@ -1220,7 +1220,7 @@
  . skeleton.c, from Becker.
  .--------------------------------------------------------
 */
-static int smc_send_packet(struct sk_buff *skb, struct device *dev)
+static int smc_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
 	if (dev->tbusy) {
 		/* If we get here, some higher level has decided we are broken.
@@ -1272,7 +1272,7 @@
 static void smc_interrupt(int irq, struct pt_regs * regs)
 #endif
 {
-	struct device *dev 	= dev_id;
+	struct net_device *dev 	= dev_id;
 	int ioaddr 		= dev->base_addr;
 	struct smc_local *lp 	= (struct smc_local *)dev->priv;
 
@@ -1414,7 +1414,7 @@
  . o otherwise, read in the packet
  --------------------------------------------------------------
 */
-static void smc_rcv(struct device *dev)
+static void smc_rcv(struct net_device *dev)
 {
 	struct smc_local *lp = (struct smc_local *)dev->priv;
 	int 	ioaddr = dev->base_addr;
@@ -1553,7 +1553,7 @@
  .	( resend?  Not really, since we don't want old packets around )
  .	Restore saved values
  ************************************************************************/
-static void smc_tx( struct device * dev )
+static void smc_tx( struct net_device * dev )
 {
 	int	ioaddr = dev->base_addr;
 	struct smc_local *lp = (struct smc_local *)dev->priv;
@@ -1614,7 +1614,7 @@
  . an 'ifconfig ethX down'
  .
  -----------------------------------------------------*/
-static int smc_close(struct device *dev)
+static int smc_close(struct net_device *dev)
 {
 	dev->tbusy = 1;
 	dev->start = 0;
@@ -1634,7 +1634,7 @@
  . Get the current statistics.
  . This may be called with the card open or closed.
  .-------------------------------------------------------------*/
-static struct net_device_stats* smc_query_statistics(struct device *dev) {
+static struct net_device_stats* smc_query_statistics(struct net_device *dev) {
 	struct smc_local *lp = (struct smc_local *)dev->priv;
 
 	return &lp->stats;
@@ -1649,10 +1649,10 @@
  . a select set of multicast packets
 */
 #ifdef SUPPORT_OLD_KERNEL
-static void smc_set_multicast_list( struct device * dev,
+static void smc_set_multicast_list( struct net_device * dev,
 			int num_addrs, void * addrs )
 #else
-static void smc_set_multicast_list(struct device *dev)
+static void smc_set_multicast_list(struct net_device *dev)
 #endif
 {
 	short ioaddr = dev->base_addr;
@@ -1725,7 +1725,7 @@
 #ifdef MODULE
 
 static char devicename[9] = { 0, };
-static struct device devSMC9194 = {
+static struct net_device devSMC9194 = {
 	devicename, /* device name is inserted by linux/drivers/net/net_init.c */
 	0, 0, 0, 0,
 	0, 0,  /* I/O address, IRQ */
diff -u --recursive --new-file v2.3.13/linux/drivers/net/sonic.c linux/drivers/net/sonic.c
--- v2.3.13/linux/drivers/net/sonic.c	Wed Jun 30 13:38:20 1999
+++ linux/drivers/net/sonic.c	Wed Aug 18 11:36:42 1999
@@ -26,7 +26,7 @@
  *  registers that "should" only need to be set once at boot, so that
  *  there is non-reboot way to recover if something goes wrong.
  */
-static int sonic_open(struct device *dev)
+static int sonic_open(struct net_device *dev)
 {
     if (sonic_debug > 2)
       printk("sonic_open: initializing sonic driver.\n");
@@ -67,7 +67,7 @@
  * Close the SONIC device
  */
 static int
-sonic_close(struct device *dev)
+sonic_close(struct net_device *dev)
 {
     unsigned int base_addr = dev->base_addr;
     
@@ -93,7 +93,7 @@
 /*
  * transmit packet
  */
-static int sonic_send_packet(struct sk_buff *skb, struct device *dev)
+static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
     struct sonic_local *lp = (struct sonic_local *)dev->priv;
     unsigned int base_addr = dev->base_addr;
@@ -183,7 +183,7 @@
 static void
 sonic_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
-    struct device *dev = (struct device *)dev_id;
+    struct net_device *dev = (struct net_device *)dev_id;
     unsigned int base_addr = dev->base_addr;
     struct sonic_local *lp;
     int status;
@@ -301,7 +301,7 @@
  * We have a good packet(s), get it/them out of the buffers.
  */
 static void
-sonic_rx(struct device *dev)
+sonic_rx(struct net_device *dev)
 {
     unsigned int base_addr = dev->base_addr;
     struct sonic_local *lp = (struct sonic_local *)dev->priv;
@@ -378,7 +378,7 @@
  * This may be called with the device open or closed.
  */
 static struct enet_statistics *
-sonic_get_stats(struct device *dev)
+sonic_get_stats(struct net_device *dev)
 {
     struct sonic_local *lp = (struct sonic_local *)dev->priv;
     unsigned int base_addr = dev->base_addr;
@@ -399,7 +399,7 @@
  * Set or clear the multicast filter for this adaptor.
  */
 static void
-sonic_multicast_list(struct device *dev)
+sonic_multicast_list(struct net_device *dev)
 {
     struct sonic_local *lp = (struct sonic_local *)dev->priv;    
     unsigned int base_addr = dev->base_addr;    
@@ -445,7 +445,7 @@
 /*
  * Initialize the SONIC ethernet controller.
  */
-static int sonic_init(struct device *dev)
+static int sonic_init(struct net_device *dev)
 {
     unsigned int base_addr = dev->base_addr;
     unsigned int cmd;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/sonic.h linux/drivers/net/sonic.h
--- v2.3.13/linux/drivers/net/sonic.h	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/sonic.h	Wed Aug 18 11:36:45 1999
@@ -17,6 +17,8 @@
 #ifndef SONIC_H
 #define SONIC_H
 
+#include <linux/config.h>
+
 /*
  * SONIC register offsets
  */
@@ -463,14 +465,14 @@
 
 /* Index to functions, as function prototypes. */
 
-static int sonic_open(struct device *dev);
-static int sonic_send_packet(struct sk_buff *skb, struct device *dev);
+static int sonic_open(struct net_device *dev);
+static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev);
 static void sonic_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void sonic_rx(struct device *dev);
-static int sonic_close(struct device *dev);
-static struct enet_statistics *sonic_get_stats(struct device *dev);
-static void sonic_multicast_list(struct device *dev);
-static int sonic_init(struct device *dev);
+static void sonic_rx(struct net_device *dev);
+static int sonic_close(struct net_device *dev);
+static struct enet_statistics *sonic_get_stats(struct net_device *dev);
+static void sonic_multicast_list(struct net_device *dev);
+static int sonic_init(struct net_device *dev);
 
 static const char *version =
 	"sonic.c:v0.92 20.9.98 tsbogend@alpha.franken.de\n";
diff -u --recursive --new-file v2.3.13/linux/drivers/net/strip.c linux/drivers/net/strip.c
--- v2.3.13/linux/drivers/net/strip.c	Tue May 25 13:06:34 1999
+++ linux/drivers/net/strip.c	Wed Aug 18 11:36:43 1999
@@ -311,7 +311,7 @@
 
     struct tty_struct *tty;			/* ptr to TTY structure		*/
     char8              if_name;			/* Dynamically generated name	*/
-    struct device      dev;			/* Our device structure		*/
+    struct net_device      dev;			/* Our device structure		*/
 
     /*
      * Neighbour radio records
@@ -505,7 +505,7 @@
     restore_flags(x);
 }
 
-static int arp_query(unsigned char *haddr, u32 paddr, struct device * dev)
+static int arp_query(unsigned char *haddr, u32 paddr, struct net_device * dev)
 {
     struct neighbour *neighbor_entry;
 
@@ -932,7 +932,7 @@
 
 static int allocate_buffers(struct strip *strip_info)
 {
-    struct device *dev = &strip_info->dev;
+    struct net_device *dev = &strip_info->dev;
     int sx_size    = MAX(STRIP_ENCAP_SIZE(MAX_RECV_MTU), 4096);
     int tx_size    = STRIP_ENCAP_SIZE(dev->mtu) + MaxCommandStringLength;
     __u8 *r = kmalloc(MAX_RECV_MTU, GFP_ATOMIC);
@@ -963,7 +963,7 @@
 static void strip_changedmtu(struct strip *strip_info)
 {
     int old_mtu           = strip_info->mtu;
-    struct device *dev    = &strip_info->dev;
+    struct net_device *dev    = &strip_info->dev;
     unsigned char *orbuff = strip_info->rx_buff;
     unsigned char *osbuff = strip_info->sx_buff;
     unsigned char *otbuff = strip_info->tx_buff;
@@ -1636,7 +1636,7 @@
 }
 
 /* Encapsulate a datagram and kick it into a TTY queue. */
-static int strip_xmit(struct sk_buff *skb, struct device *dev)
+static int strip_xmit(struct sk_buff *skb, struct net_device *dev)
 {
     struct strip *strip_info = (struct strip *)(dev->priv);
 
@@ -1693,7 +1693,7 @@
 
 static void strip_IdleTask(unsigned long parameter)
 {
-    strip_xmit(NULL, (struct device *)parameter);
+    strip_xmit(NULL, (struct net_device *)parameter);
 }
 
 /*
@@ -1707,7 +1707,7 @@
  *                 rebuild_header later to fill in the address)
  */
 
-static int strip_header(struct sk_buff *skb, struct device *dev,
+static int strip_header(struct sk_buff *skb, struct net_device *dev,
         unsigned short type, void *daddr, void *saddr, unsigned len)
 {
     struct strip *strip_info = (struct strip *)(dev->priv);
@@ -2018,7 +2018,7 @@
     if (ptr+16 > end) RecvErr("Bad Info Msg:", strip_info);
 }
 
-static struct device *get_strip_dev(struct strip *strip_info)
+static struct net_device *get_strip_dev(struct strip *strip_info)
 {
     /* If our hardware address is *manually set* to zero, and we know our */
     /* real radio hardware address, try to find another strip device that has been */
@@ -2027,7 +2027,7 @@
         !memcmp(strip_info->dev.dev_addr, zero_address.c, sizeof(zero_address)) &&
         memcmp(&strip_info->true_dev_addr, zero_address.c, sizeof(zero_address)))
     {
-        struct device *dev;
+        struct net_device *dev;
 	read_lock_bh(&dev_base_lock);
 	dev = dev_base;
         while (dev)
@@ -2414,7 +2414,7 @@
     return 0;
 }
 
-static int dev_set_mac_address(struct device *dev, void *addr)
+static int dev_set_mac_address(struct net_device *dev, void *addr)
 {
     struct strip *strip_info = (struct strip *)(dev->priv);
     struct sockaddr *sa = addr;
@@ -2423,7 +2423,7 @@
     return 0;
 }
 
-static struct enet_statistics *strip_get_stats(struct device *dev)
+static struct enet_statistics *strip_get_stats(struct net_device *dev)
 {
     static struct enet_statistics stats;
     struct strip *strip_info = (struct strip *)(dev->priv);
@@ -2468,7 +2468,7 @@
 
 /* Open the low-level part of the STRIP channel. Easy! */
 
-static int strip_open_low(struct device *dev)
+static int strip_open_low(struct net_device *dev)
 {
     struct strip *strip_info = (struct strip *)(dev->priv);
     struct in_device *in_dev = dev->ip_ptr;
@@ -2509,7 +2509,7 @@
  * Close the low-level part of the STRIP channel. Easy!
  */
 
-static int strip_close_low(struct device *dev)
+static int strip_close_low(struct net_device *dev)
 {
     struct strip *strip_info = (struct strip *)(dev->priv);
 
@@ -2546,7 +2546,7 @@
  * (dynamically assigned) device is registered
  */
 
-static int strip_dev_init(struct device *dev)
+static int strip_dev_init(struct net_device *dev)
 {
     /*
      * Finish setting up the DEVICE info.
@@ -2821,7 +2821,7 @@
 #ifdef MODULE
 static
 #endif
-int strip_init_ctrl_dev(struct device *dummy)
+int strip_init_ctrl_dev(struct net_device *dummy)
 {
     static struct tty_ldisc strip_ldisc;
     int status;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/sunbmac.c linux/drivers/net/sunbmac.c
--- v2.3.13/linux/drivers/net/sunbmac.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/sunbmac.c	Wed Aug 18 11:36:43 1999
@@ -199,7 +199,7 @@
 static void bigmac_init_rings(struct bigmac *bp, int from_irq)
 {
 	struct bmac_init_block *bb = bp->bmac_block;
-	struct device *dev = bp->dev;
+	struct net_device *dev = bp->dev;
 	int i, gfp_flags = GFP_KERNEL;
 
 	if(from_irq || in_interrupt())
@@ -1014,7 +1014,7 @@
 }
 #endif
 
-static int bigmac_open(struct device *dev)
+static int bigmac_open(struct net_device *dev)
 {
 	struct bigmac *bp = (struct bigmac *) dev->priv;
 	int res;
@@ -1041,7 +1041,7 @@
 	return res;
 }
 
-static int bigmac_close(struct device *dev)
+static int bigmac_close(struct net_device *dev)
 {
 	struct bigmac *bp = (struct bigmac *) dev->priv;
 
@@ -1057,7 +1057,7 @@
 }
 
 /* Put a packet on the wire. */
-static int bigmac_start_xmit(struct sk_buff *skb, struct device *dev)
+static int bigmac_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct bigmac *bp = (struct bigmac *) dev->priv;
 	int len, entry;
@@ -1123,7 +1123,7 @@
 }
 
 #ifndef __sparc_v9__
-static int sun4c_bigmac_start_xmit(struct sk_buff *skb, struct device *dev)
+static int sun4c_bigmac_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct bigmac *bp = (struct bigmac *) dev->priv;
 	struct bigmac_buffers *bbufs = bp->sun4c_buffers;
@@ -1182,7 +1182,7 @@
 }
 #endif
 
-static struct enet_statistics *bigmac_get_stats(struct device *dev)
+static struct enet_statistics *bigmac_get_stats(struct net_device *dev)
 {
 	struct bigmac *bp = (struct bigmac *) dev->priv;
 
@@ -1193,7 +1193,7 @@
 #define CRC_POLYNOMIAL_BE 0x04c11db7UL  /* Ethernet CRC, big endian */
 #define CRC_POLYNOMIAL_LE 0xedb88320UL  /* Ethernet CRC, little endian */
 
-static void bigmac_set_multicast(struct device *dev)
+static void bigmac_set_multicast(struct net_device *dev)
 {
 	struct bigmac *bp = (struct bigmac *) dev->priv;
 	struct BIG_MAC_regs *bregs = bp->bregs;
@@ -1253,7 +1253,7 @@
 	bregs->rx_cfg |= BIGMAC_RXCFG_ENABLE;
 }
 
-static int __init bigmac_ether_init(struct device *dev, struct linux_sbus_device *qec_sdev)
+static int __init bigmac_ether_init(struct net_device *dev, struct linux_sbus_device *qec_sdev)
 {
 	static unsigned version_printed = 0;
 	struct bigmac *bp = 0;
@@ -1492,7 +1492,7 @@
 	return res;	/* Return error code. */
 }
 
-int __init bigmac_probe(struct device *dev)
+int __init bigmac_probe(struct net_device *dev)
 {
 	struct linux_sbus *bus;
 	struct linux_sbus_device *sdev = 0;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/sunbmac.h linux/drivers/net/sunbmac.h
--- v2.3.13/linux/drivers/net/sunbmac.h	Mon Mar 15 16:11:30 1999
+++ linux/drivers/net/sunbmac.h	Wed Aug 18 11:36:45 1999
@@ -356,7 +356,7 @@
 	struct enet_statistics		enet_stats;
 	struct linux_sbus_device	*qec_sbus_dev;
 	struct linux_sbus_device	*bigmac_sbus_dev;
-	struct device			*dev;
+	struct net_device			*dev;
 	struct bigmac			*next_module;
 };
 
diff -u --recursive --new-file v2.3.13/linux/drivers/net/sunhme.c linux/drivers/net/sunhme.c
--- v2.3.13/linux/drivers/net/sunhme.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/sunhme.c	Wed Aug 18 11:36:43 1999
@@ -1046,7 +1046,7 @@
 static void happy_meal_init_rings(struct happy_meal *hp, int from_irq)
 {
 	struct hmeal_init_block *hb = hp->happy_block;
-	struct device *dev = hp->dev;
+	struct net_device *dev = hp->dev;
 	int i, gfp_flags = GFP_KERNEL;
 
 	if(from_irq || in_interrupt())
@@ -1841,7 +1841,7 @@
  * ring when we cannot get a new skb and give them all back to the happy meal,
  * maybe things will be "happier" now.
  */
-static inline void happy_meal_rx(struct happy_meal *hp, struct device *dev,
+static inline void happy_meal_rx(struct happy_meal *hp, struct net_device *dev,
 				 struct hmeal_gregs *gregs)
 {
 	struct happy_meal_rxd *rxbase = &hp->happy_block->happy_meal_rxd[0];
@@ -1947,7 +1947,7 @@
 }
 
 #ifdef CONFIG_PCI
-static inline void pci_happy_meal_rx(struct happy_meal *hp, struct device *dev,
+static inline void pci_happy_meal_rx(struct happy_meal *hp, struct net_device *dev,
 				     struct hmeal_gregs *gregs)
 {
 	struct happy_meal_rxd *rxbase = &hp->happy_block->happy_meal_rxd[0];
@@ -2067,7 +2067,7 @@
 #endif
 
 #ifndef __sparc_v9__
-static inline void sun4c_happy_meal_rx(struct happy_meal *hp, struct device *dev,
+static inline void sun4c_happy_meal_rx(struct happy_meal *hp, struct net_device *dev,
 				       struct hmeal_gregs *gregs)
 {
 	struct happy_meal_rxd *rxbase = &hp->happy_block->happy_meal_rxd[0];
@@ -2130,7 +2130,7 @@
 	RXD((">"));
 }
 
-static inline void sun4d_happy_meal_rx(struct happy_meal *hp, struct device *dev,
+static inline void sun4d_happy_meal_rx(struct happy_meal *hp, struct net_device *dev,
 				       struct hmeal_gregs *gregs)
 {
 	struct happy_meal_rxd *rxbase = &hp->happy_block->happy_meal_rxd[0];
@@ -2242,7 +2242,7 @@
 
 static void happy_meal_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev            = (struct device *) dev_id;
+	struct net_device *dev            = (struct net_device *) dev_id;
 	struct happy_meal *hp         = (struct happy_meal *) dev->priv;
 	struct hmeal_gregs *gregs     = hp->gregs;
 	struct hmeal_tcvregs *tregs   = hp->tcvregs;
@@ -2287,7 +2287,7 @@
 #ifdef CONFIG_PCI
 static void pci_happy_meal_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev            = (struct device *) dev_id;
+	struct net_device *dev            = (struct net_device *) dev_id;
 	struct happy_meal *hp         = (struct happy_meal *) dev->priv;
 	struct hmeal_gregs *gregs     = hp->gregs;
 	struct hmeal_tcvregs *tregs   = hp->tcvregs;
@@ -2333,7 +2333,7 @@
 #ifndef __sparc_v9__
 static void sun4c_happy_meal_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev            = (struct device *) dev_id;
+	struct net_device *dev            = (struct net_device *) dev_id;
 	struct happy_meal *hp         = (struct happy_meal *) dev->priv;
 	struct hmeal_gregs *gregs     = hp->gregs;
 	struct hmeal_tcvregs *tregs   = hp->tcvregs;
@@ -2377,7 +2377,7 @@
 
 static void sun4d_happy_meal_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev            = (struct device *) dev_id;
+	struct net_device *dev            = (struct net_device *) dev_id;
 	struct happy_meal *hp         = (struct happy_meal *) dev->priv;
 	struct hmeal_gregs *gregs     = hp->gregs;
 	struct hmeal_tcvregs *tregs   = hp->tcvregs;
@@ -2426,7 +2426,7 @@
 	int i;
 
 	for(i = 0; i < 4; i++) {
-		struct device *hdev = qp->happy_meals[i];
+		struct net_device *hdev = qp->happy_meals[i];
 		struct happy_meal *hp = (struct happy_meal *) hdev->priv;
 		volatile u32 *sreg = qp->irq_status[i];
 
@@ -2439,7 +2439,7 @@
 	}
 }
 
-static int happy_meal_open(struct device *dev)
+static int happy_meal_open(struct net_device *dev)
 {
 	struct happy_meal *hp = (struct happy_meal *) dev->priv;
 	int res;
@@ -2499,7 +2499,7 @@
 	return res;
 }
 
-static int happy_meal_close(struct device *dev)
+static int happy_meal_close(struct net_device *dev)
 {
 	struct happy_meal *hp = (struct happy_meal *) dev->priv;
 
@@ -2530,7 +2530,7 @@
 #define SXD(x)
 #endif
 
-static int happy_meal_start_xmit(struct sk_buff *skb, struct device *dev)
+static int happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct happy_meal *hp = (struct happy_meal *) dev->priv;
 	int len, entry;
@@ -2593,7 +2593,7 @@
 }
 
 #ifdef CONFIG_PCI
-static int pci_happy_meal_start_xmit(struct sk_buff *skb, struct device *dev)
+static int pci_happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct happy_meal *hp = (struct happy_meal *) dev->priv;
 	int len, entry;
@@ -2647,7 +2647,7 @@
 #endif
 
 #ifndef __sparc_v9__
-static int sun4c_happy_meal_start_xmit(struct sk_buff *skb, struct device *dev)
+static int sun4c_happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct happy_meal *hp = (struct happy_meal *) dev->priv;
 	struct hmeal_buffers *hbufs = hp->sun4c_buffers;
@@ -2703,7 +2703,7 @@
 	return 0;
 }
 
-static int sun4d_happy_meal_start_xmit(struct sk_buff *skb, struct device *dev)
+static int sun4d_happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct happy_meal *hp = (struct happy_meal *) dev->priv;
 	int len, entry;
@@ -2756,7 +2756,7 @@
 }
 #endif
 
-static struct net_device_stats *happy_meal_get_stats(struct device *dev)
+static struct net_device_stats *happy_meal_get_stats(struct net_device *dev)
 {
 	struct happy_meal *hp = (struct happy_meal *) dev->priv;
 
@@ -2764,7 +2764,7 @@
 	return &hp->net_stats;
 }
 
-static void happy_meal_set_multicast(struct device *dev)
+static void happy_meal_set_multicast(struct net_device *dev)
 {
 	struct happy_meal *hp = (struct happy_meal *) dev->priv;
 	struct hmeal_bigmacregs *bregs = hp->bigmacregs;
@@ -2822,7 +2822,7 @@
 }
 
 /* Ethtool support... */
-static int happy_meal_ioctl(struct device *dev,
+static int happy_meal_ioctl(struct net_device *dev,
 			    struct ifreq *rq, int cmd)
 {
 	struct happy_meal *hp = (struct happy_meal *) dev->priv;
@@ -3061,7 +3061,7 @@
 
 static unsigned hme_version_printed = 0;
 
-static int __init happy_meal_ether_init(struct device *dev, struct linux_sbus_device *sdev, int is_qfe)
+static int __init happy_meal_ether_init(struct net_device *dev, struct linux_sbus_device *sdev, int is_qfe)
 {
 	struct quattro *qp = NULL;
 	struct happy_meal *hp;
@@ -3250,7 +3250,7 @@
 }
 
 #ifdef CONFIG_PCI
-static int __init happy_meal_pci_init(struct device *dev, struct pci_dev *pdev)
+static int __init happy_meal_pci_init(struct net_device *dev, struct pci_dev *pdev)
 {
 	struct quattro *qp = NULL;
 	struct pcidev_cookie *pcp;
@@ -3423,7 +3423,7 @@
 }
 #endif
 
-int __init happy_meal_probe(struct device *dev)
+int __init happy_meal_probe(struct net_device *dev)
 {
 	struct linux_sbus *bus;
 	struct linux_sbus_device *sdev = 0;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/sunhme.h linux/drivers/net/sunhme.h
--- v2.3.13/linux/drivers/net/sunhme.h	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/sunhme.h	Wed Aug 18 11:36:45 1999
@@ -560,7 +560,7 @@
 #ifdef CONFIG_PCI
 	struct pci_dev		 *happy_pci_dev;
 #endif
-	struct device            *dev;            /* Backpointer                       */
+	struct net_device            *dev;            /* Backpointer                       */
 	struct quattro		 *qfe_parent;	  /* For Quattro cards                 */
 	int			  qfe_ent;	  /* Which instance on quattro         */
 	struct happy_meal        *next_module;
@@ -587,7 +587,7 @@
 /* Support for QFE/Quattro cards. */
 struct quattro {
 	volatile u32		 *irq_status[4];
-	struct device		 *happy_meals[4];
+	struct net_device		 *happy_meals[4];
 	void (*handler)(int, void *, struct pt_regs *);
 
 	struct linux_sbus_device *quattro_sbus_dev;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/sunlance.c linux/drivers/net/sunlance.c
--- v2.3.13/linux/drivers/net/sunlance.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/sunlance.c	Wed Aug 18 11:36:43 1999
@@ -252,7 +252,7 @@
 	unsigned short busmaster_regval;
 	unsigned short pio_buffer;
 
-	struct device		 *dev;		  /* Backpointer	*/
+	struct net_device		 *dev;		  /* Backpointer	*/
 	struct lance_private	 *next_module;
 	struct linux_sbus        *sbus;
 	struct timer_list         multicast_timer;
@@ -311,7 +311,7 @@
 
 /* Setup the Lance Rx and Tx rings */
 /* Sets dev->tbusy */
-static void lance_init_ring (struct device *dev)
+static void lance_init_ring (struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_init_block *ib = lp->init_block;
@@ -444,7 +444,7 @@
 	return 0;
 }
 
-static int lance_rx (struct device *dev)
+static int lance_rx (struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_init_block *ib = lp->init_block;
@@ -518,7 +518,7 @@
 	return 0;
 }
 
-static int lance_tx (struct device *dev)
+static int lance_tx (struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_init_block *ib = lp->init_block;
@@ -599,7 +599,7 @@
 
 static void lance_interrupt (int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev = (struct device *)dev_id;
+	struct net_device *dev = (struct net_device *)dev_id;
 	struct lance_private *lp = (struct lance_private *)dev->priv;
 	volatile struct lance_regs *ll = lp->ll;
 	int csr0;
@@ -660,9 +660,9 @@
 	dev->interrupt = 0;
 }
 
-struct device *last_dev = 0;
+struct net_device *last_dev = 0;
 
-static int lance_open (struct device *dev)
+static int lance_open (struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *)dev->priv;
 	volatile struct lance_regs *ll = lp->ll;
@@ -744,7 +744,7 @@
 	return status;
 }
 
-static int lance_close (struct device *dev)
+static int lance_close (struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_regs *ll = lp->ll;
@@ -762,7 +762,7 @@
 	return 0;
 }
 
-static inline int lance_reset (struct device *dev)
+static inline int lance_reset (struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *)dev->priv;
 	volatile struct lance_regs *ll = lp->ll;
@@ -793,7 +793,7 @@
 	return status;
 }
 
-static int lance_start_xmit (struct sk_buff *skb, struct device *dev)
+static int lance_start_xmit (struct sk_buff *skb, struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *)dev->priv;
 	volatile struct lance_regs *ll = lp->ll;
@@ -861,7 +861,7 @@
 	return 0;
 }
 
-static struct net_device_stats *lance_get_stats (struct device *dev)
+static struct net_device_stats *lance_get_stats (struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 
@@ -869,7 +869,7 @@
 }
 
 /* taken from the depca driver */
-static void lance_load_multicast (struct device *dev)
+static void lance_load_multicast (struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_init_block *ib = lp->init_block;
@@ -915,7 +915,7 @@
 	}
 }
 
-static void lance_set_multicast (struct device *dev)
+static void lance_set_multicast (struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_init_block *ib = lp->init_block;
@@ -966,7 +966,7 @@
 }
 
 static int __init 
-sparc_lance_init (struct device *dev, struct linux_sbus_device *sdev,
+sparc_lance_init (struct net_device *dev, struct linux_sbus_device *sdev,
 		  struct Linux_SBus_DMA *ledma,
 		  struct linux_sbus_device *lebuffer)
 {
@@ -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 device *dev)
+int __init sparc_lance_probe (struct net_device *dev)
 {
 	static struct linux_sbus_device sdev;
 	static int called = 0;
@@ -1179,7 +1179,7 @@
 #else /* !CONFIG_SUN4 */
 
 /* Find all the lance cards on the system and initialize them */
-int __init sparc_lance_probe (struct device *dev)
+int __init sparc_lance_probe (struct net_device *dev)
 {
 	struct linux_sbus *bus;
 	struct linux_sbus_device *sdev = 0;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/sunqe.c linux/drivers/net/sunqe.c
--- v2.3.13/linux/drivers/net/sunqe.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/sunqe.c	Wed Aug 18 11:36:43 1999
@@ -131,7 +131,7 @@
 static void qe_init_rings(struct sunqe *qep, int from_irq)
 {
 	struct qe_init_block *qb = qep->qe_block;
-	struct device *dev = qep->dev;
+	struct net_device *dev = qep->dev;
 	int i, gfp_flags = GFP_KERNEL;
 
 	if(from_irq || in_interrupt())
@@ -281,7 +281,7 @@
  */
 static int qe_is_bolixed(struct sunqe *qep, unsigned int qe_status)
 {
-	struct device *dev = qep->dev;
+	struct net_device *dev = qep->dev;
 	int mace_hwbug_workaround = 0;
 
 	if(qe_status & CREG_STAT_EDEFER) {
@@ -631,7 +631,7 @@
 	while(channel < 4) {
 		if(qec_status & 0xf) {
 			struct sunqe *qep = qecp->qes[channel];
-			struct device *dev = qep->dev;
+			struct net_device *dev = qep->dev;
 			unsigned int qe_status;
 
 			dev->interrupt = 1;
@@ -671,7 +671,7 @@
 	while(channel < 4) {
 		if(qec_status & 0xf) {
 			struct sunqe *qep = qecp->qes[channel];
-			struct device *dev = qep->dev;
+			struct net_device *dev = qep->dev;
 			unsigned int qe_status;
 
 			dev->interrupt = 1;
@@ -700,7 +700,7 @@
 	}
 }
 
-static int qe_open(struct device *dev)
+static int qe_open(struct net_device *dev)
 {
 	struct sunqe *qep = (struct sunqe *) dev->priv;
 	int res;
@@ -712,7 +712,7 @@
 	return res;
 }
 
-static int qe_close(struct device *dev)
+static int qe_close(struct net_device *dev)
 {
 	struct sunqe *qep = (struct sunqe *) dev->priv;
 
@@ -723,7 +723,7 @@
 }
 
 /* Get a packet queued to go onto the wire. */
-static int qe_start_xmit(struct sk_buff *skb, struct device *dev)
+static int qe_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct sunqe *qep = (struct sunqe *) dev->priv;
 	int len, entry;
@@ -774,7 +774,7 @@
 	return 0;
 }
 
-static int sun4c_qe_start_xmit(struct sk_buff *skb, struct device *dev)
+static int sun4c_qe_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct sunqe *qep = (struct sunqe *) dev->priv;
 	struct sunqe_buffers *qbufs = qep->sun4c_buffers;
@@ -823,7 +823,7 @@
 	return 0;
 }
 
-static struct net_device_stats *qe_get_stats(struct device *dev)
+static struct net_device_stats *qe_get_stats(struct net_device *dev)
 {
 	struct sunqe *qep = (struct sunqe *) dev->priv;
 
@@ -833,7 +833,7 @@
 #define CRC_POLYNOMIAL_BE 0x04c11db7UL  /* Ethernet CRC, big endian */
 #define CRC_POLYNOMIAL_LE 0xedb88320UL  /* Ethernet CRC, little endian */
 
-static void qe_set_multicast(struct device *dev)
+static void qe_set_multicast(struct net_device *dev)
 {
 	struct sunqe *qep = (struct sunqe *) dev->priv;
 	struct dev_mc_list *dmi = dev->mc_list;
@@ -926,10 +926,10 @@
 }
 
 /* Four QE's per QEC card. */
-static inline int qec_ether_init(struct device *dev, struct linux_sbus_device *sdev)
+static inline int qec_ether_init(struct net_device *dev, struct linux_sbus_device *sdev)
 {
 	static unsigned version_printed = 0;
-	struct device *qe_devs[4];
+	struct net_device *qe_devs[4];
 	struct sunqe *qeps[4];
 	struct linux_sbus_device *qesdevs[4];
 	struct sunqec *qecp;
@@ -1173,7 +1173,7 @@
 	return res;
 }
 
-int __init qec_probe(struct device *dev)
+int __init qec_probe(struct net_device *dev)
 {
 	struct linux_sbus *bus;
 	struct linux_sbus_device *sdev = 0;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/sunqe.h linux/drivers/net/sunqe.h
--- v2.3.13/linux/drivers/net/sunqe.h	Fri May  8 00:20:48 1998
+++ linux/drivers/net/sunqe.h	Wed Aug 18 11:36:45 1999
@@ -370,7 +370,7 @@
 
 	struct net_device_stats   net_stats;     /* Statistical counters               */
 	struct linux_sbus_device  *qe_sbusdev;   /* QE's SBUS device struct            */
-	struct device             *dev;          /* QE's netdevice struct              */
+	struct net_device             *dev;          /* QE's netdevice struct              */
 	int                        channel;      /* Who am I?                          */
 };
 
diff -u --recursive --new-file v2.3.13/linux/drivers/net/syncppp.c linux/drivers/net/syncppp.c
--- v2.3.13/linux/drivers/net/syncppp.c	Fri Apr 16 13:58:46 1999
+++ linux/drivers/net/syncppp.c	Wed Aug 18 11:36:43 1999
@@ -148,7 +148,7 @@
  *	Interface down stub
  */	
 
-static void if_down(struct device *dev)
+static void if_down(struct net_device *dev)
 {
 	;
 }
@@ -183,7 +183,7 @@
  * Process the received packet.
  */
  
-void sppp_input (struct device *dev, struct sk_buff *skb)
+void sppp_input (struct net_device *dev, struct sk_buff *skb)
 {
 	struct ppp_header *h;
 	struct sppp *sp = &((struct ppp_device *)dev)->sppp;
@@ -312,7 +312,7 @@
  *	Handle transmit packets.
  */
  
-static int sppp_hard_header(struct sk_buff *skb, struct device *dev, __u16 type,
+static int sppp_hard_header(struct sk_buff *skb, struct net_device *dev, __u16 type,
 		void *daddr, void *saddr, unsigned int len)
 {
 	struct sppp *sp = &((struct ppp_device *)dev)->sppp;
@@ -363,7 +363,7 @@
 
 	for (sp=spppq; sp; sp=sp->pp_next) 
 	{
-		struct device *dev = sp->pp_if;
+		struct net_device *dev = sp->pp_if;
 
 		/* Keepalive mode disabled or channel down? */
 		if (! (sp->pp_flags & PP_KEEPALIVE) ||
@@ -413,7 +413,7 @@
 static void sppp_lcp_input (struct sppp *sp, struct sk_buff *skb)
 {
 	struct lcp_header *h;
-	struct device *dev = sp->pp_if;
+	struct net_device *dev = sp->pp_if;
 	int len = skb->len;
 	u8 *p, opt[6];
 	u32 rmagic;
@@ -648,7 +648,7 @@
 static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb)
 {
 	struct cisco_packet *h;
-	struct device *dev = sp->pp_if;
+	struct net_device *dev = sp->pp_if;
 
 	if (skb->len != CISCO_PACKET_LEN && skb->len != CISCO_BIG_PACKET_LEN) {
 		if (sp->pp_flags & PP_DEBUG)
@@ -736,7 +736,7 @@
 	struct ppp_header *h;
 	struct lcp_header *lh;
 	struct sk_buff *skb;
-	struct device *dev = sp->pp_if;
+	struct net_device *dev = sp->pp_if;
 
 	skb=alloc_skb(dev->hard_header_len+PPP_HEADER_LEN+LCP_HEADER_LEN+len,
 		GFP_ATOMIC);
@@ -785,7 +785,7 @@
 	struct ppp_header *h;
 	struct cisco_packet *ch;
 	struct sk_buff *skb;
-	struct device *dev = sp->pp_if;
+	struct net_device *dev = sp->pp_if;
 	u32 t = jiffies * 1000/HZ;
 
 	skb=alloc_skb(dev->hard_header_len+PPP_HEADER_LEN+CISCO_PACKET_LEN,
@@ -819,7 +819,7 @@
 }
 
 
-int sppp_close (struct device *dev)
+int sppp_close (struct net_device *dev)
 {
 	struct sppp *sp = &((struct ppp_device *)dev)->sppp;
 	dev->flags &= ~IFF_RUNNING;
@@ -832,7 +832,7 @@
 EXPORT_SYMBOL(sppp_close);
 
 
-int sppp_open (struct device *dev)
+int sppp_open (struct net_device *dev)
 {
 	struct sppp *sp = &((struct ppp_device *)dev)->sppp;
 	sppp_close(dev);
@@ -844,7 +844,7 @@
 
 EXPORT_SYMBOL(sppp_open);
 
-int sppp_reopen (struct device *dev)
+int sppp_reopen (struct net_device *dev)
 {
 	struct sppp *sp = &((struct ppp_device *)dev)->sppp;
 	sppp_close(dev);
@@ -863,7 +863,7 @@
 
 EXPORT_SYMBOL(sppp_reopen);
 
-int sppp_change_mtu(struct device *dev, int new_mtu)
+int sppp_change_mtu(struct net_device *dev, int new_mtu)
 {
 	if(new_mtu<128||new_mtu>PPP_MTU||(dev->flags&IFF_UP))
 		return -EINVAL;
@@ -873,7 +873,7 @@
 
 EXPORT_SYMBOL(sppp_change_mtu);
 
-int sppp_do_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
+int sppp_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	struct sppp *sp = &((struct ppp_device *)dev)->sppp;
 
@@ -908,7 +908,7 @@
 
 void sppp_attach(struct ppp_device *pd)
 {
-	struct device *dev=&pd->dev;
+	struct net_device *dev=&pd->dev;
 	struct sppp *sp = &pd->sppp;
 	
 	/* Initialize keepalive handler. */
@@ -963,7 +963,7 @@
 
 EXPORT_SYMBOL(sppp_attach);
 
-void sppp_detach (struct device *dev)
+void sppp_detach (struct net_device *dev)
 {
 	struct sppp **q, *p, *sp = &((struct ppp_device *)dev)->sppp;
 
@@ -1039,7 +1039,7 @@
 static void sppp_ipcp_input (struct sppp *sp, struct sk_buff *skb)
 {
 	struct lcp_header *h;
-	struct device *dev = sp->pp_if;
+	struct net_device *dev = sp->pp_if;
 	int len = skb->len;
 
 	if (len < 4) 
@@ -1266,7 +1266,7 @@
  *	cards use.
  */
 
-int sppp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *p)
+int sppp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *p)
 {
 	sppp_input(dev,skb);
 	return 0;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/syncppp.h linux/drivers/net/syncppp.h
--- v2.3.13/linux/drivers/net/syncppp.h	Sat Feb  6 12:46:21 1999
+++ linux/drivers/net/syncppp.h	Wed Aug 18 11:36:45 1999
@@ -46,12 +46,12 @@
 	u32		ibytes,obytes;	/* Bytes in/out */
 	u32		ipkts,opkts;	/* Packets in/out */
 	struct timer_list	pp_timer;
-	struct device	*pp_if;
+	struct net_device	*pp_if;
 };
 
 struct ppp_device
 {	
-	struct device dev;	/* Network device */
+	struct net_device dev;	/* Network device */
 	struct sppp sppp;	/* Synchronous PPP */
 };
 
@@ -73,15 +73,15 @@
 #define IPCP_STATE_OPENED       3       /* IPCP state: opened */
 
 void sppp_attach (struct ppp_device *pd);
-void sppp_detach (struct device *dev);
-void sppp_input (struct device *dev, struct sk_buff *m);
-int sppp_do_ioctl (struct device *dev, struct ifreq *ifr, int cmd);
-struct sk_buff *sppp_dequeue (struct device *dev);
-int sppp_isempty (struct device *dev);
-void sppp_flush (struct device *dev);
-int sppp_open (struct device *dev);
-int sppp_reopen (struct device *dev);
-int sppp_close (struct device *dev);
+void sppp_detach (struct net_device *dev);
+void sppp_input (struct net_device *dev, struct sk_buff *m);
+int sppp_do_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd);
+struct sk_buff *sppp_dequeue (struct net_device *dev);
+int sppp_isempty (struct net_device *dev);
+void sppp_flush (struct net_device *dev);
+int sppp_open (struct net_device *dev);
+int sppp_reopen (struct net_device *dev);
+int sppp_close (struct net_device *dev);
 #endif
 
 #define SPPPIOCCISCO	(SIOCDEVPRIVATE)
diff -u --recursive --new-file v2.3.13/linux/drivers/net/tlan.c linux/drivers/net/tlan.c
--- v2.3.13/linux/drivers/net/tlan.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/tlan.c	Wed Aug 18 11:36:43 1999
@@ -46,12 +46,12 @@
 
 
 
-typedef u32 (TLanIntVectorFunc)( struct device *, u16 );
+typedef u32 (TLanIntVectorFunc)( struct net_device *, u16 );
 
 
 #ifdef MODULE
 
-static	struct device	*TLanDevices = NULL;
+static	struct net_device	*TLanDevices = NULL;
 static	int		TLanDevicesInstalled = 0;
 
 static	int		aui = 0;
@@ -159,57 +159,57 @@
 
 
 static int	TLan_PciProbe( u8 *, u8 *, u8 *, u32 *, u32 * );
-static int	TLan_Init( struct device * );
-static int	TLan_Open(struct device *dev);
-static int	TLan_StartTx(struct sk_buff *, struct device *);
+static int	TLan_Init( struct net_device * );
+static int	TLan_Open(struct net_device *dev);
+static int	TLan_StartTx(struct sk_buff *, struct net_device *);
 static void	TLan_HandleInterrupt(int, void *, struct pt_regs *);
-static int	TLan_Close(struct device *);
-static struct	net_device_stats *TLan_GetStats( struct device * );
-static void	TLan_SetMulticastList( struct device * );
-
-static u32	TLan_HandleInvalid( struct device *, u16 );
-static u32	TLan_HandleTxEOF( struct device *, u16 );
-static u32	TLan_HandleStatOverflow( struct device *, u16 );
-static u32	TLan_HandleRxEOF( struct device *, u16 );
-static u32	TLan_HandleDummy( struct device *, u16 );
-static u32	TLan_HandleTxEOC( struct device *, u16 );
-static u32	TLan_HandleStatusCheck( struct device *, u16 );
-static u32	TLan_HandleRxEOC( struct device *, u16 );
+static int	TLan_Close(struct net_device *);
+static struct	net_device_stats *TLan_GetStats( struct net_device * );
+static void	TLan_SetMulticastList( struct net_device * );
+
+static u32	TLan_HandleInvalid( struct net_device *, u16 );
+static u32	TLan_HandleTxEOF( struct net_device *, u16 );
+static u32	TLan_HandleStatOverflow( struct net_device *, u16 );
+static u32	TLan_HandleRxEOF( struct net_device *, u16 );
+static u32	TLan_HandleDummy( struct net_device *, u16 );
+static u32	TLan_HandleTxEOC( struct net_device *, u16 );
+static u32	TLan_HandleStatusCheck( struct net_device *, u16 );
+static u32	TLan_HandleRxEOC( struct net_device *, u16 );
 
 static void	TLan_Timer( unsigned long );
 
-static void	TLan_ResetLists( struct device * );
-static void	TLan_FreeLists( struct device * );
+static void	TLan_ResetLists( struct net_device * );
+static void	TLan_FreeLists( struct net_device * );
 static void	TLan_PrintDio( u16 );
 static void	TLan_PrintList( TLanList *, char *, int );
-static void	TLan_ReadAndClearStats( struct device *, int );
-static void	TLan_ResetAdapter( struct device * );
-static void	TLan_FinishReset( struct device * );
-static void	TLan_SetMac( struct device *, int areg, char *mac );
-
-static void	TLan_PhyPrint( struct device * );
-static void	TLan_PhyDetect( struct device * );
-static void	TLan_PhyPowerDown( struct device * );
-static void	TLan_PhyPowerUp( struct device * );
-static void	TLan_PhyReset( struct device * );
-static void	TLan_PhyStartLink( struct device * );
-static void	TLan_PhyFinishAutoNeg( struct device * );
+static void	TLan_ReadAndClearStats( struct net_device *, int );
+static void	TLan_ResetAdapter( struct net_device * );
+static void	TLan_FinishReset( struct net_device * );
+static void	TLan_SetMac( struct net_device *, int areg, char *mac );
+
+static void	TLan_PhyPrint( struct net_device * );
+static void	TLan_PhyDetect( struct net_device * );
+static void	TLan_PhyPowerDown( struct net_device * );
+static void	TLan_PhyPowerUp( struct net_device * );
+static void	TLan_PhyReset( struct net_device * );
+static void	TLan_PhyStartLink( struct net_device * );
+static void	TLan_PhyFinishAutoNeg( struct net_device * );
 /*
-static int	TLan_PhyNop( struct device * );
-static int	TLan_PhyInternalCheck( struct device * );
-static int	TLan_PhyInternalService( struct device * );
-static int	TLan_PhyDp83840aCheck( struct device * );
+static int	TLan_PhyNop( struct net_device * );
+static int	TLan_PhyInternalCheck( struct net_device * );
+static int	TLan_PhyInternalService( struct net_device * );
+static int	TLan_PhyDp83840aCheck( struct net_device * );
 */
 
-static int	TLan_MiiReadReg( struct device *, u16, u16, u16 * );
+static int	TLan_MiiReadReg( struct net_device *, u16, u16, u16 * );
 static void	TLan_MiiSendData( u16, u32, unsigned );
 static void	TLan_MiiSync( u16 );
-static void	TLan_MiiWriteReg( struct device *, u16, u16, u16 );
+static void	TLan_MiiWriteReg( struct net_device *, u16, u16, u16 );
 
 static void	TLan_EeSendStart( u16 );
 static int	TLan_EeSendByte( u16, u8, int );
 static void	TLan_EeReceiveByte( u16, u8 *, int );
-static int	TLan_EeReadByte( struct device *, u8, u8 * );
+static int	TLan_EeReadByte( struct net_device *, u8, u8 * );
 
 
 static TLanIntVectorFunc *TLanIntVector[TLAN_INT_NUMBER_OF_INTS] = {
@@ -224,7 +224,7 @@
 };
 
 static inline void
-TLan_SetTimer( struct device *dev, u32 ticks, u32 type )
+TLan_SetTimer( struct net_device *dev, u32 ticks, u32 type )
 {
 	TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;
 
@@ -275,7 +275,7 @@
 extern int init_module(void)
 {
 	TLanPrivateInfo	*priv;
-	struct device	*dev;
+	struct net_device	*dev;
 	size_t		dev_size;
 	u8		dfn;
 	u32		index;
@@ -299,17 +299,17 @@
 
 	memset( TLanPadBuffer, 0, TLAN_MIN_FRAME_SIZE );
 
-	dev_size = sizeof(struct device) + sizeof(TLanPrivateInfo);
+	dev_size = sizeof(struct net_device) + sizeof(TLanPrivateInfo);
 
 	while ( ( found = TLan_PciProbe( &dfn, &irq, &rev, &io_base, &index ) ) ) {
-		dev = (struct device *) kmalloc( dev_size, GFP_KERNEL );
+		dev = (struct net_device *) kmalloc( dev_size, GFP_KERNEL );
 		if ( dev == NULL ) {
 			printk( "TLAN:  Could not allocate memory for device.\n" );
 			continue;
 		}
 		memset( dev, 0, dev_size );
 
-		dev->priv = priv = ( (void *) dev ) + sizeof(struct device);
+		dev->priv = priv = ( (void *) dev ) + sizeof(struct net_device);
 		dev->name = priv->devName;
 		strcpy( priv->devName, "    " );
 		dev->base_addr = io_base;
@@ -376,7 +376,7 @@
 
 extern void cleanup_module(void)
 {
-	struct device	*dev;
+	struct net_device	*dev;
 	TLanPrivateInfo	*priv;
 
 	while ( TLanDevicesInstalled ) {
@@ -417,7 +417,7 @@
 	 *
 	 **************************************************************/
 	 
-extern int tlan_probe( struct device *dev )
+extern int tlan_probe( struct net_device *dev )
 {
 	TLanPrivateInfo	*priv;
 	static int	pad_allocated = 0;
@@ -609,7 +609,7 @@
 	 *	
 	 **************************************************************/
 
-int TLan_Init( struct device *dev )
+int TLan_Init( struct net_device *dev )
 {
 	int		dma_size;
 	int		err;
@@ -697,7 +697,7 @@
 	 *
 	 **************************************************************/
 
-int TLan_Open( struct device *dev )
+int TLan_Open( struct net_device *dev )
 {
 	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
 	int		err;
@@ -757,7 +757,7 @@
 	 *
 	 **************************************************************/
 
-int TLan_StartTx( struct sk_buff *skb, struct device *dev )
+int TLan_StartTx( struct sk_buff *skb, struct net_device *dev )
 {
 	TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;
 	TLanList	*tail_list;
@@ -859,12 +859,12 @@
 void TLan_HandleInterrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	u32		ack;
-	struct device	*dev;
+	struct net_device	*dev;
 	u32		host_cmd;
 	u16		host_int;
 	int		type;
 
-	dev = (struct device *) dev_id;
+	dev = (struct net_device *) dev_id;
 
 	cli();
 	if ( dev->interrupt ) {
@@ -907,7 +907,7 @@
 	 *
 	 **************************************************************/
 
-int TLan_Close(struct device *dev)
+int TLan_Close(struct net_device *dev)
 {
 	TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;
 
@@ -946,7 +946,7 @@
 	 *
 	 **************************************************************/
 
-struct net_device_stats *TLan_GetStats( struct device *dev )
+struct net_device_stats *TLan_GetStats( struct net_device *dev )
 {
 	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
 	int i;
@@ -994,7 +994,7 @@
 	 *
 	 **************************************************************/
 
-void TLan_SetMulticastList( struct device *dev )
+void TLan_SetMulticastList( struct net_device *dev )
 {	
 	struct dev_mc_list	*dmi = dev->mc_list;
 	u32			hash1 = 0;
@@ -1068,7 +1068,7 @@
 	 *
 	 **************************************************************/
 
-u32 TLan_HandleInvalid( struct device *dev, u16 host_int )
+u32 TLan_HandleInvalid( struct net_device *dev, u16 host_int )
 {
 	host_int = 0;
 	/* printk( "TLAN:  Invalid interrupt on %s.\n", dev->name ); */
@@ -1101,7 +1101,7 @@
 	 *
 	 **************************************************************/
 
-u32 TLan_HandleTxEOF( struct device *dev, u16 host_int )
+u32 TLan_HandleTxEOF( struct net_device *dev, u16 host_int )
 {
 	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
 	int		eoc = 0;
@@ -1174,7 +1174,7 @@
 	 *
 	 **************************************************************/
 
-u32 TLan_HandleStatOverflow( struct device *dev, u16 host_int )
+u32 TLan_HandleStatOverflow( struct net_device *dev, u16 host_int )
 {
 	host_int = 0;
 	TLan_ReadAndClearStats( dev, TLAN_RECORD );
@@ -1211,7 +1211,7 @@
 	 *
 	 **************************************************************/
 
-u32 TLan_HandleRxEOF( struct device *dev, u16 host_int )
+u32 TLan_HandleRxEOF( struct net_device *dev, u16 host_int )
 {
 	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
 	u32		ack = 1;
@@ -1335,7 +1335,7 @@
 	 *
 	 **************************************************************/
 
-u32 TLan_HandleDummy( struct device *dev, u16 host_int )
+u32 TLan_HandleDummy( struct net_device *dev, u16 host_int )
 {
 	host_int = 0;
 	printk( "TLAN:  Test interrupt on %s.\n", dev->name );
@@ -1366,7 +1366,7 @@
 	 *
 	 **************************************************************/
 
-u32 TLan_HandleTxEOC( struct device *dev, u16 host_int )
+u32 TLan_HandleTxEOC( struct net_device *dev, u16 host_int )
 {
 	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
 	TLanList		*head_list;
@@ -1411,7 +1411,7 @@
 	 *
 	 **************************************************************/
 
-u32 TLan_HandleStatusCheck( struct device *dev, u16 host_int )
+u32 TLan_HandleStatusCheck( struct net_device *dev, u16 host_int )
 {	
 	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
 	u32		ack;
@@ -1485,7 +1485,7 @@
 	 *
 	 **************************************************************/
 
-u32 TLan_HandleRxEOC( struct device *dev, u16 host_int )
+u32 TLan_HandleRxEOC( struct net_device *dev, u16 host_int )
 {
 	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
 	TLanList	*head_list;
@@ -1548,7 +1548,7 @@
 
 void TLan_Timer( unsigned long data )
 {
-	struct device	*dev = (struct device *) data;
+	struct net_device	*dev = (struct net_device *) data;
 	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
 	u32		elapsed;
 
@@ -1620,7 +1620,7 @@
 	 *
 	 **************************************************************/
 
-void TLan_ResetLists( struct device *dev )
+void TLan_ResetLists( struct net_device *dev )
 {
 	TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;
 	int		i;
@@ -1675,7 +1675,7 @@
 } /* TLan_ResetLists */
 
 
-void TLan_FreeLists( struct device *dev )
+void TLan_FreeLists( struct net_device *dev )
 {
 	TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;
 	int		i;
@@ -1792,7 +1792,7 @@
 	 *
 	 **************************************************************/
 
-void TLan_ReadAndClearStats( struct device *dev, int record )
+void TLan_ReadAndClearStats( struct net_device *dev, int record )
 {
 	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
 	u32		tx_good, tx_under;
@@ -1868,7 +1868,7 @@
 	 **************************************************************/
 
 void
-TLan_ResetAdapter( struct device *dev )
+TLan_ResetAdapter( struct net_device *dev )
 {
 	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
 	int		i;
@@ -1950,7 +1950,7 @@
 
 
 void
-TLan_FinishReset( struct device *dev )
+TLan_FinishReset( struct net_device *dev )
 {
 	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
 	u8		data;
@@ -2036,7 +2036,7 @@
 	 *
 	 **************************************************************/
 
-void TLan_SetMac( struct device *dev, int areg, char *mac )
+void TLan_SetMac( struct net_device *dev, int areg, char *mac )
 {
 	int i;
 			
@@ -2078,7 +2078,7 @@
 	 *
 	 ********************************************************************/
 
-void TLan_PhyPrint( struct device *dev )
+void TLan_PhyPrint( struct net_device *dev )
 {
 	TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;
 	u16 i, data0, data1, data2, data3, phy;
@@ -2127,7 +2127,7 @@
 	 *
 	 ********************************************************************/
 
-void TLan_PhyDetect( struct device *dev )
+void TLan_PhyDetect( struct net_device *dev )
 {
 	TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;
 	u16		control;
@@ -2174,7 +2174,7 @@
 
 
 
-void TLan_PhyPowerDown( struct device *dev )
+void TLan_PhyPowerDown( struct net_device *dev )
 {
 	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
 	u16		value;
@@ -2199,7 +2199,7 @@
 
 
 
-void TLan_PhyPowerUp( struct device *dev )
+void TLan_PhyPowerUp( struct net_device *dev )
 {
 	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
 	u16		value;
@@ -2220,7 +2220,7 @@
 
 
 
-void TLan_PhyReset( struct device *dev )
+void TLan_PhyReset( struct net_device *dev )
 {
 	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
 	u16		phy;
@@ -2248,7 +2248,7 @@
 
 
 
-void TLan_PhyStartLink( struct device *dev )
+void TLan_PhyStartLink( struct net_device *dev )
 {
 	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
 	u16		ability;
@@ -2329,7 +2329,7 @@
 
 
 
-void TLan_PhyFinishAutoNeg( struct device *dev )
+void TLan_PhyFinishAutoNeg( struct net_device *dev )
 {
 	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
 	u16		an_adv;
@@ -2424,7 +2424,7 @@
 	 *
 	 **************************************************************/
 
-int TLan_MiiReadReg( struct device *dev, u16 phy, u16 reg, u16 *val )
+int TLan_MiiReadReg( struct net_device *dev, u16 phy, u16 reg, u16 *val )
 {
 	u8	nack;
 	u16	sio, tmp;
@@ -2595,7 +2595,7 @@
 	 *
 	 **************************************************************/
 
-void TLan_MiiWriteReg( struct device *dev, u16 phy, u16 reg, u16 val )
+void TLan_MiiWriteReg( struct net_device *dev, u16 phy, u16 reg, u16 val )
 {
 	u16	sio;
 	int	minten;
@@ -2824,7 +2824,7 @@
 	 *
 	 **************************************************************/
 
-int TLan_EeReadByte( struct device *dev, u8 ee_addr, u8 *data )
+int TLan_EeReadByte( struct net_device *dev, u8 ee_addr, u8 *data )
 {
 	int err;
 
diff -u --recursive --new-file v2.3.13/linux/drivers/net/tlan.h linux/drivers/net/tlan.h
--- v2.3.13/linux/drivers/net/tlan.h	Sun Aug  9 10:42:41 1998
+++ linux/drivers/net/tlan.h	Wed Aug 18 11:36:45 1999
@@ -156,7 +156,7 @@
 	 ****************************************************************/
 
 typedef struct tlan_private_tag {
-	struct device           *nextDevice;
+	struct net_device           *nextDevice;
 	void			*dmaStorage;
 	u8			*padBuffer;
 	TLanList                *rxList;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/tulip.c linux/drivers/net/tulip.c
--- v2.3.13/linux/drivers/net/tulip.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/tulip.c	Wed Aug 18 11:36:43 1999
@@ -367,7 +367,7 @@
 struct tulip_private {
 	char devname[8];			/* Used only for kernel debugging. */
 	const char *product_name;
-	struct device *next_module;
+	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(). */
@@ -409,36 +409,36 @@
 	int pad0, pad1;						/* Used for 8-byte alignment */
 };
 
-static struct device *tulip_probe1(int pci_bus, int pci_devfn,
-								   struct device *dev,
+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 device *dev);
+static void parse_eeprom(struct net_device *dev);
 static int read_eeprom(long ioaddr, int location);
-static int mdio_read(struct device *dev, int phy_id, int location);
-static void mdio_write(struct device *dev, int phy_id, int location, int value);
-static void select_media(struct device *dev, int startup);
-static int tulip_open(struct device *dev);
+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 int tulip_open(struct net_device *dev);
 static void tulip_timer(unsigned long data);
-static void tulip_tx_timeout(struct device *dev);
-static void tulip_init_ring(struct device *dev);
-static int tulip_start_xmit(struct sk_buff *skb, struct device *dev);
-static int tulip_rx(struct 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 IRQ(int irq, void *dev_instance, struct pt_regs *regs);
-static int tulip_close(struct device *dev);
-static struct enet_statistics *tulip_get_stats(struct device *dev);
+static int tulip_close(struct net_device *dev);
+static struct enet_statistics *tulip_get_stats(struct net_device *dev);
 #ifdef HAVE_PRIVATE_IOCTL
-static int private_ioctl(struct device *dev, struct ifreq *rq, int cmd);
+static int private_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 #endif
 #ifdef NEW_MULTICAST
-static void set_rx_mode(struct device *dev);
+static void set_rx_mode(struct net_device *dev);
 #else
-static void set_rx_mode(struct device *dev, int num_addrs, void *addrs);
+static void set_rx_mode(struct net_device *dev, int num_addrs, void *addrs);
 #endif
 
 
 
 /* A list of all installed Tulip devices, for removing the driver module. */
-static struct device *root_tulip_dev = NULL;
+static struct net_device *root_tulip_dev = NULL;
 
 /* This 21040 probe no longer uses a large fixed contiguous Rx buffer region,
    but now receives directly into full-sized skbuffs that are allocated
@@ -446,7 +446,7 @@
    This allows the probe routine to use the old driver initialization
    interface. */
 
-int tulip_probe(struct device *dev)
+int tulip_probe(struct net_device *dev)
 {
 	int cards_found = 0;
 	static int pci_index = 0;	/* Static, for multiple probe calls. */
@@ -552,8 +552,8 @@
 	return cards_found ? 0 : -ENODEV;
 }
 
-static struct device *tulip_probe1(int pci_bus, int pci_device_fn,
-								   struct device *dev,
+static struct net_device *tulip_probe1(int pci_bus, int pci_device_fn,
+								   struct net_device *dev,
 								   int chip_id, int board_idx)
 {
 	static int did_version = 0;			/* Already printed version info. */
@@ -861,7 +861,7 @@
 #define get_u16(ptr) (((u8*)(ptr))[0] + (((u8*)(ptr))[1]<<8))
 #endif
 
-static void parse_eeprom(struct device *dev)
+static void parse_eeprom(struct net_device *dev)
 {
 	/* The last media info list parsed, for multiport boards.  */
 	static struct mediatable *last_mediatable = NULL;
@@ -1102,7 +1102,7 @@
 #define MDIO_ENB_IN		0x40000
 #define MDIO_DATA_READ	0x80000
 
-static int mdio_read(struct device *dev, int phy_id, int location)
+static int mdio_read(struct net_device *dev, int phy_id, int location)
 {
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
 	int i;
@@ -1147,7 +1147,7 @@
 	return (retval>>1) & 0xffff;
 }
 
-static void mdio_write(struct device *dev, int phy_id, int location, int value)
+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;
@@ -1192,7 +1192,7 @@
 
 
 static int
-tulip_open(struct device *dev)
+tulip_open(struct net_device *dev)
 {
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -1369,7 +1369,7 @@
 }
 
 /* Set up the transceiver control registers for the selected media type. */
-static void select_media(struct device *dev, int startup)
+static void select_media(struct net_device *dev, int startup)
 {
 	long ioaddr = dev->base_addr;
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
@@ -1552,7 +1552,7 @@
 
 static void tulip_timer(unsigned long data)
 {
-	struct device *dev = (struct device *)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);
@@ -1751,7 +1751,7 @@
    of available transceivers.  */
 static void t21142_timer(unsigned long data)
 {
-	struct device *dev = (struct device *)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);
@@ -1814,7 +1814,7 @@
 	add_timer(&tp->timer);
 }
 
-static void t21142_lnk_change( struct device *dev)
+static void t21142_lnk_change( struct net_device *dev)
 {
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -1866,7 +1866,7 @@
 
 static void mxic_timer(unsigned long data)
 {
-	struct device *dev = (struct device *)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;
@@ -1883,7 +1883,7 @@
 
 static void pnic_timer(unsigned long data)
 {
-	struct device *dev = (struct device *)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);
@@ -1966,7 +1966,7 @@
 	add_timer(&tp->timer);
 }
 
-static void tulip_tx_timeout(struct device *dev)
+static void tulip_tx_timeout(struct net_device *dev)
 {
   struct tulip_private *tp = (struct tulip_private *)dev->priv;
   long ioaddr = dev->base_addr;
@@ -2057,7 +2057,7 @@
 
 /* Initialize the Rx and Tx rings, along with various 'dev' bits. */
 static void
-tulip_init_ring(struct device *dev)
+tulip_init_ring(struct net_device *dev)
 {
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
 	int i;
@@ -2102,7 +2102,7 @@
 }
 
 static int
-tulip_start_xmit(struct sk_buff *skb, struct device *dev)
+tulip_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
 	int entry;
@@ -2159,9 +2159,9 @@
 static void tulip_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *regs)
 {
 #ifdef SA_SHIRQ		/* Use the now-standard shared IRQ implementation. */
-	struct device *dev = (struct device *)dev_instance;
+	struct net_device *dev = (struct net_device *)dev_instance;
 #else
-	struct device *dev = (struct device *)(irq2dev_map[irq]);
+	struct net_device *dev = (struct net_device *)(irq2dev_map[irq]);
 #endif
 
 	struct tulip_private *tp;
@@ -2339,7 +2339,7 @@
 }
 
 static int
-tulip_rx(struct device *dev)
+tulip_rx(struct net_device *dev)
 {
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
 	int entry = tp->cur_rx % RX_RING_SIZE;
@@ -2450,7 +2450,7 @@
 }
 
 static int
-tulip_close(struct device *dev)
+tulip_close(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
@@ -2517,7 +2517,7 @@
 }
 
 static struct enet_statistics *
-tulip_get_stats(struct device *dev)
+tulip_get_stats(struct net_device *dev)
 {
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -2530,7 +2530,7 @@
 
 #ifdef HAVE_PRIVATE_IOCTL
 /* Provide ioctl() calls to examine the MII xcvr state. */
-static int private_ioctl(struct device *dev, struct ifreq *rq, int cmd)
+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;
@@ -2620,9 +2620,9 @@
 }
 
 #ifdef NEW_MULTICAST
-static void set_rx_mode(struct device *dev)
+static void set_rx_mode(struct net_device *dev)
 #else
-static void set_rx_mode(struct device *dev, int num_addrs, void *addrs)
+static void set_rx_mode(struct net_device *dev, int num_addrs, void *addrs)
 #endif
 {
 	long ioaddr = dev->base_addr;
@@ -2737,7 +2737,7 @@
 	u16 dev_id;
 	u32 io;
 	u8 bus, devfn;
-	struct device *dev;
+	struct net_device *dev;
 
 	if (loc->bus != LOC_PCI) return NULL;
 	bus = loc->b.pci.bus; devfn = loc->b.pci.devfn;
@@ -2759,7 +2759,7 @@
 
 static void tulip_detach(dev_node_t *node)
 {
-	struct device **devp, **next;
+	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;
@@ -2813,7 +2813,7 @@
 void
 cleanup_module(void)
 {
-	struct device *next_dev;
+	struct net_device *next_dev;
 
 #ifdef CARDBUS
 	unregister_driver(&tulip_ops);
diff -u --recursive --new-file v2.3.13/linux/drivers/net/via-rhine.c linux/drivers/net/via-rhine.c
--- v2.3.13/linux/drivers/net/via-rhine.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/via-rhine.c	Wed Aug 18 11:36:43 1999
@@ -250,12 +250,12 @@
 	const char *name;
 	u16	vendor_id, device_id, device_id_mask, flags;
 	int io_size;
-	struct device *(*probe1)(int pci_bus, int pci_devfn, struct device *dev,
+	struct net_device *(*probe1)(int pci_bus, int pci_devfn, struct net_device *dev,
 							 long ioaddr, int irq, int chip_idx, int fnd_cnt);
 };
 
-static struct device *via_probe1(int pci_bus, int pci_devfn,
-								 struct device *dev, long ioaddr, int irq,
+static struct net_device *via_probe1(int pci_bus, int pci_devfn,
+								 struct net_device *dev, long ioaddr, int irq,
 								 int chp_idx, int fnd_cnt);
 
 static struct pci_id_info pci_tbl[] = {
@@ -344,7 +344,7 @@
 	struct sk_buff* tx_skbuff[TX_RING_SIZE];
 	unsigned char *tx_buf[TX_RING_SIZE];	/* Tx bounce buffers */
 	unsigned char *tx_bufs;				/* Tx bounce buffer region. */
-	struct device *next_module;			/* Link for devices of this type. */
+	struct net_device *next_module;			/* Link for devices of this type. */
 	struct net_device_stats stats;
 	struct timer_list timer;	/* Media monitoring timer. */
 	unsigned char pci_bus, pci_devfn;
@@ -369,33 +369,33 @@
 	unsigned char phys[2];				/* MII device addresses. */
 };
 
-static int  mdio_read(struct device *dev, int phy_id, int location);
-static void mdio_write(struct device *dev, int phy_id, int location, int value);
-static int  netdev_open(struct device *dev);
-static void check_duplex(struct device *dev);
+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 int  netdev_open(struct net_device *dev);
+static void check_duplex(struct net_device *dev);
 static void netdev_timer(unsigned long data);
-static void tx_timeout(struct device *dev);
-static void init_ring(struct device *dev);
-static int  start_tx(struct sk_buff *skb, struct device *dev);
+static void tx_timeout(struct net_device *dev);
+static void init_ring(struct net_device *dev);
+static int  start_tx(struct sk_buff *skb, struct net_device *dev);
 static void intr_handler(int irq, void *dev_instance, struct pt_regs *regs);
-static int  netdev_rx(struct device *dev);
-static void netdev_error(struct device *dev, int intr_status);
-static void set_rx_mode(struct device *dev);
-static struct net_device_stats *get_stats(struct device *dev);
-static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd);
-static int  netdev_close(struct device *dev);
+static int  netdev_rx(struct net_device *dev);
+static void netdev_error(struct net_device *dev, int intr_status);
+static void set_rx_mode(struct net_device *dev);
+static struct net_device_stats *get_stats(struct net_device *dev);
+static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static int  netdev_close(struct net_device *dev);
 
 
 
 /* A list of our installed devices, for removing the driver module. */
-static struct device *root_net_dev = NULL;
+static struct net_device *root_net_dev = NULL;
 
 /* Ideally we would detect all network cards in slot order.  That would
    be best done a central PCI probe dispatch, which wouldn't work
    well when dynamically adding drivers.  So instead we detect just the
    cards we know about in slot order. */
 
-static int pci_etherdev_probe(struct device *dev, struct pci_id_info pci_tbl[])
+static int pci_etherdev_probe(struct net_device *dev, struct pci_id_info pci_tbl[])
 {
 	int cards_found = 0;
 	int pci_index = 0;
@@ -503,15 +503,15 @@
 }
 
 #ifndef MODULE
-int via_rhine_probe(struct device *dev)
+int via_rhine_probe(struct net_device *dev)
 {
 	printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB);
 	return pci_etherdev_probe(dev, pci_tbl);
 }
 #endif
 
-static struct device *via_probe1(int pci_bus, int pci_devfn,
-								 struct device *dev, long ioaddr, int irq,
+static struct net_device *via_probe1(int pci_bus, int pci_devfn,
+								 struct net_device *dev, long ioaddr, int irq,
 								 int chip_id, int card_idx)
 {
 	struct netdev_private *np;
@@ -599,7 +599,7 @@
 
 /* Read and write over the MII Management Data I/O (MDIO) interface. */
 
-static int mdio_read(struct device *dev, int phy_id, int regnum)
+static int mdio_read(struct net_device *dev, int phy_id, int regnum)
 {
 	long ioaddr = dev->base_addr;
 	int boguscnt = 1024;
@@ -617,7 +617,7 @@
 	return readw(ioaddr + MIIData);
 }
 
-static void mdio_write(struct device *dev, int phy_id, int regnum, int value)
+static void mdio_write(struct net_device *dev, int phy_id, int regnum, int value)
 {
 	long ioaddr = dev->base_addr;
 	int boguscnt = 1024;
@@ -634,7 +634,7 @@
 }
 
 
-static int netdev_open(struct device *dev)
+static int netdev_open(struct net_device *dev)
 {
 	struct netdev_private *np = (struct netdev_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -707,7 +707,7 @@
 	return 0;
 }
 
-static void check_duplex(struct device *dev)
+static void check_duplex(struct net_device *dev)
 {
 	struct netdev_private *np = (struct netdev_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -733,7 +733,7 @@
 
 static void netdev_timer(unsigned long data)
 {
-	struct device *dev = (struct device *)data;
+	struct net_device *dev = (struct net_device *)data;
 	struct netdev_private *np = (struct netdev_private *)dev->priv;
 	long ioaddr = dev->base_addr;
 	int next_tick = 10*HZ;
@@ -748,7 +748,7 @@
 	add_timer(&np->timer);
 }
 
-static void tx_timeout(struct device *dev)
+static void tx_timeout(struct net_device *dev)
 {
 	struct netdev_private *np = (struct netdev_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -771,7 +771,7 @@
 
 
 /* Initialize the Rx and Tx rings, along with various 'dev' bits. */
-static void init_ring(struct device *dev)
+static void init_ring(struct net_device *dev)
 {
 	struct netdev_private *np = (struct netdev_private *)dev->priv;
 	int i;
@@ -818,7 +818,7 @@
 	return;
 }
 
-static int start_tx(struct sk_buff *skb, struct device *dev)
+static int start_tx(struct sk_buff *skb, struct net_device *dev)
 {
 	struct netdev_private *np = (struct netdev_private *)dev->priv;
 	unsigned entry;
@@ -877,7 +877,7 @@
    after the Tx thread. */
 static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
 {
-	struct device *dev = (struct device *)dev_instance;
+	struct net_device *dev = (struct net_device *)dev_instance;
 	struct netdev_private *np;
 	long ioaddr, boguscnt = max_interrupt_work;
 
@@ -988,7 +988,7 @@
 
 /* This routine is logically part of the interrupt handler, but isolated
    for clarity and better register allocation. */
-static int netdev_rx(struct device *dev)
+static int netdev_rx(struct net_device *dev)
 {
 	struct netdev_private *np = (struct netdev_private *)dev->priv;
 	int entry = np->cur_rx % RX_RING_SIZE;
@@ -1082,7 +1082,7 @@
 	return 0;
 }
 
-static void netdev_error(struct device *dev, int intr_status)
+static void netdev_error(struct net_device *dev, int intr_status)
 {
 	struct netdev_private *np = (struct netdev_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -1123,7 +1123,7 @@
 	}
 }
 
-static struct enet_statistics *get_stats(struct device *dev)
+static struct enet_statistics *get_stats(struct net_device *dev)
 {
 	struct netdev_private *np = (struct netdev_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -1157,7 +1157,7 @@
     return crc;
 }
 
-static void set_rx_mode(struct device *dev)
+static void set_rx_mode(struct net_device *dev)
 {
 	struct netdev_private *np = (struct netdev_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -1188,7 +1188,7 @@
 	writeb(np->rx_thresh | rx_mode, ioaddr + RxConfig);
 }
 
-static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd)
+static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	u16 *data = (u16 *)&rq->ifr_data;
 
@@ -1209,7 +1209,7 @@
 	}
 }
 
-static int netdev_close(struct device *dev)
+static int netdev_close(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
 	struct netdev_private *np = (struct netdev_private *)dev->priv;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/wavelan.c linux/drivers/net/wavelan.c
--- v2.3.13/linux/drivers/net/wavelan.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/wavelan.c	Wed Aug 18 11:36:43 1999
@@ -1876,7 +1876,7 @@
  * It is here that the wireless extensions are treated (iwconfig).
  */
 static int
-wavelan_ioctl(struct device *	dev,	/* device on which the ioctl is applied */
+wavelan_ioctl(struct net_device *	dev,	/* device on which the ioctl is applied */
 	      struct ifreq *	rq,	/* data passed */
 	      int		cmd)	/* ioctl number */
 {
@@ -4239,13 +4239,13 @@
 	  device *	dev;
 
 	  /* Create device and set basic arguments. */
-	  dev = kmalloc(sizeof(struct device), GFP_KERNEL);
+	  dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
 	  if(dev==NULL)
 	  {
 	  	ret = -ENOMEM;
 	  	break;
 	  }
-	  memset(dev, 0x00, sizeof(struct device));
+	  memset(dev, 0x00, sizeof(struct net_device));
 	  dev->name = name[i];
 	  dev->base_addr = io[i];
 	  dev->irq = irq[i];
@@ -4257,7 +4257,7 @@
 	    {
 	      /* Deallocate everything. */
 	      /* Note: if dev->priv is mallocated, there is no way to fail. */
-	      kfree_s(dev, sizeof(struct device));
+	      kfree_s(dev, sizeof(struct net_device));
 	    }
 	  else
 	    {
@@ -4310,7 +4310,7 @@
 
       /* Free pieces. */
       kfree_s(dev->priv, sizeof(struct net_local));
-      kfree_s(dev, sizeof(struct device));
+      kfree_s(dev, sizeof(struct net_device));
     }
 
 #ifdef DEBUG_MODULE_TRACE
diff -u --recursive --new-file v2.3.13/linux/drivers/net/wavelan.p.h linux/drivers/net/wavelan.p.h
--- v2.3.13/linux/drivers/net/wavelan.p.h	Thu Apr 29 11:53:41 1999
+++ linux/drivers/net/wavelan.p.h	Wed Aug 18 11:36:45 1999
@@ -404,7 +404,7 @@
 /****************************** TYPES ******************************/
 
 /* Shortcuts */
-typedef struct device		device;
+typedef struct net_device		device;
 typedef struct net_device_stats	en_stats;
 typedef struct iw_statistics	iw_stats;
 typedef struct iw_quality	iw_qual;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/wd.c linux/drivers/net/wd.c
--- v2.3.13/linux/drivers/net/wd.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/wd.c	Wed Aug 18 11:36:43 1999
@@ -45,18 +45,18 @@
 static unsigned int wd_portlist[] __initdata =
 {0x300, 0x280, 0x380, 0x240, 0};
 
-int wd_probe(struct device *dev);
-int wd_probe1(struct device *dev, int ioaddr);
+int wd_probe(struct net_device *dev);
+int wd_probe1(struct net_device *dev, int ioaddr);
 
-static int wd_open(struct device *dev);
-static void wd_reset_8390(struct device *dev);
-static void wd_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
+static int wd_open(struct net_device *dev);
+static void wd_reset_8390(struct net_device *dev);
+static void wd_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
 						int ring_page);
-static void wd_block_input(struct device *dev, int count,
+static void wd_block_input(struct net_device *dev, int count,
 						  struct sk_buff *skb, int ring_offset);
-static void wd_block_output(struct device *dev, int count,
+static void wd_block_output(struct net_device *dev, int count,
 							const unsigned char *buf, int start_page);
-static int wd_close(struct device *dev);
+static int wd_close(struct net_device *dev);
 
 
 #define WD_START_PG		0x00	/* First page of TX buffer */
@@ -86,7 +86,7 @@
 {"wd", wd_probe1, WD_IO_EXTENT, wd_portlist};
 #else
 
-int __init wd_probe(struct device *dev)
+int __init wd_probe(struct net_device *dev)
 {
 	int i;
 	int base_addr = dev ? dev->base_addr : 0;
@@ -108,7 +108,7 @@
 }
 #endif
 
-int __init wd_probe1(struct device *dev, int ioaddr)
+int __init wd_probe1(struct net_device *dev, int ioaddr)
 {
 	int i;
 	int checksum = 0;
@@ -313,7 +313,7 @@
 }
 
 static int
-wd_open(struct device *dev)
+wd_open(struct net_device *dev)
 {
   int ioaddr = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
 
@@ -332,7 +332,7 @@
 }
 
 static void
-wd_reset_8390(struct device *dev)
+wd_reset_8390(struct net_device *dev)
 {
 	int wd_cmd_port = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
 
@@ -354,7 +354,7 @@
    the start of a page, so we optimize accordingly. */
 
 static void
-wd_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+wd_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 {
 
 	int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
@@ -379,7 +379,7 @@
    switch between 8- and 16-bit modes. */
 
 static void
-wd_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
+wd_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
 {
 	int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
 	unsigned long xfer_start = dev->mem_start + ring_offset - (WD_START_PG<<8);
@@ -401,7 +401,7 @@
 }
 
 static void
-wd_block_output(struct device *dev, int count, const unsigned char *buf,
+wd_block_output(struct net_device *dev, int count, const unsigned char *buf,
 				int start_page)
 {
 	int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
@@ -419,7 +419,7 @@
 
 
 static int
-wd_close(struct device *dev)
+wd_close(struct net_device *dev)
 {
 	int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
 
@@ -444,7 +444,7 @@
 #define MAX_WD_CARDS	4	/* Max number of wd cards per module */
 #define NAMELEN		8	/* # of chars for storing dev->name */
 static char namelist[NAMELEN * MAX_WD_CARDS] = { 0, };
-static struct device dev_wd[MAX_WD_CARDS] = {
+static struct net_device dev_wd[MAX_WD_CARDS] = {
 	{
 		NULL,		/* assign a chunk of namelist[] below */
 		0, 0, 0, 0,
@@ -471,7 +471,7 @@
 	int this_dev, found = 0;
 
 	for (this_dev = 0; this_dev < MAX_WD_CARDS; this_dev++) {
-		struct device *dev = &dev_wd[this_dev];
+		struct net_device *dev = &dev_wd[this_dev];
 		dev->name = namelist+(NAMELEN*this_dev);
 		dev->irq = irq[this_dev];
 		dev->base_addr = io[this_dev];
@@ -502,7 +502,7 @@
 	int this_dev;
 
 	for (this_dev = 0; this_dev < MAX_WD_CARDS; this_dev++) {
-		struct device *dev = &dev_wd[this_dev];
+		struct net_device *dev = &dev_wd[this_dev];
 		if (dev->priv != NULL) {
 			void *priv = dev->priv;
 			int ioaddr = dev->base_addr - WD_NIC_OFFSET;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/x25_asy.c linux/drivers/net/x25_asy.c
--- v2.3.13/linux/drivers/net/x25_asy.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/x25_asy.c	Wed Aug 18 11:36:43 1999
@@ -34,7 +34,7 @@
 typedef struct x25_ctrl {
 	char		if_name[8];	/* "xasy0\0" .. "xasy99999\0"	*/
 	struct x25_asy	ctrl;		/* X.25 things			*/
-	struct device	dev;		/* the device			*/
+	struct net_device	dev;		/* the device			*/
 } x25_asy_ctrl_t;
 
 static x25_asy_ctrl_t	**x25_asy_ctrls = NULL;
@@ -139,7 +139,7 @@
 
 static void x25_asy_changed_mtu(struct x25_asy *sl)
 {
-	struct device *dev = sl->dev;
+	struct net_device *dev = sl->dev;
 	unsigned char *xbuff, *rbuff, *oxbuff, *orbuff;
 	int len;
 	unsigned long flags;
@@ -324,7 +324,7 @@
 
 /* Encapsulate an IP datagram and kick it into a TTY queue. */
 
-static int x25_asy_xmit(struct sk_buff *skb, struct device *dev)
+static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct x25_asy *sl = (struct x25_asy*)(dev->priv);
 	int err;
@@ -481,7 +481,7 @@
 
 /* Open the low-level part of the X.25 channel. Easy! */
 
-static int x25_asy_open(struct device *dev)
+static int x25_asy_open(struct net_device *dev)
 {
 	struct lapb_register_struct x25_asy_callbacks;
 	struct x25_asy *sl = (struct x25_asy*)(dev->priv);
@@ -542,7 +542,7 @@
 
 
 /* Close the low-level part of the X.25 channel. Easy! */
-static int x25_asy_close(struct device *dev)
+static int x25_asy_close(struct net_device *dev)
 {
 	struct x25_asy *sl = (struct x25_asy*)(dev->priv);
 	int err;
@@ -676,7 +676,7 @@
 }
 
 
-static struct net_device_stats *x25_asy_get_stats(struct device *dev)
+static struct net_device_stats *x25_asy_get_stats(struct net_device *dev)
 {
 	static struct net_device_stats stats;
 	struct x25_asy *sl = (struct x25_asy*)(dev->priv);
@@ -806,7 +806,7 @@
 	}
 }
 
-static int x25_asy_open_dev(struct device *dev)
+static int x25_asy_open_dev(struct net_device *dev)
 {
 	struct x25_asy *sl = (struct x25_asy*)(dev->priv);
 	if(sl->tty==NULL)
@@ -818,7 +818,7 @@
 #ifdef MODULE
 static int x25_asy_init_ctrl_dev(void)
 #else	/* !MODULE */
-int __init x25_asy_init_ctrl_dev(struct device *dummy)
+int __init x25_asy_init_ctrl_dev(struct net_device *dummy)
 #endif	/* !MODULE */
 {
 	int status;
@@ -869,7 +869,7 @@
 
 /* Initialise the X.25 driver.  Called by the device init code */
 
-int x25_asy_init(struct device *dev)
+int x25_asy_init(struct net_device *dev)
 {
 	struct x25_asy *sl = (struct x25_asy*)(dev->priv);
 
diff -u --recursive --new-file v2.3.13/linux/drivers/net/x25_asy.h linux/drivers/net/x25_asy.h
--- v2.3.13/linux/drivers/net/x25_asy.h	Fri Apr  4 08:52:22 1997
+++ linux/drivers/net/x25_asy.h	Wed Aug 18 11:36:45 1999
@@ -19,7 +19,7 @@
 
   /* Various fields. */
   struct tty_struct	*tty;		/* ptr to TTY structure		*/
-  struct device		*dev;		/* easy for intr handling	*/
+  struct net_device		*dev;		/* easy for intr handling	*/
 
   /* These are pointers to the malloc()ed frame buffers. */
   unsigned char		*rbuff;		/* receiver buffer		*/
@@ -53,6 +53,6 @@
 
 #define X25_ASY_MAGIC 0x5303
 
-extern int x25_asy_init(struct device *dev);
+extern int x25_asy_init(struct net_device *dev);
 
 #endif	/* _LINUX_X25_ASY.H */
diff -u --recursive --new-file v2.3.13/linux/drivers/net/yellowfin.c linux/drivers/net/yellowfin.c
--- v2.3.13/linux/drivers/net/yellowfin.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/yellowfin.c	Wed Aug 18 11:36:43 1999
@@ -272,7 +272,7 @@
 	struct yellowfin_desc rx_ring[RX_RING_SIZE];
 	struct yellowfin_desc tx_ring[TX_RING_SIZE*2];
 	const char *product_name;
-	struct device *next_module;
+	struct net_device *next_module;
 	/* The addresses of receive-in-place skbuffs. */
 	struct sk_buff* rx_skbuff[RX_RING_SIZE];
 	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
@@ -316,32 +316,32 @@
 
 #endif
 
-static struct device *yellowfin_probe1(struct device *dev, long ioaddr,
+static struct net_device *yellowfin_probe1(struct net_device *dev, 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);
 #ifdef HAVE_PRIVATE_IOCTL
-static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd);
+static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 #endif
-static int yellowfin_open(struct device *dev);
+static int yellowfin_open(struct net_device *dev);
 static void yellowfin_timer(unsigned long data);
-static void yellowfin_tx_timeout(struct device *dev);
-static void yellowfin_init_ring(struct device *dev);
-static int yellowfin_start_xmit(struct sk_buff *skb, struct device *dev);
+static void yellowfin_tx_timeout(struct net_device *dev);
+static void yellowfin_init_ring(struct net_device *dev);
+static int yellowfin_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static void yellowfin_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
-static int yellowfin_rx(struct device *dev);
-static void yellowfin_error(struct device *dev, int intr_status);
-static int yellowfin_close(struct device *dev);
-static struct enet_statistics *yellowfin_get_stats(struct device *dev);
-static void set_rx_mode(struct device *dev);
+static int yellowfin_rx(struct net_device *dev);
+static void yellowfin_error(struct net_device *dev, int intr_status);
+static int yellowfin_close(struct net_device *dev);
+static struct enet_statistics *yellowfin_get_stats(struct net_device *dev);
+static void set_rx_mode(struct net_device *dev);
 
 
 
 /* A list of all installed Yellowfin devices, for removing the driver module. */
-static struct device *root_yellowfin_dev = NULL;
+static struct net_device *root_yellowfin_dev = NULL;
 
-int yellowfin_probe(struct device *dev)
+int yellowfin_probe(struct net_device *dev)
 {
 	int cards_found = 0;
 	int pci_index = 0;
@@ -423,7 +423,7 @@
 	return cards_found ? 0 : -ENODEV;
 }
 
-static struct device *yellowfin_probe1(struct device *dev, long ioaddr,
+static struct net_device *yellowfin_probe1(struct net_device *dev, long ioaddr,
 									   int irq, int chip_id, int card_idx)
 {
 	static int did_version = 0;			/* Already printed version info. */
@@ -560,7 +560,7 @@
 }
 
 
-static int yellowfin_open(struct device *dev)
+static int yellowfin_open(struct net_device *dev)
 {
 	struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -645,7 +645,7 @@
 
 static void yellowfin_timer(unsigned long data)
 {
-	struct device *dev = (struct device *)data;
+	struct net_device *dev = (struct net_device *)data;
 	struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
 	long ioaddr = dev->base_addr;
 	int next_tick = 0;
@@ -683,7 +683,7 @@
 	}
 }
 
-static void yellowfin_tx_timeout(struct device *dev)
+static void yellowfin_tx_timeout(struct net_device *dev)
 {
 	struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -717,7 +717,7 @@
 
 
 /* Initialize the Rx and Tx rings, along with various 'dev' bits. */
-static void yellowfin_init_ring(struct device *dev)
+static void yellowfin_init_ring(struct net_device *dev)
 {
 	struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
 	int i;
@@ -785,7 +785,7 @@
 	return;
 }
 
-static int yellowfin_start_xmit(struct sk_buff *skb, struct device *dev)
+static int yellowfin_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
 	unsigned entry;
@@ -859,7 +859,7 @@
    after the Tx thread. */
 static void yellowfin_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 {
-	struct device *dev = (struct device *)dev_instance;
+	struct net_device *dev = (struct net_device *)dev_instance;
 	struct yellowfin_private *yp;
 	long ioaddr, boguscnt = max_interrupt_work;
 
@@ -1021,7 +1021,7 @@
 
 /* This routine is logically part of the interrupt handler, but separated
    for clarity and better register allocation. */
-static int yellowfin_rx(struct device *dev)
+static int yellowfin_rx(struct net_device *dev)
 {
 	struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
 	int entry = yp->cur_rx % RX_RING_SIZE;
@@ -1155,7 +1155,7 @@
 	return 0;
 }
 
-static void yellowfin_error(struct device *dev, int intr_status)
+static void yellowfin_error(struct net_device *dev, int intr_status)
 {
 	struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
 
@@ -1168,7 +1168,7 @@
 		yp->stats.rx_errors++;
 }
 
-static int yellowfin_close(struct device *dev)
+static int yellowfin_close(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
 	struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
@@ -1260,7 +1260,7 @@
 	return 0;
 }
 
-static struct enet_statistics *yellowfin_get_stats(struct device *dev)
+static struct enet_statistics *yellowfin_get_stats(struct net_device *dev)
 {
 	struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
 	return &yp->stats;
@@ -1291,7 +1291,7 @@
 }
 
 
-static void set_rx_mode(struct device *dev)
+static void set_rx_mode(struct net_device *dev)
 {
 	struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
 	long ioaddr = dev->base_addr;
@@ -1338,7 +1338,7 @@
 }
 
 #ifdef HAVE_PRIVATE_IOCTL
-static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd)
+static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	long ioaddr = dev->base_addr;
 	u16 *data = (u16 *)&rq->ifr_data;
@@ -1377,7 +1377,7 @@
 
 void cleanup_module(void)
 {
-	struct device *next_dev;
+	struct net_device *next_dev;
 
 	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
 	while (root_yellowfin_dev) {
diff -u --recursive --new-file v2.3.13/linux/drivers/net/z85230.c linux/drivers/net/z85230.c
--- v2.3.13/linux/drivers/net/z85230.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/net/z85230.c	Wed Aug 18 11:36:43 1999
@@ -609,7 +609,7 @@
 };
 
 
-int z8530_sync_open(struct device *dev, struct z8530_channel *c)
+int z8530_sync_open(struct net_device *dev, struct z8530_channel *c)
 {
 	c->sync = 1;
 	c->mtu = dev->mtu+64;
@@ -631,7 +631,7 @@
 
 EXPORT_SYMBOL(z8530_sync_open);
 
-int z8530_sync_close(struct device *dev, struct z8530_channel *c)
+int z8530_sync_close(struct net_device *dev, struct z8530_channel *c)
 {
 	u8 chk;
 	c->irqs = &z8530_nop;
@@ -646,7 +646,7 @@
 
 EXPORT_SYMBOL(z8530_sync_close);
 
-int z8530_sync_dma_open(struct device *dev, struct z8530_channel *c)
+int z8530_sync_dma_open(struct net_device *dev, struct z8530_channel *c)
 {
 	unsigned long flags;
 	
@@ -766,7 +766,7 @@
 
 EXPORT_SYMBOL(z8530_sync_dma_open);
 
-int z8530_sync_dma_close(struct device *dev, struct z8530_channel *c)
+int z8530_sync_dma_close(struct net_device *dev, struct z8530_channel *c)
 {
 	u8 chk;
 	unsigned long flags;
@@ -832,7 +832,7 @@
 
 EXPORT_SYMBOL(z8530_sync_dma_close);
 
-int z8530_sync_txdma_open(struct device *dev, struct z8530_channel *c)
+int z8530_sync_txdma_open(struct net_device *dev, struct z8530_channel *c)
 {
 	unsigned long flags;
 
@@ -925,7 +925,7 @@
 
 EXPORT_SYMBOL(z8530_sync_txdma_open);
 	
-int z8530_sync_txdma_close(struct device *dev, struct z8530_channel *c)
+int z8530_sync_txdma_close(struct net_device *dev, struct z8530_channel *c)
 {
 	unsigned long flags;
 	u8 chk;
diff -u --recursive --new-file v2.3.13/linux/drivers/net/z85230.h linux/drivers/net/z85230.h
--- v2.3.13/linux/drivers/net/z85230.h	Sat May 15 15:05:36 1999
+++ linux/drivers/net/z85230.h	Wed Aug 18 11:36:45 1999
@@ -320,7 +320,7 @@
 	 */
 
 	void		*private;	/* For our owner */
-	struct device	*netdevice;	/* Network layer device */
+	struct net_device	*netdevice;	/* Network layer device */
 	struct net_device_stats stats;	/* Network layer statistics */
 
 	/*
@@ -397,12 +397,12 @@
 extern void z8530_describe(struct z8530_dev *, char *mapping,int io);
 extern int z8530_init(struct z8530_dev *);
 extern int z8530_shutdown(struct z8530_dev *);
-extern int z8530_sync_open(struct device *, struct z8530_channel *);
-extern int z8530_sync_close(struct device *, struct z8530_channel *);
-extern int z8530_sync_dma_open(struct device *, struct z8530_channel *);
-extern int z8530_sync_dma_close(struct device *, struct z8530_channel *);
-extern int z8530_sync_txdma_open(struct device *, struct z8530_channel *);
-extern int z8530_sync_txdma_close(struct device *, struct z8530_channel *);
+extern int z8530_sync_open(struct net_device *, struct z8530_channel *);
+extern int z8530_sync_close(struct net_device *, struct z8530_channel *);
+extern int z8530_sync_dma_open(struct net_device *, struct z8530_channel *);
+extern int z8530_sync_dma_close(struct net_device *, struct z8530_channel *);
+extern int z8530_sync_txdma_open(struct net_device *, struct z8530_channel *);
+extern int z8530_sync_txdma_close(struct net_device *, struct z8530_channel *);
 extern int z8530_channel_load(struct z8530_channel *, u8 *);
 extern int z8530_queue_xmit(struct z8530_channel *c, struct sk_buff *skb);
 extern struct net_device_stats *z8530_get_stats(struct z8530_channel *c);
diff -u --recursive --new-file v2.3.13/linux/drivers/net/znet.c linux/drivers/net/znet.c
--- v2.3.13/linux/drivers/net/znet.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/net/znet.c	Wed Aug 18 11:36:43 1999
@@ -180,15 +180,15 @@
 	char pad;
 };
 
-int znet_probe(struct device *dev);
-static int	znet_open(struct device *dev);
-static int	znet_send_packet(struct sk_buff *skb, struct device *dev);
+int znet_probe(struct net_device *dev);
+static int	znet_open(struct net_device *dev);
+static int	znet_send_packet(struct sk_buff *skb, struct net_device *dev);
 static void	znet_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void	znet_rx(struct device *dev);
-static int	znet_close(struct device *dev);
-static struct net_device_stats *net_get_stats(struct device *dev);
-static void set_multicast_list(struct device *dev);
-static void hardware_init(struct device *dev);
+static void	znet_rx(struct net_device *dev);
+static int	znet_close(struct net_device *dev);
+static struct net_device_stats *net_get_stats(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
+static void hardware_init(struct net_device *dev);
 static void update_stop_hit(short ioaddr, unsigned short rx_stop_offset);
 
 #ifdef notdef
@@ -200,7 +200,7 @@
    BIOS area.  We just scan for the signature, and pull the vital parameters
    out of the structure. */
 
-int __init znet_probe(struct device *dev)
+int __init znet_probe(struct net_device *dev)
 {
 	int i;
 	struct netidblk *netinfo;
@@ -283,7 +283,7 @@
 }
 
 
-static int znet_open(struct device *dev)
+static int znet_open(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr;
 
@@ -314,7 +314,7 @@
 	return 0;
 }
 
-static int znet_send_packet(struct sk_buff *skb, struct device *dev)
+static int znet_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
 	int ioaddr = dev->base_addr;
 	struct net_local *lp = (struct net_local *)dev->priv;
@@ -402,7 +402,7 @@
 /* The ZNET interrupt handler. */
 static void	znet_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
-	struct device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	int ioaddr;
 	int boguscnt = 20;
 
@@ -465,7 +465,7 @@
 	return;
 }
 
-static void znet_rx(struct device *dev)
+static void znet_rx(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -589,7 +589,7 @@
 }
 
 /* The inverse routine to znet_open(). */
-static int znet_close(struct device *dev)
+static int znet_close(struct net_device *dev)
 {
 	unsigned long flags;
 	int ioaddr = dev->base_addr;
@@ -617,7 +617,7 @@
 
 /* Get the current statistics.	This may be called with the card open or
    closed. */
-static struct net_device_stats *net_get_stats(struct device *dev)
+static struct net_device_stats *net_get_stats(struct net_device *dev)
 {
 		struct net_local *lp = (struct net_local *)dev->priv;
 
@@ -632,7 +632,7 @@
    mode change persistent, but must be changed if this code is moved to
    a multiple adaptor environment.
  */
-static void set_multicast_list(struct device *dev)
+static void set_multicast_list(struct net_device *dev)
 {
 	short ioaddr = dev->base_addr;
 
@@ -677,7 +677,7 @@
 
 /* Initialize the hardware.  We have to do this when the board is open()ed
    or when we come out of suspend mode. */
-static void hardware_init(struct device *dev)
+static void hardware_init(struct net_device *dev)
 {
 	unsigned long flags;
 	short ioaddr = dev->base_addr;
diff -u --recursive --new-file v2.3.13/linux/drivers/parport/ieee1284_ops.c linux/drivers/parport/ieee1284_ops.c
--- v2.3.13/linux/drivers/parport/ieee1284_ops.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/parport/ieee1284_ops.c	Thu Aug 12 11:53:18 1999
@@ -32,18 +32,12 @@
  * One-way data transfer functions. *
  *                                ***/
 
-static inline
-int polling (struct pardevice *dev)
-{
-	return dev->port->irq == PARPORT_IRQ_NONE;
-}
-
 /* Compatibility mode. */
 size_t parport_ieee1284_write_compat (struct parport *port,
 				      const void *buffer, size_t len,
 				      int flags)
 {
-	int no_irq;
+	int no_irq = 1;
 	ssize_t count = 0;
 	const unsigned char *addr = buffer;
 	unsigned char byte;
@@ -51,11 +45,15 @@
 	unsigned char ctl = (PARPORT_CONTROL_SELECT
 			     | PARPORT_CONTROL_INIT);
 
-	if (port->irq != PARPORT_IRQ_NONE)
+	if (port->irq != PARPORT_IRQ_NONE) {
 		parport_enable_irq (port);
+		no_irq = 0;
+
+		/* Clear out previous irqs. */
+		while (!down_trylock (&port->physport->ieee1284.irq));
+	}
 
 	port->physport->ieee1284.phase = IEEE1284_PH_FWD_DATA;
-	no_irq = polling (dev);
 	while (count < len) {
 		long expire = jiffies + dev->timeout;
 		long wait = (HZ + 99) / 100;
@@ -63,12 +61,6 @@
 				      | PARPORT_STATUS_BUSY);
 		unsigned char val = (PARPORT_STATUS_ERROR
 				     | PARPORT_STATUS_BUSY);
-		int i;
-
-		/* Write the character to the data lines. */
-		byte = *addr++;
-		parport_write_data (port, byte);
-		udelay (1);
 
 		/* Wait until the peripheral's ready */
 		do {
@@ -111,18 +103,23 @@
 
 			/* Is there a signal pending? */
 			if (signal_pending (current))
-				goto stop;
+				break;
 
 			/* Wait longer next time. */
 			wait *= 2;
 		} while (time_before (jiffies, expire));
 
+		if (signal_pending (current))
+			break;
+
 		DPRINTK (KERN_DEBUG "%s: Timed out\n", port->name);
 		break;
 
 	ready:
-		/* Clear out previous irqs. */
-		while (!down_trylock (&port->physport->ieee1284.irq));
+		/* Write the character to the data lines. */
+		byte = *addr++;
+		parport_write_data (port, byte);
+		udelay (1);
 
 		/* Pulse strobe. */
 		parport_write_control (port, ctl | PARPORT_CONTROL_STROBE);
@@ -131,30 +128,7 @@
 		parport_write_control (port, ctl);
 		udelay (1); /* hold */
 
-		if (no_irq)
-			/* Assume the peripheral received it. */
-			goto done;
-
-		/* Wait until it's received, up to 500us (this ought to be
-		 * tuneable). */
-		for (i = 500; i; i--) {
-			if (!down_trylock (&port->physport->ieee1284.irq) ||
-			    !(parport_read_status (port) & PARPORT_STATUS_ACK))
-				goto done;
-			udelay (1);
-		}
-
-		/* Two choices:
-		 * 1. Assume that the peripheral got the data and just
-		 *    hasn't acknowledged it yet.
-		 * 2. Assume that the peripheral never saw the strobe pulse.
-		 *
-		 * We can't know for sure, so let's be conservative.
-		 */
-		DPRINTK (KERN_DEBUG "%s: no ack", port->name);
-		break;
-
-	done:
+		/* Assume the peripheral received it. */
 		count++;
 
                 /* Let another process run if it needs to. */
@@ -547,7 +521,7 @@
 				goto out;
 
 			/* Yield the port for a while. */
-			if (count && polling (dev)) {
+			if (count && dev->port->irq != PARPORT_IRQ_NONE) {
 				parport_release (dev);
 				current->state = TASK_INTERRUPTIBLE;
 				schedule_timeout ((HZ + 99) / 25);
diff -u --recursive --new-file v2.3.13/linux/drivers/parport/parport_mfc3.c linux/drivers/parport/parport_mfc3.c
--- v2.3.13/linux/drivers/parport/parport_mfc3.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/parport/parport_mfc3.c	Sun Aug 15 11:48:32 1999
@@ -346,7 +346,7 @@
 
 					if (p->irq != PARPORT_IRQ_NONE)
 						if (use_cnt++ == 0)
-							if (request_irq(IRQ_AMIGA_PORTS, mfc3_interrupt, 0, p->name, &pp_mfc3_ops))
+							if (request_irq(IRQ_AMIGA_PORTS, mfc3_interrupt, SA_SHIRQ, p->name, &pp_mfc3_ops))
 								use_cnt--;
 
 					if (parport_probe_hook)
diff -u --recursive --new-file v2.3.13/linux/drivers/parport/parport_pc.c linux/drivers/parport/parport_pc.c
--- v2.3.13/linux/drivers/parport/parport_pc.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/parport/parport_pc.c	Thu Aug 12 11:53:22 1999
@@ -76,7 +76,7 @@
 	outb ((inb (ECONTROL (pb)) & ~m) ^ v, ECONTROL (pb));
 }
 
-#if defined(CONFIG_PARPORT_1284) || defined(CONFIG_PARPORT_PC_FIFO)
+#ifdef CONFIG_PARPORT_PC_FIFO
 /* Safely change the mode bits in the ECR */
 static int change_mode(struct parport *p, int m)
 {
@@ -134,6 +134,7 @@
 	return 0;
 }
 
+#ifdef CONFIG_PARPORT_1284
 /* Find FIFO lossage; FIFO is reset */
 static int get_fifo_residue (struct parport *p)
 {
@@ -180,8 +181,8 @@
 
 	return residue;
 }
-
-#endif /* IEEE 1284 support or FIFO support */
+#endif /* IEEE 1284 support */
+#endif /* FIFO support */
 
 /*
  * Clear TIMEOUT BIT in EPP MODE
@@ -1879,7 +1880,7 @@
 			if (p->irq != PARPORT_IRQ_NONE)
 				free_irq(p->irq, p);
 			release_region(p->base, 3);
-			if (p->size > 3);
+			if (p->size > 3)
 				release_region(p->base + 3, p->size - 3);
 			if (p->modes & PARPORT_MODE_ECP)
 				release_region(p->base_hi, 3);
diff -u --recursive --new-file v2.3.13/linux/drivers/parport/procfs.c linux/drivers/parport/procfs.c
--- v2.3.13/linux/drivers/parport/procfs.c	Wed Jul 28 14:47:42 1999
+++ linux/drivers/parport/procfs.c	Thu Aug 12 10:19:59 1999
@@ -23,8 +23,12 @@
 
 #include <asm/uaccess.h>
 
-#ifdef CONFIG_SYSCTL
+#if defined(CONFIG_SYSCTL) && defined(CONFIG_PROC_FS)
 
+#define PARPORT_MIN_TIMESLICE_VALUE 1ul 
+#define PARPORT_MAX_TIMESLICE_VALUE ((unsigned long) HZ)
+#define PARPORT_MIN_SPINTIME_VALUE 1
+#define PARPORT_MAX_SPINTIME_VALUE 1000
 
 static int do_active_device(ctl_table *table, int write, struct file *filp,
 		      void *result, size_t *lenp)
@@ -167,6 +171,18 @@
 #define PARPORT_DEVICES_ROOT_DIR  { DEV_PARPORT_DEVICES, "devices", \
                                     NULL, 0, 0555, NULL }
 
+static const unsigned long parport_min_timeslice_value =
+PARPORT_MIN_TIMESLICE_VALUE;
+
+static const unsigned long parport_max_timeslice_value =
+PARPORT_MAX_TIMESLICE_VALUE;
+
+static const  int parport_min_spintime_value =
+PARPORT_MIN_SPINTIME_VALUE;
+
+static const int parport_max_spintime_value =
+PARPORT_MAX_SPINTIME_VALUE;
+
 
 struct parport_sysctl_table {
 	struct ctl_table_header *sysctl_header;
@@ -182,7 +198,9 @@
         {
 		{ DEV_PARPORT_SPINTIME, "spintime",
 		  NULL, sizeof(int), 0644, NULL,
-		  &proc_dointvec },
+		  &proc_dointvec_minmax, NULL, NULL,
+		  (void*) &parport_min_spintime_value,
+		  (void*) &parport_max_spintime_value },
 		{ DEV_PARPORT_HARDWARE, "hardware",
 		  NULL, 0, 0444, NULL,
 		  &do_hardware },
@@ -230,7 +248,9 @@
 	{
 		{ DEV_PARPORT_DEVICE_TIMESLICE, "timeslice",
 		  NULL, sizeof(int), 0644, NULL,
-		  &proc_dointvec },
+		  &proc_doulongvec_ms_jiffies_minmax, NULL, NULL,
+		  (void*) &parport_min_timeslice_value,
+		  (void*) &parport_max_timeslice_value },
 	},
 	{ {0, NULL, NULL, 0, 0555, NULL}, {0}},
 	{ PARPORT_DEVICES_ROOT_DIR, {0}},
@@ -258,11 +278,15 @@
 		{ DEV_PARPORT_DEFAULT_TIMESLICE, "timeslice",
 		  &parport_default_timeslice,
 		  sizeof(parport_default_timeslice), 0644, NULL,
-		  &proc_dointvec },
+		  &proc_doulongvec_ms_jiffies_minmax, NULL, NULL,
+		  (void*) &parport_min_timeslice_value,
+		  (void*) &parport_max_timeslice_value },
 		{ DEV_PARPORT_DEFAULT_SPINTIME, "spintime",
 		  &parport_default_spintime,
-		  sizeof(parport_default_timeslice), 0644, NULL,
-		  &proc_dointvec },
+		  sizeof(parport_default_spintime), 0644, NULL,
+		  &proc_dointvec_minmax, NULL, NULL,
+		  (void*) &parport_min_spintime_value,
+		  (void*) &parport_max_spintime_value },
 		{0}
 	},
 	{ { DEV_PARPORT_DEFAULT, "default", NULL, 0, 0555,
@@ -395,7 +419,7 @@
 	return 0;
 }
 
-#else /* no sysctl */
+#else /* no sysctl or no procfs*/
 
 int parport_proc_register(struct parport *pp)
 {
diff -u --recursive --new-file v2.3.13/linux/drivers/pci/Makefile linux/drivers/pci/Makefile
--- v2.3.13/linux/drivers/pci/Makefile	Mon Aug  9 14:59:22 1999
+++ linux/drivers/pci/Makefile	Thu Aug 12 10:39:20 1999
@@ -18,7 +18,7 @@
 O_OBJS   = pci.o names.o
 L_OBJS   := pci_syms.o
 else
-L_OBJS   := pci.o
+L_OBJS   := pci.o names.o
 endif
 
 ifdef CONFIG_PROC_FS
diff -u --recursive --new-file v2.3.13/linux/drivers/pci/pci.c linux/drivers/pci/pci.c
--- v2.3.13/linux/drivers/pci/pci.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/pci/pci.c	Thu Aug 12 11:50:14 1999
@@ -27,6 +27,8 @@
 #define DBG(x...)
 #endif
 
+extern void pci_namedevice(struct pci_dev *);
+
 struct pci_bus pci_root;
 struct pci_dev *pci_devices = NULL;
 int pci_reverse __initdata = 0;
diff -u --recursive --new-file v2.3.13/linux/drivers/pnp/Config.in linux/drivers/pnp/Config.in
--- v2.3.13/linux/drivers/pnp/Config.in	Thu Jul  8 15:42:20 1999
+++ linux/drivers/pnp/Config.in	Sun Aug 15 11:50:35 1999
@@ -1,3 +1,11 @@
 #
 # Plug and Play configuration
 #
+mainmenu_option next_comment
+comment 'Plug and Play configuration'
+
+tristate 'Plug and Play support' CONFIG_PNP
+
+dep_tristate 'ISA Plug and Play support' CONFIG_ISAPNP $CONFIG_PNP
+
+endmenu
diff -u --recursive --new-file v2.3.13/linux/drivers/pnp/Makefile linux/drivers/pnp/Makefile
--- v2.3.13/linux/drivers/pnp/Makefile	Thu Jul  8 15:42:20 1999
+++ linux/drivers/pnp/Makefile	Sun Aug 15 11:50:35 1999
@@ -18,4 +18,12 @@
 MI_OBJS  :=
 MIX_OBJS :=
 
+ifeq ($(CONFIG_ISAPNP),y)
+  LX_OBJS += isapnp.o
+else
+  ifeq ($(CONFIG_ISAPNP),m)
+    MX_OBJS += isapnp.o
+  endif
+endif
+
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.13/linux/drivers/pnp/isapnp.c linux/drivers/pnp/isapnp.c
--- v2.3.13/linux/drivers/pnp/isapnp.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/pnp/isapnp.c	Wed Aug 18 09:59:26 1999
@@ -0,0 +1,2156 @@
+/*
+ *  ISA Plug & Play support
+ *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ *
+ *
+ *   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/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/string.h>
+#include <linux/malloc.h>
+#include <linux/proc_fs.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <linux/isapnp.h>
+
+#ifdef CONFIG_PROC_FS
+#include "isapnp_proc.c"
+#endif
+
+#if 0
+#define ISAPNP_REGION_OK
+#endif
+#if 0
+#define ISAPNP_DEBUG
+#endif
+
+struct resource *pidxr_res = NULL;
+struct resource *pnpwrp_res = NULL;
+struct resource *isapnp_rdp_res = NULL;
+
+int isapnp_disable = 0;			/* Disable ISA PnP */
+int isapnp_rdp = 0;			/* Read Data Port */
+int isapnp_reset = 0;			/* reset all PnP cards (deactivate) */
+int isapnp_skip_pci_scan = 0;		/* skip PCI resource scanning */
+int isapnp_verbose = 1;			/* verbose mode */
+int isapnp_reserve_irq[16] = { [0 ... 15] = -1 };	/* reserve (don't use) some IRQ */
+int isapnp_reserve_dma[8] = { [0 ... 7] = -1 };		/* reserve (don't use) some DMA */
+int isapnp_reserve_io[16] = { [0 ... 15] = -1 };	/* reserve (don't use) some I/O region */
+int isapnp_reserve_mem[16] = { [0 ... 15] = -1 };	/* reserve (don't use) some memory region */
+
+MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_DESCRIPTION("Generic ISA Plug & Play support");
+MODULE_PARM(isapnp_disable, "i");
+MODULE_PARM_DESC(isapnp_disable, "ISA Plug & Play disable");
+MODULE_PARM(isapnp_rdp, "i");
+MODULE_PARM_DESC(isapnp_rdp, "ISA Plug & Play read data port");
+MODULE_PARM(isapnp_reset, "i");
+MODULE_PARM_DESC(isapnp_reset, "ISA Plug & Play reset all cards");
+MODULE_PARM(isapnp_skip_pci_scan, "i");
+MODULE_PARM_DESC(isapnp_skip_pci_scan, "ISA Plug & Play skip PCI resource scanning");
+MODULE_PARM(isapnp_verbose, "i");
+MODULE_PARM_DESC(isapnp_verbose, "ISA Plug & Play verbose mode");
+MODULE_PARM(isapnp_reserve_irq, "1-16i");
+MODULE_PARM_DESC(isapnp_reserve_irq, "ISA Plug & Play - reserve IRQ line(s)");
+MODULE_PARM(isapnp_reserve_dma, "1-8i");
+MODULE_PARM_DESC(isapnp_reserve_dma, "ISA Plug & Play - reserve DMA channel(s)");
+MODULE_PARM(isapnp_reserve_io, "1-16i");
+MODULE_PARM_DESC(isapnp_reserve_io, "ISA Plug & Play - reserve I/O region(s) - port,size");
+MODULE_PARM(isapnp_reserve_mem, "1-16i");
+MODULE_PARM_DESC(isapnp_reserve_mem, "ISA Plug & Play - reserve memory region(s) - address,size");
+
+#define _PIDXR		0x279
+#define _PNPWRP		0xa79
+
+/* short tags */
+#define _STAG_PNPVERNO		0x01
+#define _STAG_LOGDEVID		0x02
+#define _STAG_COMPATDEVID	0x03
+#define _STAG_IRQ		0x04
+#define _STAG_DMA		0x05
+#define _STAG_STARTDEP		0x06
+#define _STAG_ENDDEP		0x07
+#define _STAG_IOPORT		0x08
+#define _STAG_FIXEDIO		0x09
+#define _STAG_VENDOR		0x0e
+#define _STAG_END		0x0f
+/* long tags */
+#define _LTAG_MEMRANGE		0x81
+#define _LTAG_ANSISTR		0x82
+#define _LTAG_UNICODESTR	0x83
+#define _LTAG_VENDOR		0x84
+#define _LTAG_MEM32RANGE	0x85
+#define _LTAG_FIXEDMEM32RANGE	0x86
+
+struct pci_bus *isapnp_cards = NULL;	/* ISA PnP cards */
+struct pci_dev *isapnp_devices = NULL;	/* ISA PnP devices */
+static struct pci_dev *isapnp_last_device = NULL;
+static unsigned char isapnp_checksum_value;
+static DECLARE_MUTEX(isapnp_cfg_mutex);
+static int isapnp_detected = 0;
+
+/* some prototypes */
+
+static int isapnp_config_prepare(struct pci_dev *dev);
+static int isapnp_config_activate(struct pci_dev *dev);
+static int isapnp_config_deactivate(struct pci_dev *dev);
+
+static inline void write_data(unsigned char x)
+{
+	outb(x, _PNPWRP);
+}
+
+static inline void write_address(unsigned char x)
+{
+	outb(x, _PIDXR);
+	udelay(10);
+}
+
+static inline unsigned char read_data(void)
+{
+	unsigned char val = inb(isapnp_rdp);
+	return val;
+}
+
+unsigned char isapnp_read_byte(unsigned char idx)
+{
+	write_address(idx);
+	return read_data();
+}
+
+unsigned short isapnp_read_word(unsigned char idx)
+{
+	unsigned short val;
+
+	val = isapnp_read_byte(idx);
+	val = (val << 8) + isapnp_read_byte(idx+1);
+	return val;
+}
+
+unsigned int isapnp_read_dword(unsigned char idx)
+{
+	unsigned int val;
+
+	val = isapnp_read_byte(idx);
+	val = (val << 8) + isapnp_read_byte(idx+1);
+	val = (val << 8) + isapnp_read_byte(idx+2);
+	val = (val << 8) + isapnp_read_byte(idx+3);
+	return val;
+}
+
+void isapnp_write_byte(unsigned char idx, unsigned char val)
+{
+	write_address(idx);
+	write_data(val);
+}
+
+void isapnp_write_word(unsigned char idx, unsigned short val)
+{
+	isapnp_write_byte(idx, val >> 8);
+	isapnp_write_byte(idx+1, val);
+}
+
+void isapnp_write_dword(unsigned char idx, unsigned int val)
+{
+	isapnp_write_byte(idx, val >> 24);
+	isapnp_write_byte(idx+1, val >> 16);
+	isapnp_write_byte(idx+2, val >> 8);
+	isapnp_write_byte(idx+3, val);
+}
+
+static void *isapnp_alloc(long size)
+{
+	void *result;
+
+	result = kmalloc(size, GFP_KERNEL);
+	if (!result)
+		return NULL;
+	memset(result, 0, size);
+	return result;
+}
+
+static void isapnp_key(void)
+{
+	unsigned char code = 0x6a, msb;
+	int i;
+
+	mdelay(1);
+	write_address(0x00);
+	write_address(0x00);
+
+	write_address(code);
+
+	for (i = 1; i < 32; i++) {
+		msb = ((code & 0x01) ^ ((code & 0x02) >> 1)) << 7;
+		code = (code >> 1) | msb;
+		write_address(code);
+	}
+}
+
+/* place all pnp cards in wait-for-key state */
+static void isapnp_wait(void)
+{
+	isapnp_write_byte(0x02, 0x02);
+}
+
+void isapnp_wake(unsigned char csn)
+{
+	isapnp_write_byte(0x03, csn);
+}
+
+void isapnp_device(unsigned char logdev)
+{
+	isapnp_write_byte(0x07, logdev);
+}
+
+void isapnp_activate(unsigned char logdev)
+{
+	isapnp_device(logdev);
+	isapnp_write_byte(ISAPNP_CFG_ACTIVATE, 1);
+	udelay(250);
+}
+
+void isapnp_deactivate(unsigned char logdev)
+{
+	isapnp_device(logdev);
+	isapnp_write_byte(ISAPNP_CFG_ACTIVATE, 0);
+}
+
+static void __init isapnp_peek(unsigned char *data, int bytes)
+{
+	int i, j;
+	unsigned char d;
+
+	for (i = 1; i <= bytes; i++) {
+		for (j = 0; j < 10; j++) {
+			d = isapnp_read_byte(0x05);
+			if (d & 1)
+				break;
+			udelay(10);
+		}
+		if (!(d & 1)) {
+			*data++ = 0xff;
+			continue;
+		}
+		d = isapnp_read_byte(0x04);	/* PRESDI */
+		isapnp_checksum_value += d;
+		if (data != NULL)
+			*data++ = d;
+	}
+}
+
+#define RDP_STEP	32	/* minimum is 4 */
+
+static int isapnp_next_rdp(void)
+{
+	int rdp = isapnp_rdp;
+	while (rdp <= 0x3ff) {
+		if (!check_region(rdp, 1)) {
+			isapnp_rdp = rdp;
+			return 0;
+		}
+		rdp += RDP_STEP;
+	}
+	return -1;
+}
+
+/* Set read port address */
+static inline void isapnp_set_rdp(void)
+{
+	isapnp_write_byte(0x00, isapnp_rdp >> 2);
+	udelay(100);
+}
+
+
+static int __init isapnp_isolate_rdp_select(void)
+{
+	isapnp_wait();
+	isapnp_key();
+
+	/* Control: reset CSN and conditionally everything else too */
+	isapnp_write_byte(0x02, isapnp_reset ? 0x05 : 0x04);
+	mdelay(2);
+
+	isapnp_wait();
+	isapnp_key();
+	isapnp_wake(0x00);
+
+	if (isapnp_next_rdp() < 0) {
+		isapnp_wait();
+		return -1;
+	}
+
+	isapnp_set_rdp();
+	udelay(1000);
+	write_address(0x01);
+	udelay(1000);
+	return 0;
+}
+
+/*
+ *  Isolate (assign uniqued CSN) to all ISA PnP devices.
+ */
+
+static int __init isapnp_isolate(void)
+{
+	unsigned char checksum = 0x6a;
+	unsigned char chksum = 0x00;
+	unsigned char bit = 0x00;
+	int data;
+	int csn = 0;
+	int i;
+	int iteration = 1;
+
+	isapnp_rdp = 0x213;
+	if (isapnp_isolate_rdp_select() < 0)
+		return -1;
+
+	while (1) {
+		for (i = 1; i <= 64; i++) {
+			data = read_data() << 8;
+			udelay(250);
+			data = data | read_data();
+			udelay(250);
+			if (data == 0x55aa)
+				bit = 0x01;
+			checksum = ((((checksum ^ (checksum >> 1)) & 0x01) ^ bit) << 7) | (checksum >> 1);
+			bit = 0x00;
+		}
+		for (i = 65; i <= 72; i++) {
+			data = read_data() << 8;
+			udelay(250);
+			data = data | read_data();
+			udelay(250);
+			if (data == 0x55aa)
+				chksum |= (1 << (i - 65));
+		}
+		if (checksum != 0x00 && checksum == chksum) {
+			csn++;
+
+			isapnp_write_byte(0x06, csn);
+			udelay(250);
+			iteration++;
+			isapnp_wake(0x00);
+			write_address(0x01);
+			goto __next;
+		}
+		if (iteration == 1) {
+			isapnp_rdp += RDP_STEP;
+			if (isapnp_isolate_rdp_select() < 0)
+				return -1;
+		} else if (iteration > 1) {
+			break;
+		}
+	      __next:
+		checksum = 0x6a;
+		chksum = 0x00;
+		bit = 0x00;
+	}
+	isapnp_wait();
+	return csn;
+}
+
+/*
+ *  Read one tag from stream.
+ */
+
+static int __init isapnp_read_tag(unsigned char *type, unsigned short *size)
+{
+	unsigned char tag, tmp[2];
+
+	isapnp_peek(&tag, 1);
+	if (tag == 0)				/* invalid tag */
+		return -1;
+	if (tag & 0x80) {	/* large item */
+		*type = tag;
+		isapnp_peek(tmp, 2);
+		*size = (tmp[1] << 8) | tmp[0];
+	} else {
+		*type = (tag >> 3) & 0x0f;
+		*size = tag & 0x07;
+	}
+#if 0
+	printk("tag = 0x%x, type = 0x%x, size = %i\n", tag, *type, *size);
+#endif
+	if (type == 0)				/* wrong type */
+		return -1;
+	if (*type == 0xff && *size == 0xffff)	/* probably invalid data */
+		return -1;
+	return 0;
+}
+
+/*
+ *  Skip specified number of bytes from stream.
+ */
+ 
+static void __init isapnp_skip_bytes(int count)
+{
+	isapnp_peek(NULL, count);
+}
+
+/*
+ *  Parse logical device tag.
+ */
+
+static struct pci_dev * __init isapnp_parse_device(struct pci_bus *card, int size, int number)
+{
+	unsigned char tmp[6];
+	struct pci_dev *dev;
+
+	isapnp_peek(tmp, size);
+	dev = isapnp_alloc(sizeof(struct pci_dev));
+	if (!dev)
+		return NULL;
+	dev->devfn = number;
+	dev->vendor = (tmp[1] << 8) | tmp[0];
+	dev->device = (tmp[3] << 8) | tmp[2];
+	dev->regs = tmp[4];
+	dev->bus = card;
+	if (size > 5)
+		dev->regs |= tmp[5] << 8;
+	dev->prepare = isapnp_config_prepare;
+	dev->activate = isapnp_config_activate;
+	dev->deactivate = isapnp_config_deactivate;
+	return dev;
+}
+
+/*
+ *  Build new resources structure
+ */
+
+static struct isapnp_resources * __init isapnp_build_resources(struct pci_dev *dev, int dependent)
+{
+	struct isapnp_resources *res, *ptr, *ptra;
+	
+	res = isapnp_alloc(sizeof(struct isapnp_resources));
+	if (!res)
+		return NULL;
+	res->dev = dev;
+	ptr = (struct isapnp_resources *)dev->sysdata;
+	while (ptr && ptr->next)
+		ptr = ptr->next;
+	if (ptr && ptr->dependent && dependent) { /* add to another list */
+		ptra = ptr->alt;
+		while (ptra && ptra->alt)
+			ptra = ptra->alt;
+		if (!ptra)
+			ptr->alt = res;
+		else
+			ptra->alt = res;
+	} else {
+		if (!ptr)
+			dev->sysdata = res;
+		else
+			ptr->next = res;
+	}
+	if (dependent) {
+		res->priority = dependent & 0xff;
+		if (res->priority > ISAPNP_RES_PRIORITY_FUNCTIONAL)
+			res->priority = ISAPNP_RES_PRIORITY_INVALID;
+		res->dependent = 1;
+	} else {
+		res->priority = ISAPNP_RES_PRIORITY_PREFERRED;
+		res->dependent = 0;
+	}
+	return res;
+}
+
+/*
+ *  Add IRQ resource to resources list.
+ */
+
+static void __init isapnp_add_irq_resource(struct pci_dev *dev,
+                                    	       struct isapnp_resources **res,
+                                               int dependent, int size)
+{
+	unsigned char tmp[3];
+	struct isapnp_irq *irq, *ptr;
+
+	isapnp_peek(tmp, size);
+	irq = isapnp_alloc(sizeof(struct isapnp_irq));
+	if (!irq)
+		return;
+	if (*res == NULL) {
+		*res = isapnp_build_resources(dev, dependent);
+		if (*res == NULL) {
+			kfree(irq);
+			return;
+		}
+	}
+	irq->map = (tmp[1] << 8) | tmp[0];
+	if (size > 2)
+		irq->flags = tmp[2];
+	else
+		irq->flags = DEVICE_IRQ_FLAG_HIGHEDGE;
+	irq->res = *res;
+	ptr = (*res)->irq;
+	while (ptr && ptr->next)
+		ptr = ptr->next;
+	if (ptr)
+		ptr->next = irq;
+	else
+		(*res)->irq = irq;
+}
+
+/*
+ *  Add DMA resource to resources list.
+ */
+
+static void __init isapnp_add_dma_resource(struct pci_dev *dev,
+                                    	       struct isapnp_resources **res,
+                                    	       int dependent, int size)
+{
+	unsigned char tmp[2];
+	struct isapnp_dma *dma, *ptr;
+
+	isapnp_peek(tmp, size);
+	dma = isapnp_alloc(sizeof(struct isapnp_dma));
+	if (!dma)
+		return;
+	if (*res == NULL) {
+		*res = isapnp_build_resources(dev, dependent);
+		if (*res == NULL) {
+			kfree(dma);
+			return;
+		}
+	}
+	dma->map = tmp[0];
+	dma->type = tmp[1] & 3;
+	dma->flags = (tmp[1] >> 2) & 7;
+	dma->speed = (tmp[1] >> 6) & 3;
+	dma->res = *res;
+	ptr = (*res)->dma;
+	while (ptr && ptr->next)
+		ptr = ptr->next;
+	if (ptr)
+		ptr->next = dma;
+	else
+		(*res)->dma = dma;
+}
+
+/*
+ *  Add port resource to resources list.
+ */
+
+static void __init isapnp_add_port_resource(struct pci_dev *dev,
+						struct isapnp_resources **res,
+						int dependent, int size)
+{
+	unsigned char tmp[7];
+	struct isapnp_port *port, *ptr;
+
+	isapnp_peek(tmp, size);
+	port = isapnp_alloc(sizeof(struct isapnp_port));
+	if (!port)
+		return;
+	if (*res == NULL) {
+		*res = isapnp_build_resources(dev, dependent);
+		if (*res == NULL) {
+			kfree(port);
+			return;
+		}
+	}
+	port->min = (tmp[2] << 8) | tmp[1];
+	port->max = (tmp[4] << 8) | tmp[3];
+	port->align = tmp[5];
+	port->size = tmp[6];
+	port->flags = tmp[0] ? ISAPNP_PORT_FLAG_16BITADDR : 0;
+	port->res = *res;
+	ptr = (*res)->port;
+	while (ptr && ptr->next)
+		ptr = ptr->next;
+	if (ptr)
+		ptr->next = port;
+	else
+		(*res)->port = port;
+}
+
+/*
+ *  Add fixed port resource to resources list.
+ */
+
+static void __init isapnp_add_fixed_port_resource(struct pci_dev *dev,
+						      struct isapnp_resources **res,
+						      int dependent, int size)
+{
+	unsigned char tmp[3];
+	struct isapnp_port *port, *ptr;
+
+	isapnp_peek(tmp, size);
+	port = isapnp_alloc(sizeof(struct isapnp_port));
+	if (!port)
+		return;
+	if (*res == NULL) {
+		*res = isapnp_build_resources(dev, dependent);
+		if (*res == NULL) {
+			kfree(port);
+			return;
+		}
+	}
+	port->min = port->max = (tmp[1] << 8) | tmp[0];
+	port->size = tmp[2];
+	port->align = 0;
+	port->flags = ISAPNP_PORT_FLAG_FIXED;
+	port->res = *res;
+	ptr = (*res)->port;
+	while (ptr && ptr->next)
+		ptr = ptr->next;
+	if (ptr)
+		ptr->next = port;
+	else
+		(*res)->port = port;
+}
+
+/*
+ *  Add memory resource to resources list.
+ */
+
+static void __init isapnp_add_mem_resource(struct pci_dev *dev,
+					       struct isapnp_resources **res,
+					       int dependent, int size)
+{
+	unsigned char tmp[9];
+	struct isapnp_mem *mem, *ptr;
+
+	isapnp_peek(tmp, size);
+	mem = isapnp_alloc(sizeof(struct isapnp_mem));
+	if (!mem)
+		return;
+	if (*res == NULL) {
+		*res = isapnp_build_resources(dev, dependent);
+		if (*res == NULL) {
+			kfree(mem);
+			return;
+		}
+	}
+	mem->min = ((tmp[2] << 8) | tmp[1]) << 8;
+	mem->max = ((tmp[4] << 8) | tmp[3]) << 8;
+	mem->align = (tmp[6] << 8) | tmp[5];
+	mem->size = ((tmp[8] << 8) | tmp[7]) << 8;
+	mem->flags = tmp[0] & 7;
+	mem->flags |= (tmp[0] >> 2) & 0x18;
+	mem->type = (tmp[0] >> 3) & 3;
+	mem->res = *res;
+	ptr = (*res)->mem;
+	while (ptr && ptr->next)
+		ptr = ptr->next;
+	if (ptr)
+		ptr->next = mem;
+	else
+		(*res)->mem = mem;
+}
+
+/*
+ *  Add 32-bit memory resource to resources list.
+ */
+
+static void __init isapnp_add_mem32_resource(struct pci_dev *dev,
+						 struct isapnp_resources **res,
+						 int dependent, int size)
+{
+	unsigned char tmp[17];
+	struct isapnp_mem32 *mem32, *ptr;
+
+	isapnp_peek(tmp, size);
+	mem32 = isapnp_alloc(sizeof(struct isapnp_mem32));
+	if (!mem32)
+		return;
+	if (*res == NULL) {
+		*res = isapnp_build_resources(dev, dependent);
+		if (*res == NULL) {
+			kfree(mem32);
+			return;
+		}
+	}
+	memcpy(mem32->data, tmp, 17);
+	mem32->res = *res;
+	ptr = (*res)->mem32;
+	while (ptr && ptr->next)
+		ptr = ptr->next;
+	if (ptr)
+		ptr->next = mem32;
+	else
+		(*res)->mem32 = mem32;
+}
+
+/*
+ *  Add 32-bit fixed memory resource to resources list.
+ */
+
+static void __init isapnp_add_fixed_mem32_resource(struct pci_dev *dev,
+						       struct isapnp_resources **res,
+						       int dependent, int size)
+{
+	unsigned char tmp[17];
+	struct isapnp_mem32 *mem32, *ptr;
+
+	isapnp_peek(tmp, size);
+	mem32 = isapnp_alloc(sizeof(struct isapnp_mem32));
+	if (!mem32)
+		return;
+	if (*res == NULL) {
+		*res = isapnp_build_resources(dev, dependent);
+		if (*res == NULL) {
+			kfree(mem32);
+			return;
+		}
+	}
+	memcpy(mem32->data, tmp, 17);
+	mem32->res = *res;
+	ptr = (*res)->mem32;
+	while (ptr && ptr->next)
+		ptr = ptr->next;
+	if (ptr)
+		ptr->next = mem32;
+	else
+		(*res)->mem32 = mem32;
+}
+
+/*
+ *  Parse resource map for logical device.
+ */
+
+static int __init isapnp_create_device(struct pci_bus *card,
+					   unsigned short size)
+{
+	int number = 0, skip = 0, dependent = 0, compat = 0;
+	unsigned char type, tmp[17];
+	struct pci_dev *dev, *prev_dev;
+	struct isapnp_resources *res = NULL;
+	
+	if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
+		return 1;
+	card->devices = dev;
+	if (isapnp_last_device) {
+		isapnp_last_device->next = dev;
+		isapnp_last_device = dev;
+	} else {
+		isapnp_devices = isapnp_last_device = dev;
+	}
+	while (1) {
+		if (isapnp_read_tag(&type, &size)<0)
+			return 1;
+		if (skip && type != _STAG_LOGDEVID && type != _STAG_END)
+			goto __skip;
+		switch (type) {
+		case _STAG_LOGDEVID:
+			if (size >= 5 && size <= 6) {
+				prev_dev = dev;
+				isapnp_config_prepare(dev);
+				if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
+					return 1;
+				prev_dev->sibling = dev;
+				isapnp_last_device->next = dev;
+				isapnp_last_device = dev;
+				size = 0;
+				skip = 0;
+			} else {
+				skip = 1;
+			}
+			res = NULL;
+			dependent = 0;
+			compat = 0;
+			break;
+		case _STAG_COMPATDEVID:
+			if (size == 4 && compat < DEVICE_COUNT_COMPATIBLE) {
+				isapnp_peek(tmp, 4);
+				dev->vendor_compatible[compat] = (tmp[1] << 8) | tmp[0];
+				dev->device_compatible[compat] = (tmp[3] << 8) | tmp[2];
+				compat++;
+				size = 0;
+			}
+			break;
+		case _STAG_IRQ:
+			if (size < 2 || size > 3)
+				goto __skip;
+			isapnp_add_irq_resource(dev, &res, dependent, size);
+			size = 0;
+			break;
+		case _STAG_DMA:
+			if (size != 2)
+				goto __skip;
+			isapnp_add_dma_resource(dev, &res, dependent, size);
+			size = 0;
+			break;
+		case _STAG_STARTDEP:
+			if (size > 1)
+				goto __skip;
+			res = NULL;
+			dependent = 0x100 | ISAPNP_RES_PRIORITY_ACCEPTABLE;
+			if (size > 0) {
+				isapnp_peek(tmp, size);
+				dependent = 0x100 | tmp[0];
+				size = 0;
+			}
+			break;
+		case _STAG_ENDDEP:
+			if (size != 0)
+				goto __skip;
+			res = NULL;
+			dependent = 0;
+			break;
+		case _STAG_IOPORT:
+			if (size != 7)
+				goto __skip;
+			isapnp_add_port_resource(dev, &res, dependent, size);
+			size = 0;
+			break;
+		case _STAG_FIXEDIO:
+			if (size != 3)
+				goto __skip;
+			isapnp_add_fixed_port_resource(dev, &res, dependent, size);
+			size = 0;
+			break;
+		case _STAG_VENDOR:
+			break;
+		case _LTAG_MEMRANGE:
+			if (size != 9)
+				goto __skip;
+			isapnp_add_mem_resource(dev, &res, dependent, size);
+			size = 0;
+			break;
+		case _LTAG_ANSISTR:
+			if (dev->name[0] == '\0') {
+				unsigned short size1 = size > 47 ? 47 : size;
+				isapnp_peek(dev->name, size1);
+				dev->name[size1] = '\0';
+				size -= size1;
+			}
+			break;
+		case _LTAG_UNICODESTR:
+			/* silently ignore */
+			/* who use unicode for hardware identification? */
+			break;
+		case _LTAG_VENDOR:
+			break;
+		case _LTAG_MEM32RANGE:
+			if (size != 17)
+				goto __skip;
+			isapnp_add_mem32_resource(dev, &res, dependent, size);
+			size = 0;
+			break;
+		case _LTAG_FIXEDMEM32RANGE:
+			if (size != 17)
+				goto __skip;
+			isapnp_add_fixed_mem32_resource(dev, &res, dependent, size);
+			size = 0;
+			break;
+		case _STAG_END:
+			if (size > 0)
+				isapnp_skip_bytes(size);
+			return 1;
+		default:
+			printk("isapnp: unexpected or unknown tag type 0x%x for logical device %i (device %i), ignored\n", type, dev->devfn, card->number);
+		}
+	      __skip:
+	      	if (size > 0)
+		      	isapnp_skip_bytes(size);
+	}
+	isapnp_config_prepare(dev);
+	return 0;
+}
+
+/*
+ *  Parse resource map for ISA PnP card.
+ */
+ 
+static void __init isapnp_parse_resource_map(struct pci_bus *card)
+{
+	unsigned char type, tmp[17];
+	unsigned short size;
+	
+	while (1) {
+		if (isapnp_read_tag(&type, &size)<0)
+			return;
+		switch (type) {
+		case _STAG_PNPVERNO:
+			if (size != 2)
+				goto __skip;
+			isapnp_peek(tmp, 2);
+			card->pnpver = tmp[0];
+			card->productver = tmp[1];
+			size = 0;
+			break;
+		case _STAG_LOGDEVID:
+			if (size >= 5 && size <= 6) {
+				if (isapnp_create_device(card, size)==1)
+					return;
+				size = 0;
+			}
+			break;
+		case _STAG_VENDOR:
+			break;
+		case _LTAG_ANSISTR:
+			if (card->name[0] == '\0') {
+				unsigned short size1 = size > 47 ? 47 : size;
+				isapnp_peek(card->name, size1);
+				card->name[size1] = '\0';
+				size -= size1;
+			}
+			break;
+		case _LTAG_UNICODESTR:
+			/* silently ignore */
+			/* who use unicode for hardware identification? */
+			break;
+		case _LTAG_VENDOR:
+			break;
+		case _STAG_END:
+			if (size > 0)
+				isapnp_skip_bytes(size);
+			return;
+		default:
+			printk("isapnp: unexpected or unknown tag type 0x%x for device %i, ignored\n", type, card->number);
+		}
+	      __skip:
+	      	if (size > 0)
+		      	isapnp_skip_bytes(size);
+	}
+}
+
+/*
+ *  Compute ISA PnP checksum for first eight bytes.
+ */
+
+static unsigned char __init isapnp_checksum(unsigned char *data)
+{
+	int i, j;
+	unsigned char checksum = 0x6a, bit, b;
+	
+	for (i = 0; i < 8; i++) {
+		b = data[i];
+		for (j = 0; j < 8; j++) {
+			bit = 0;
+			if (b & (1 << j))
+				bit = 1;
+			checksum = ((((checksum ^ (checksum >> 1)) & 0x01) ^ bit) << 7) | (checksum >> 1);
+		}
+	}
+	return checksum;
+}
+
+/*
+ *  Build device list for all present ISA PnP devices.
+ */
+
+static int __init isapnp_build_device_list(void)
+{
+	int csn;
+	unsigned char header[9], checksum;
+	struct pci_bus *card, *prev = NULL;
+
+	isapnp_wait();
+	isapnp_key();
+	for (csn = 1; csn <= 10; csn++) {
+		isapnp_wake(csn);
+		isapnp_peek(header, 9);
+		checksum = isapnp_checksum(header);
+#if 0
+		printk("vendor: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+			header[0], header[1], header[2], header[3],
+			header[4], header[5], header[6], header[7], header[8]);
+		printk("checksum = 0x%x\n", checksum);
+#endif
+		if (checksum == 0x00 || checksum != header[8])	/* not valid CSN */
+			continue;
+		if ((card = isapnp_alloc(sizeof(struct pci_bus))) == NULL)
+			continue;
+		card->number = csn;
+		card->vendor = (header[1] << 8) | header[0];
+		card->device = (header[3] << 8) | header[2];
+		card->serial = (header[7] << 24) | (header[6] << 16) | (header[5] << 8) | header[4];
+		isapnp_checksum_value = 0x00;
+		isapnp_parse_resource_map(card);
+		if (isapnp_checksum_value != 0x00)
+			printk("isapnp: checksum for device %i is not valid (0x%x)\n", csn, isapnp_checksum_value);
+		card->checksum = isapnp_checksum_value;
+		if (!isapnp_cards)
+			isapnp_cards = card;
+		else
+			prev->next = card;
+		prev = card;
+	}
+	return 0;
+}
+
+/*
+ *  Basic configuration routines.
+ */
+
+int isapnp_present(void)
+{
+	if (isapnp_devices)
+		return 1;
+	return 0;
+}
+
+int isapnp_cfg_begin(int csn, int logdev)
+{
+	if (csn < 1 || csn > 10 || logdev > 10)
+		return -EINVAL;
+	MOD_INC_USE_COUNT;
+	down(&isapnp_cfg_mutex);
+	isapnp_wait();
+	isapnp_key();
+	isapnp_wake(csn);
+#if 1	/* to avoid malfunction when the isapnptools package is used */
+	isapnp_set_rdp();
+	udelay(1000);	/* delay 1000us */
+	write_address(0x01);
+	udelay(1000);	/* delay 1000us */
+#endif
+	if (logdev >= 0)
+		isapnp_device(logdev);
+	return 0;
+}
+
+int isapnp_cfg_end(void)
+{
+	isapnp_wait();
+	up(&isapnp_cfg_mutex);
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+/*
+ *  Resource manager.
+ */
+
+static struct isapnp_port *isapnp_find_port(struct pci_dev *dev, int index)
+{
+	struct isapnp_resources *res;
+	struct isapnp_port *port;
+	
+	if (!dev || index < 0 || index > 7)
+		return NULL;
+	for (res = (struct isapnp_resources *)dev->sysdata; res; res = res->next) {
+		for (port = res->port; port; port = port->next) {
+			if (!index)
+				return port;
+			index--;
+		}
+	}
+	return NULL;
+}
+
+struct isapnp_irq *isapnp_find_irq(struct pci_dev *dev, int index)
+{
+	struct isapnp_resources *res, *resa;
+	struct isapnp_irq *irq;
+	int index1, index2, index3;
+	
+	if (!dev || index < 0 || index > 7)
+		return NULL;
+	for (res = (struct isapnp_resources *)dev->sysdata; res; res = res->next) {
+		index3 = 0;
+		for (resa = res; resa; resa = resa->alt) {
+			index1 = index;
+			index2 = 0;
+			for (irq = resa->irq; irq; irq = irq->next) {
+				if (!index1)
+					return irq;
+				index1--;
+				index2++;
+			}
+			if (index3 < index2)
+				index3 = index2;
+		}
+		index -= index3;
+	}
+	return NULL;
+}
+
+struct isapnp_dma *isapnp_find_dma(struct pci_dev *dev, int index)
+{
+	struct isapnp_resources *res;
+	struct isapnp_dma *dma;
+	
+	if (!dev || index < 0 || index > 7)
+		return NULL;
+	for (res = (struct isapnp_resources *)dev->sysdata; res; res = res->next) {
+		for (dma = res->dma; dma; dma = dma->next) {
+			if (!index)
+				return dma;
+			index--;
+		}
+	}
+	return NULL;
+}
+
+struct isapnp_mem *isapnp_find_mem(struct pci_dev *dev, int index)
+{
+	struct isapnp_resources *res;
+	struct isapnp_mem *mem;
+	
+	if (!dev || index < 0 || index > 7)
+		return NULL;
+	for (res = (struct isapnp_resources *)dev->sysdata; res; res = res->next) {
+		for (mem = res->mem; mem; mem = mem->next) {
+			if (!index)
+				return mem;
+			index--;
+		}
+	}
+	return NULL;
+}
+
+struct isapnp_mem32 *isapnp_find_mem32(struct pci_dev *dev, int index)
+{
+	struct isapnp_resources *res;
+	struct isapnp_mem32 *mem32;
+	
+	if (!dev || index < 0 || index > 7)
+		return NULL;
+	for (res = (struct isapnp_resources *)dev->sysdata; res; res = res->next) {
+		for (mem32 = res->mem32; mem32; mem32 = mem32->next) {
+			if (!index)
+				return mem32;
+			index--;
+		}
+	}
+	return NULL;
+}
+
+/*
+ *  Device manager.
+ */
+
+struct pci_bus *isapnp_find_card(unsigned short vendor,
+				 unsigned short device,
+				 struct pci_bus *from)
+{
+	struct pci_bus *card;
+
+	if (from == NULL) {
+		from = isapnp_cards;
+	} else {
+		from = from->next;
+	}
+	for (card = from; card; card = card->next) {
+		if (card->vendor == vendor && card->device == device)
+			return card;
+	}
+	return NULL;
+}
+
+struct pci_dev *isapnp_find_dev(struct pci_bus *card,
+				unsigned short vendor,
+				unsigned short function,
+				struct pci_dev *from)
+{
+	struct pci_dev *dev;
+	int idx;
+	
+	if (card == NULL) {	/* look for a logical device from all cards */
+		if (from == NULL) {
+			from = isapnp_devices;
+		} else {
+			from = from->next;
+		}
+		for (dev = from; dev; dev = dev->next) {
+			if (dev->vendor == vendor && dev->device == function)
+				return dev;
+			for (idx = 0; idx < DEVICE_COUNT_COMPATIBLE; idx++)
+				if (dev->vendor_compatible[idx] == vendor &&
+				    dev->device_compatible[idx] == function)
+					return dev;
+		}
+	} else {
+		if (from == NULL) {
+			from = card->devices;
+		} else {
+			from = from->next;
+		}
+		if (from->bus != card)	/* something is wrong */
+			return NULL;
+		for (dev = from; dev; dev = dev->sibling) {
+			if (dev->vendor == vendor && dev->device == function)
+				return dev;
+			for (idx = 0; idx < DEVICE_COUNT_COMPATIBLE; idx++)
+				if (dev->vendor_compatible[idx] == vendor &&
+				    dev->device_compatible[idx] == function)
+					return dev;
+		}		
+	}
+	return NULL;
+}
+
+static int isapnp_config_prepare(struct pci_dev *dev)
+{
+	struct isapnp_resources *res, *resa;
+	struct isapnp_port *port;
+	struct isapnp_irq *irq;
+	struct isapnp_dma *dma;
+	struct isapnp_mem *mem;
+	int port_count, port_count1;
+	int irq_count, irq_count1;
+	int dma_count, dma_count1;
+	int mem_count, mem_count1;
+	int idx;
+
+	if (dev == NULL)
+		return -EINVAL;
+	if (dev->active || dev->ro)
+		return -EBUSY;
+	dev->irq = dev->irq2 = DEVICE_IRQ_NOTSET;
+	dev->irq_flags = dev->irq2_flags = 0;
+	for (idx = 0; idx < DEVICE_COUNT_DMA; idx++) {
+		dev->dma[idx] = DEVICE_DMA_NOTSET;
+		dev->dma_type[idx] = DEVICE_DMA_TYPE_8AND16BIT;
+		dev->dma_flags[idx] = 0;
+		dev->dma_speed[idx] = DEVICE_DMA_SPEED_COMPATIBLE;
+	}
+	for (idx = 0; idx < DEVICE_COUNT_RESOURCE; idx++) {
+		dev->resource[idx].name = NULL;
+		dev->resource[idx].start = DEVICE_IO_NOTSET;
+		dev->resource[idx].end = 0;
+		dev->resource[idx].fixed = 0;
+		dev->resource[idx].bits = 12;
+		dev->resource[idx].hw_flags = 0;
+		dev->resource[idx].type = DEVICE_IO_TYPE_8AND16BIT;
+	}
+	port_count = irq_count = dma_count = mem_count = 0;
+	for (res = (struct isapnp_resources *)dev->sysdata; res; res = res->next) {
+		port_count1 = irq_count1 = dma_count1 = mem_count1 = 0;
+		for (resa = res; resa; resa = resa->alt) {
+			for (port = resa->port, idx = 0; port; port = port->next, idx++) {
+				if (dev->resource[port_count + idx].start == DEVICE_IO_NOTSET) {
+					dev->resource[port_count + idx].start = DEVICE_IO_AUTO;
+					dev->resource[port_count + idx].end = port->size;
+					dev->resource[port_count + idx].bits = port->flags & ISAPNP_PORT_FLAG_16BITADDR ? 16 : 12;
+					dev->resource[port_count + idx].fixed = port->flags & ISAPNP_PORT_FLAG_FIXED ? 1 : 0;
+				}
+			}
+			if (port_count1 < idx)
+				port_count1 = idx;
+			for (irq = resa->irq, idx = 0; irq; irq = irq->next, idx++) {
+				if (irq_count + idx == 0) {
+					if (dev->irq == DEVICE_IRQ_NOTSET) {
+						dev->irq = DEVICE_IRQ_AUTO;
+						dev->irq_flags = irq->flags;
+					}
+				} else if (irq_count + idx == 1) {
+					if (dev->irq2 == DEVICE_IRQ_NOTSET) {
+						dev->irq2 = DEVICE_IRQ_AUTO;
+						dev->irq2_flags = irq->flags;
+					}
+				}
+				
+			}
+			if (irq_count1 < idx)
+				irq_count1 = idx;
+			for (dma = resa->dma, idx = 0; dma; dma = dma->next, idx++)
+				if (dev->dma[idx] == DEVICE_DMA_NOTSET) {
+					dev->dma[idx] = DEVICE_DMA_AUTO;
+					dev->dma_type[idx] = dma->type;
+					dev->dma_flags[idx] = dma->flags;
+					dev->dma_speed[idx] = dma->speed;
+				}
+			if (dma_count1 < idx)
+				dma_count1 = idx;
+			for (mem = resa->mem, idx = 0; mem; mem = mem->next, idx++)
+				if (dev->resource[mem_count + idx + 8].start == DEVICE_IO_AUTO) {
+					dev->resource[mem_count + idx].start = DEVICE_IO_AUTO;
+					dev->resource[mem_count + idx].end = mem->size;
+					dev->resource[mem_count + idx].bits = 24;
+					dev->resource[mem_count + idx].fixed = 0;
+					dev->resource[mem_count + idx].hw_flags = mem->flags;
+					dev->resource[mem_count + idx].type = mem->type;
+				}
+			if (mem_count1 < idx)
+				mem_count1 = idx;
+		}
+		port_count += port_count1;
+		irq_count += irq_count1;
+		dma_count += dma_count1;
+		mem_count += mem_count1;
+	}
+	return 0;
+}
+
+struct isapnp_cfgtmp {
+	struct isapnp_port *port[8];
+	struct isapnp_irq *irq[2];
+	struct isapnp_dma *dma[2];
+	struct isapnp_mem *mem[4];
+	struct pci_dev *request;
+	struct pci_dev result;
+};
+
+static int isapnp_alternative_switch(struct isapnp_cfgtmp *cfg,
+				     struct isapnp_resources *from,
+				     struct isapnp_resources *to)
+{
+	int tmp, tmp1;
+	struct isapnp_port *port;
+	struct isapnp_irq *irq;
+	struct isapnp_dma *dma;
+	struct isapnp_mem *mem;
+
+	if (!cfg)
+		return -EINVAL;
+	/* process port settings */
+	for (tmp = 0; tmp < 8; tmp++) {
+		if (cfg->request->resource[tmp].start != DEVICE_IO_AUTO)
+			continue;		/* don't touch */
+		port = cfg->port[tmp];
+		if (!port) {
+			cfg->port[tmp] = port = isapnp_find_port(cfg->request, tmp);
+			if (!port)
+				return -EINVAL;
+		}
+		if (from && port->res == from) {
+			while (port->res != to) {
+				if (!port->res->alt)
+					return -EINVAL;
+				port = port->res->alt->port;
+				for (tmp1 = tmp; tmp1 > 0 && port; tmp1--)
+					port = port->next;
+				cfg->port[tmp] = port;
+				cfg->result.resource[tmp].start = DEVICE_IO_AUTO;
+				if (!port)
+					return -ENOENT;
+			}
+		}
+	}
+	/* process irq settings */
+	for (tmp = 0; tmp < 2; tmp++) {
+		if (tmp == 0) {
+			if (cfg->request->irq != DEVICE_IRQ_AUTO)
+				continue;		/* don't touch */
+		} else {
+			if (cfg->request->irq2 != DEVICE_IRQ_AUTO)
+				continue;		/* don't touch */
+		}
+		irq = cfg->irq[tmp];
+		if (!irq) {
+			cfg->irq[tmp] = irq = isapnp_find_irq(cfg->request, tmp);
+			if (!irq)
+				return -EINVAL;
+		}
+		if (from && irq->res == from) {
+			while (irq->res != to) {
+				if (!irq->res->alt)
+					return -EINVAL;
+				irq = irq->res->alt->irq;
+				for (tmp1 = tmp; tmp1 > 0 && irq; tmp1--)
+					irq = irq->next;
+				cfg->irq[tmp] = irq;
+				if (tmp == 0) {
+					cfg->result.irq = DEVICE_IRQ_AUTO;
+				} else {
+					cfg->result.irq2 = DEVICE_IRQ_AUTO;
+				}
+				if (!irq)
+					return -ENOENT;
+			}
+		}
+	}
+	/* process dma settings */
+	for (tmp = 0; tmp < 2; tmp++) {
+		if (cfg->request->dma[tmp] != DEVICE_DMA_AUTO)
+			continue;		/* don't touch */
+		dma = cfg->dma[tmp];
+		if (!dma) {
+			cfg->dma[tmp] = dma = isapnp_find_dma(cfg->request, tmp);
+			if (!dma)
+				return -EINVAL;
+		}
+		if (from && dma->res == from) {
+			while (dma->res != to) {
+				if (!dma->res->alt)
+					return -EINVAL;
+				dma = dma->res->alt->dma;
+				for (tmp1 = tmp; tmp1 > 0 && dma; tmp1--)
+					dma = dma->next;
+				cfg->dma[tmp] = dma;
+				cfg->result.dma[tmp] = DEVICE_DMA_AUTO;
+				if (!dma)
+					return -ENOENT;
+			}
+		}
+	}
+	/* process memory settings */
+	for (tmp = 0; tmp < 4; tmp++) {
+		if (cfg->request->resource[tmp + 8].start != DEVICE_IO_AUTO)
+			continue;		/* don't touch */
+		mem = cfg->mem[tmp];
+		if (!mem) {
+			cfg->mem[tmp] = mem = isapnp_find_mem(cfg->request, tmp);
+			if (!mem)
+				return -EINVAL;
+		}
+		if (from && mem->res == from) {
+			while (mem->res != to) {
+				if (!mem->res->alt)
+					return -EINVAL;
+				mem = mem->res->alt->mem;
+				for (tmp1 = tmp; tmp1 > 0 && mem; tmp1--)
+					mem = mem->next;
+				cfg->mem[tmp] = mem;
+				cfg->result.resource[tmp + 8].start = DEVICE_IO_AUTO;
+				if (!mem)
+					return -ENOENT;
+			}
+		}
+	}
+	return 0;
+}
+
+static int isapnp_check_port(struct isapnp_cfgtmp *cfg, int port, int size, int idx)
+{
+	int i, tmp, rport, rsize;
+	struct isapnp_port *xport;
+	struct pci_dev *dev;
+
+	if (check_region(port, size))
+		return 1;
+	for (i = 0; i < 8; i++) {
+		rport = isapnp_reserve_io[i << 1];
+		rsize = isapnp_reserve_io[(i << 1) + 1];
+		if (port >= rport && port < rport + rsize)
+			return 1;
+		if (port + size > rport && port + size < (rport + rsize) - 1)
+			return 1;
+	}
+	for (dev = isapnp_devices; dev; dev = dev->next) {
+		if (dev->active) {
+			for (tmp = 0; tmp < 8; tmp++) {
+				if (dev->resource[tmp].start != DEVICE_IO_NOTSET) {
+					rport = dev->resource[tmp].start;
+					rsize = (dev->resource[tmp].end - rport) + 1;
+					if (port >= rport && port < rport + rsize)
+						return 1;
+					if (port + size > rport && port + size < (rport + rsize) - 1)
+						return 1;
+				}
+			}
+		}
+	}
+	for (i = 0; i < 8; i++) {
+		if (i == idx)
+			continue;
+		tmp = cfg->request->resource[i].start;
+		if (tmp == DEVICE_IO_NOTSET)
+			continue;
+		if (tmp == DEVICE_IO_AUTO) {		/* auto */
+			xport = cfg->port[i];
+			if (!xport)
+				return 1;
+			tmp = cfg->result.resource[i].start;
+			if (tmp == DEVICE_IO_AUTO)
+				continue;
+			if (tmp + xport->size >= port && tmp <= port + xport->size)
+				return 1;
+			continue;
+		}
+		if (port == tmp)
+			return 1;
+		xport = isapnp_find_port(cfg->request, i);
+		if (!xport)
+			return 1;
+		if (tmp + xport->size >= port && tmp <= port + xport->size)
+			return 1;
+	}
+	return 0;
+}
+
+static int isapnp_valid_port(struct isapnp_cfgtmp *cfg, int idx)
+{
+	int err;
+	unsigned long *value;
+	struct isapnp_port *port;
+
+	if (!cfg || idx < 0 || idx > 7)
+		return -EINVAL;
+	if (cfg->result.resource[idx].start != DEVICE_IO_AUTO) /* don't touch */
+		return 0;
+      __again:
+      	port = cfg->port[idx];
+      	if (!port)
+      		return -EINVAL;
+      	value = &cfg->result.resource[idx].start;
+	if (*value == DEVICE_IO_AUTO) {
+		if (!isapnp_check_port(cfg, *value = port->min, port->size, idx))
+			return 0;
+	}
+	do {
+		*value += port->align;
+		if (*value > port->max || !port->align) {
+			if (port->res && port->res->alt) {
+				if ((err = isapnp_alternative_switch(cfg, port->res, port->res->alt))<0)
+					return err;
+				goto __again;
+			}
+			return -ENOENT;
+		}
+	} while (isapnp_check_port(cfg, *value, port->size, idx));
+	return 0;
+}
+
+static void isapnp_test_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+}
+
+static int isapnp_check_interrupt(struct isapnp_cfgtmp *cfg, int irq, int idx)
+{
+	int i;
+	struct pci_dev *dev;
+
+	if (irq < 0 || irq > 15)
+		return 1;
+	for (i = 0; i < 16; i++) {
+		if (isapnp_reserve_irq[i] == irq)
+			return 1;
+	}
+	for (dev = isapnp_devices; dev; dev = dev->next) {
+		if (dev->active) {
+			if (dev->irq == irq || dev->irq2 == irq)
+				return 1;
+		}
+	}
+	if (request_irq(irq, isapnp_test_handler, SA_INTERRUPT, "isapnp", NULL))
+		return 1;
+	free_irq(irq, NULL);
+	if (idx != 0) {
+		if (cfg->result.irq != DEVICE_IRQ_AUTO &&
+		    cfg->result.irq != DEVICE_IRQ_NOTSET)
+			if (cfg->result.irq == irq)
+				return 1;
+	}
+	if (idx != 1) {
+		if (cfg->result.irq2 != DEVICE_IRQ_AUTO &&
+		    cfg->result.irq2 != DEVICE_IRQ_NOTSET)
+			if (cfg->result.irq2 == irq)
+				return 1;
+	}
+	return 0;
+}
+
+static int isapnp_valid_irq(struct isapnp_cfgtmp *cfg, int idx)
+{
+	/* IRQ priority: table is good for i386 */
+	static unsigned short xtab[16] = {
+		5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2
+	};
+	int err, i;
+	unsigned int *value;
+	struct isapnp_irq *irq;
+
+	if (!cfg || idx < 0 || idx > 1)
+		return -EINVAL;
+	if (idx == 0) {
+		if (cfg->result.irq != DEVICE_IRQ_AUTO) /* don't touch */
+			return 0;
+	} else {
+		if (cfg->result.irq2 != DEVICE_IRQ_AUTO) /* don't touch */
+			return 0;
+	}
+      __again:
+      	irq = cfg->irq[idx];
+      	if (!irq)
+      		return -EINVAL;
+      	if (idx == 0) {
+	      	value = &cfg->result.irq;
+	} else {
+		value = &cfg->result.irq2;
+	}
+	if (*value == DEVICE_IRQ_AUTO) {
+		for (i = 0; i < 16 && !(irq->map & (1<<xtab[i])); i++);
+		if (i >= 16)
+			return -ENOENT;
+		if (!isapnp_check_interrupt(cfg, *value = xtab[i], idx))
+			return 0;
+	}
+	do {
+		for (i = 0; i < 16 && xtab[i] != *value; i++);
+		for (i++; i < 16 && !(irq->map & (1<<xtab[i])); i++);
+		if (i >= 16) {
+			if (irq->res && irq->res->alt) {
+				if ((err = isapnp_alternative_switch(cfg, irq->res, irq->res->alt))<0)
+					return err;
+				goto __again;
+			}
+			return -ENOENT;
+		} else {
+			*value = xtab[i];
+		}
+	} while (isapnp_check_interrupt(cfg, *value, idx));
+	return 0;
+}
+
+static int isapnp_check_dma(struct isapnp_cfgtmp *cfg, int dma, int idx)
+{
+	int i;
+	struct pci_dev *dev;
+
+	if (dma < 0 || dma == 4 || dma > 7)
+		return 1;
+	for (i = 0; i < 8; i++) {
+		if (isapnp_reserve_dma[i] == dma)
+			return 1;
+	}
+	for (dev = isapnp_devices; dev; dev = dev->next) {
+		if (dev->active) {
+			if (dev->dma[0] == dma || dev->dma[1] == dma)
+				return 1;
+		}
+	}
+	if (request_dma(dma, "isapnp"))
+		return 1;
+	free_dma(dma);
+	for (i = 0; i < 2; i++) {
+		if (i == idx)
+			continue;
+		if (cfg->result.dma[i] == DEVICE_DMA_NOTSET ||
+		    cfg->result.dma[i] == DEVICE_DMA_AUTO)
+			continue;
+		if (cfg->result.dma[i] == dma)
+			return 1;
+	}
+	return 0;
+}
+
+static int isapnp_valid_dma(struct isapnp_cfgtmp *cfg, int idx)
+{
+	int err, i;
+	unsigned char *value;
+	struct isapnp_dma *dma;
+
+	if (!cfg || idx < 0 || idx > 1)
+		return -EINVAL;
+	if (cfg->result.dma[idx] != DEVICE_DMA_AUTO)	/* don't touch */
+		return 0;
+      __again:
+      	dma = cfg->dma[idx];
+      	if (!dma)
+      		return -EINVAL;
+      	value = &cfg->result.dma[idx];
+	if (*value == DEVICE_DMA_AUTO) {
+		for (i = 0; i < 8 && !(dma->map & (1<<i)); i++);
+		if (i >= 8)
+			return -ENOENT;
+		if (!isapnp_check_dma(cfg, *value = i, idx))
+			return 0;
+	}
+	do {
+		for (i = *value + 1; i < 8 && !(dma->map & (1<<i)); i++);
+		if (i >= 8) {
+			if (dma->res && dma->res->alt) {
+				if ((err = isapnp_alternative_switch(cfg, dma->res, dma->res->alt))<0)
+					return err;
+				goto __again;
+			}
+			return -ENOENT;
+		} else {
+			*value = i;
+		}
+	} while (isapnp_check_dma(cfg, *value, idx));
+	return 0;
+}
+
+static int isapnp_check_mem(struct isapnp_cfgtmp *cfg, unsigned int addr, unsigned int size, int idx)
+{
+	int i, tmp;
+	unsigned int raddr, rsize;
+	struct pci_dev *dev;
+	struct isapnp_mem *xmem;
+
+	for (i = 0; i < 8; i++) {
+		raddr = (unsigned int)isapnp_reserve_mem[i << 1];
+		rsize = (unsigned int)isapnp_reserve_mem[(i << 1) + 1];
+		if (addr >= raddr && addr < raddr + rsize)
+			return 1;
+		if (addr + size > raddr && addr + size < (raddr + rsize) - 1)
+			return 1;
+		if (__check_region(&iomem_resource, addr, size))
+			return 1;
+	}
+	for (dev = isapnp_devices; dev; dev = dev->next) {
+		if (dev->active) {
+			for (tmp = 0; tmp < 4; tmp++) {
+				if (dev->resource[tmp].start != DEVICE_IO_NOTSET) {
+					raddr = dev->resource[tmp + 8].start;
+					rsize = (dev->resource[tmp + 8].end - raddr) + 1;
+					if (addr >= raddr && addr < raddr + rsize)
+						return 1;
+					if (addr + size > raddr && addr + size < (raddr + rsize) - 1)
+						return 1;
+				}
+			}
+		}
+	}
+	for (i = 0; i < 4; i++) {
+		if (i == idx)
+			continue;
+		tmp = cfg->request->resource[i + 8].start;
+		if (tmp == DEVICE_IO_NOTSET)
+			continue;
+		if (tmp == DEVICE_IO_AUTO) {		/* auto */
+			xmem = cfg->mem[i];
+			if (!xmem)
+				return 1;
+			tmp = cfg->result.resource[i + 8].start;
+			if (tmp == DEVICE_IO_AUTO)
+				continue;
+			if (tmp + xmem->size >= addr && tmp <= addr + xmem->size)
+				return 1;
+			continue;
+		}
+		if (addr == tmp)
+			return 1;
+		xmem = isapnp_find_mem(cfg->request, i);
+		if (!xmem)
+			return 1;
+		if (tmp + xmem->size >= addr && tmp <= addr + xmem->size)
+			return 1;
+	}
+	return 0;
+}
+
+static int isapnp_valid_mem(struct isapnp_cfgtmp *cfg, int idx)
+{
+	int err;
+	unsigned long *value;
+	struct isapnp_mem *mem;
+
+	if (!cfg || idx < 0 || idx > 3)
+		return -EINVAL;
+	if (cfg->result.resource[idx + 8].start != DEVICE_IO_AUTO) /* don't touch */
+		return 0;
+      __again:
+      	mem = cfg->mem[idx];
+      	if (!mem)
+      		return -EINVAL;
+      	value = &cfg->result.resource[idx].start;
+	if (*value == DEVICE_IO_AUTO) {
+		*value = mem->min;
+		if (!isapnp_check_mem(cfg, *value, mem->size, idx))
+			return 0;
+	}
+	do {
+		*value += mem->align;
+		if (*value >= 8 || !mem->align) {
+			if (mem->res && mem->res->alt) {
+				if ((err = isapnp_alternative_switch(cfg, mem->res, mem->res->alt))<0)
+					return err;
+				goto __again;
+			}
+			return -ENOENT;
+		}
+	} while (isapnp_check_mem(cfg, *value, mem->size, idx));
+	return 0;
+}
+
+static int isapnp_check_valid(struct isapnp_cfgtmp *cfg)
+{
+	int tmp;
+	
+	for (tmp = 0; tmp < 8; tmp++)
+		if (cfg->result.resource[tmp].start == DEVICE_IO_AUTO)
+			return -EAGAIN;
+	if (cfg->result.irq == DEVICE_IRQ_AUTO)
+		return -EAGAIN;
+	if (cfg->result.irq2 == DEVICE_IRQ_AUTO)
+		return -EAGAIN;
+	for (tmp = 0; tmp < 2; tmp++)
+		if (cfg->result.dma[tmp] == DEVICE_DMA_AUTO)
+			return -EAGAIN;
+	for (tmp = 0; tmp < 4; tmp++)
+		if (cfg->result.resource[tmp + 1].start == DEVICE_IO_AUTO)
+			return -EAGAIN;
+	return 0;
+}
+
+static int isapnp_config_activate(struct pci_dev *dev)
+{
+	struct isapnp_cfgtmp cfg;
+	int tmp, fauto, err;
+	
+	if (!dev)
+		return -EINVAL;
+	if (dev->active)
+		return -EBUSY;
+	memset(&cfg, 0, sizeof(cfg));
+	cfg.request = dev;
+	memcpy(&cfg.result, dev, sizeof(struct pci_dev));
+	/* check if all values are set, otherwise try auto-configuration */
+	for (tmp = fauto = 0; !fauto && tmp < 8; tmp++) {
+		if (dev->resource[tmp].start == DEVICE_IO_AUTO)
+			fauto++;
+	}
+	if (dev->irq == DEVICE_IRQ_AUTO)
+		fauto++;
+	if (dev->irq2 == DEVICE_IRQ_AUTO)
+		fauto++;
+	for (tmp = 0; !fauto && tmp < 2; tmp++) {
+		if (dev->dma[tmp] == DEVICE_DMA_AUTO)
+			fauto++;
+	}
+	for (tmp = 0; !fauto && tmp < 4; tmp++) {
+		if (dev->resource[tmp + 8].start == DEVICE_IO_AUTO)
+			fauto++;
+	}
+	if (!fauto)
+		goto __skip_auto;
+	/* set variables to initial values */
+	if ((err = isapnp_alternative_switch(&cfg, NULL, NULL))<0)
+		return err;
+	/* find first valid configuration */
+	fauto = 0;
+	do {
+		for (tmp = 0; tmp < 8 && cfg.result.resource[tmp].start != DEVICE_IO_NOTSET; tmp++)
+			if ((err = isapnp_valid_port(&cfg, tmp))<0)
+				return err;
+		if (cfg.result.irq != DEVICE_IRQ_NOTSET)
+			if ((err = isapnp_valid_irq(&cfg, 0))<0)
+				return err;
+		if (cfg.result.irq2 != DEVICE_IRQ_NOTSET)
+			if ((err = isapnp_valid_irq(&cfg, 1))<0)
+				return err;
+		for (tmp = 0; tmp < 2 && tmp < cfg.result.dma[tmp] != DEVICE_DMA_NOTSET; tmp++)
+			if ((err = isapnp_valid_dma(&cfg, tmp))<0)
+				return err;
+		for (tmp = 0; tmp < 4 && tmp < cfg.result.resource[tmp + 8].start != DEVICE_IO_NOTSET; tmp++)
+			if ((err = isapnp_valid_mem(&cfg, tmp))<0)
+				return err;
+	} while (isapnp_check_valid(&cfg)<0 && fauto++ < 20);
+	if (fauto >= 20)
+		return -EAGAIN;
+      __skip_auto:
+      	/* we have valid configuration, try configure hardware */
+      	isapnp_cfg_begin(dev->bus->number, dev->devfn);
+	dev->active = 1;
+	dev->irq = cfg.result.irq;
+	dev->irq2 = cfg.result.irq2;
+	dev->dma[0] = cfg.result.dma[0];
+	dev->dma[1] = cfg.result.dma[1];
+	for (tmp = 0; tmp < 12; tmp++) {
+		dev->resource[tmp].start = cfg.result.resource[tmp].start;
+		if (cfg.result.resource[tmp].start != DEVICE_IO_NOTSET &&
+		    cfg.result.resource[tmp].end != DEVICE_IO_AUTO)
+			dev->resource[tmp].end += cfg.result.resource[tmp].start;
+	}	
+	for (tmp = 0; tmp < 8 && dev->resource[tmp].start != DEVICE_IO_NOTSET; tmp++)
+		isapnp_write_word(ISAPNP_CFG_PORT+(tmp<<1), dev->resource[tmp].start);
+	if (dev->irq != DEVICE_IRQ_NOTSET) {
+		if (dev->irq == 2)
+			dev->irq = 9;
+		isapnp_write_byte(ISAPNP_CFG_IRQ+(0<<1), dev->irq);
+	}
+	if (dev->irq2 != DEVICE_IRQ_NOTSET) {
+		if (dev->irq2 == 2)
+			dev->irq2 = 9;
+		isapnp_write_byte(ISAPNP_CFG_IRQ+(1<<1), dev->irq2);
+	}
+	for (tmp = 0; tmp < 2 && dev->dma[tmp] != DEVICE_DMA_NOTSET; tmp++)
+		isapnp_write_byte(ISAPNP_CFG_DMA+tmp, dev->dma[tmp]);
+	for (tmp = 0; tmp < 4 && dev->resource[tmp].start != DEVICE_IO_NOTSET; tmp++)
+		isapnp_write_word(ISAPNP_CFG_MEM+(tmp<<2), (dev->resource[tmp + 8].start >> 8) & 0xffff);
+	isapnp_activate(dev->devfn);
+	isapnp_cfg_end();
+	return 0;
+}
+
+static int isapnp_config_deactivate(struct pci_dev *dev)
+{
+	if (!dev || !dev->active)
+		return -EINVAL;
+      	isapnp_cfg_begin(dev->bus->number, dev->devfn);
+	isapnp_deactivate(dev->devfn);
+	dev->activate = 0;
+	isapnp_cfg_end();
+	return 0;
+}
+
+/*
+ *  Inititialization.
+ */
+
+#ifdef MODULE
+
+static void isapnp_free_port(struct isapnp_port *port)
+{
+	struct isapnp_port *next;
+
+	while (port) {
+		next = port->next;
+		kfree(port);
+		port = next;
+	}
+}
+
+static void isapnp_free_irq(struct isapnp_irq *irq)
+{
+	struct isapnp_irq *next;
+
+	while (irq) {
+		next = irq->next;
+		kfree(irq);
+		irq = next;
+	}
+}
+
+static void isapnp_free_dma(struct isapnp_dma *dma)
+{
+	struct isapnp_dma *next;
+
+	while (dma) {
+		next = dma->next;
+		kfree(dma);
+		dma = next;
+	}
+}
+
+static void isapnp_free_mem(struct isapnp_mem *mem)
+{
+	struct isapnp_mem *next;
+
+	while (mem) {
+		next = mem->next;
+		kfree(mem);
+		mem = next;
+	}
+}
+
+static void isapnp_free_mem32(struct isapnp_mem32 *mem32)
+{
+	struct isapnp_mem32 *next;
+
+	while (mem32) {
+		next = mem32->next;
+		kfree(mem32);
+		mem32 = next;
+	}
+}
+
+static void isapnp_free_resources(struct isapnp_resources *resources, int alt)
+{
+	struct isapnp_resources *next;
+
+	while (resources) {
+		next = alt ? resources->alt : resources->next;
+		isapnp_free_port(resources->port);
+		isapnp_free_irq(resources->irq);
+		isapnp_free_dma(resources->dma);
+		isapnp_free_mem(resources->mem);
+		isapnp_free_mem32(resources->mem32);
+		if (!alt && resources->alt)
+			isapnp_free_resources(resources->alt, 1);
+		kfree(resources);
+		resources = next;
+	}
+}
+
+static void isapnp_free_device(struct pci_dev *dev)
+{
+	struct pci_dev *next;
+
+	while (dev) {
+		next = dev->next;
+		isapnp_free_resources((struct isapnp_resources *)dev->sysdata, 0);
+		kfree(dev);
+		dev = next;
+	}
+}
+
+#endif /* MODULE */
+
+static void isapnp_free_all_resources(void)
+{
+#ifdef MODULE
+	struct pci_bus *card, *cardnext;
+#endif
+
+#ifdef ISAPNP_REGION_OK
+	release_resource(pidxr_res);
+#endif
+	release_resource(pnpwrp_res);
+	if (isapnp_rdp >= 0x203 && isapnp_rdp <= 0x3ff)
+		release_resource(isapnp_rdp_res);
+#ifdef MODULE
+	for (card = isapnp_cards; card; card = cardnext) {
+		cardnext = card->next;
+		isapnp_free_device(card->devices);
+		kfree(card);
+	}
+#ifdef CONFIG_PROC_FS
+	isapnp_proc_done();
+#endif
+#endif
+}
+
+static int __init isapnp_do_reserve_irq(int irq)
+{
+	int i;
+	
+	if (irq < 0 || irq > 15)
+		return -EINVAL;
+	for (i = 0; i < 16; i++) {
+		if (isapnp_reserve_irq[i] == irq)
+			return 0;
+	}
+	for (i = 0; i < 16; i++) {
+		if (isapnp_reserve_irq[i] < 0) {
+			isapnp_reserve_irq[i] = irq;
+#ifdef ISAPNP_DEBUG
+			printk("IRQ %i is reserved now.\n", irq);
+#endif
+			return 0;
+		}
+	}
+	return -ENOMEM;
+}
+
+#ifdef CONFIG_PCI
+
+static void __init isapnp_pci_init(void)
+{
+	int devfn;
+	struct pci_dev *dev;
+	
+	for (devfn = 0; devfn < 255; devfn++) {
+		dev = pci_find_slot(0, devfn);
+		if (dev != NULL)
+			break;
+	}
+	if (dev == NULL)
+		return;
+	while (dev) {
+#ifdef ISAPNP_DEBUG
+		printk("PCI: reserved IRQ: %i\n", dev->irq);
+#endif
+		if (dev->irq > 0)
+			isapnp_do_reserve_irq(dev->irq);
+		dev = dev->next;
+	}
+}
+
+#endif /* CONFIG_PCI */
+
+EXPORT_SYMBOL(isapnp_present);
+EXPORT_SYMBOL(isapnp_cfg_begin);
+EXPORT_SYMBOL(isapnp_cfg_end);
+EXPORT_SYMBOL(isapnp_read_byte);
+EXPORT_SYMBOL(isapnp_read_word);
+EXPORT_SYMBOL(isapnp_read_dword);
+EXPORT_SYMBOL(isapnp_write_byte);
+EXPORT_SYMBOL(isapnp_write_word);
+EXPORT_SYMBOL(isapnp_write_dword);
+EXPORT_SYMBOL(isapnp_wake);
+EXPORT_SYMBOL(isapnp_device);
+EXPORT_SYMBOL(isapnp_activate);
+EXPORT_SYMBOL(isapnp_deactivate);
+EXPORT_SYMBOL(isapnp_find_card);
+EXPORT_SYMBOL(isapnp_find_dev);
+
+int __init isapnp_init(void)
+{
+	int cards;
+	struct pci_bus *card;
+	struct pci_dev *dev;
+
+	if (isapnp_disable) {
+		isapnp_detected = 0;
+		printk("isapnp: ISA Plug & Play support disabled\n");
+		return 0;
+	}
+#ifdef ISAPNP_REGION_OK
+	pidxr_res=request_region(_PIDXR, 1, "isapnp index");
+	if(!pidxr_res) {
+		printk("isapnp: Index Register 0x%x already used\n", _PIDXR);
+		return -EBUSY;
+	}
+#endif
+	pnpwrp_res=request_region(_PNPWRP, 1, "isapnp write");
+	if(!pnpwrp_res) {
+		printk("isapnp: Write Data Register 0x%x already used\n", _PNPWRP);
+		return -EBUSY;
+	}
+	if (isapnp_rdp >= 0x203 && isapnp_rdp <= 0x3ff) {
+		isapnp_rdp |= 3;
+		isapnp_rdp_res=request_region(isapnp_rdp, 1, "isapnp read");
+		if(!isapnp_rdp_res) {
+			printk("isapnp: Read Data Register 0x%x already used\n", isapnp_rdp);
+			return -EBUSY;
+		}
+		isapnp_set_rdp();
+	}
+	isapnp_detected = 1;
+	if (isapnp_rdp < 0x203 || isapnp_rdp > 0x3ff) {
+		cards = isapnp_isolate();
+		if (cards < 0 || 
+		    (isapnp_rdp < 0x203 || isapnp_rdp > 0x3ff)) {
+			isapnp_free_all_resources();
+			isapnp_detected = 0;
+			printk("isapnp: No Plug & Play device found\n");
+			return 0;
+		}
+		isapnp_rdp_res=request_region(isapnp_rdp, 1, "isapnp read");
+	}
+	isapnp_build_device_list();
+	cards = 0;
+	for (card = isapnp_cards; card; card = card->next)
+		cards++;
+	if (isapnp_verbose) {
+		for (card = isapnp_cards; card; card = card->next) {
+			printk( "isapnp: Card '%s'\n", card->name[0]?card->name:"Unknown");
+			if (isapnp_verbose < 2)
+				continue;
+			for (dev = card->devices; dev; dev = dev->next)
+				printk("isapnp:   Device '%s'\n", dev->name[0]?card->name:"Unknown");
+		}
+	}
+	if (cards) {
+		printk("isapnp: %i Plug & Play card%s detected total\n", cards, cards>1?"s":"");
+	} else {
+		printk("isapnp: No Plug & Play card found\n");
+	}
+#ifdef CONFIG_PCI
+	if (!isapnp_skip_pci_scan)
+		isapnp_pci_init();
+#endif
+#ifdef CONFIG_PROC_FS
+	isapnp_proc_init();
+#endif
+	return 0;
+}
+
+#ifdef MODULE
+
+int init_module(void)
+{
+	return isapnp_init();
+}
+
+void cleanup_module(void)
+{
+	if (isapnp_detected)
+		isapnp_free_all_resources();
+}
+
+#endif
diff -u --recursive --new-file v2.3.13/linux/drivers/pnp/isapnp_proc.c linux/drivers/pnp/isapnp_proc.c
--- v2.3.13/linux/drivers/pnp/isapnp_proc.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/pnp/isapnp_proc.c	Tue Aug 17 17:19:58 1999
@@ -0,0 +1,945 @@
+/*
+ *  ISA Plug & Play support
+ *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ *
+ *
+ *   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.
+ *
+ */
+
+static void *isapnp_alloc(long size);
+struct pci_bus *isapnp_cards;
+struct pci_dev *isapnp_devices;
+
+struct isapnp_info_buffer {
+	char *buffer;		/* pointer to begin of buffer */
+	char *curr;		/* current position in buffer */
+	unsigned long size;	/* current size */
+	unsigned long len;	/* total length of buffer */
+	int stop;		/* stop flag */
+	int error;		/* error code */
+};
+
+typedef struct isapnp_info_buffer isapnp_info_buffer_t;
+
+static struct proc_dir_entry *isapnp_proc_entry = NULL;
+
+static void isapnp_info_read(isapnp_info_buffer_t *buffer);
+static void isapnp_info_write(isapnp_info_buffer_t *buffer);
+
+int isapnp_printf(isapnp_info_buffer_t * buffer, char *fmt,...)
+{
+	va_list args;
+	int res;
+	char sbuffer[512];
+
+	if (buffer->stop || buffer->error)
+		return 0;
+	va_start(args, fmt);
+	res = vsprintf(sbuffer, fmt, args);
+	va_end(args);
+	if (buffer->size + res >= buffer->len) {
+		buffer->stop = 1;
+		return 0;
+	}
+	strcpy(buffer->curr, sbuffer);
+	buffer->curr += res;
+	buffer->size += res;
+	return res;
+}
+
+static loff_t isapnp_info_entry_lseek(struct file *file, loff_t offset, int orig)
+{
+	switch (orig) {
+	case 0:	/* SEEK_SET */
+		file->f_pos = offset;
+		return file->f_pos;
+	case 1:	/* SEEK_CUR */
+		file->f_pos += offset;
+		return file->f_pos;
+	case 2:	/* SEEK_END */
+	default:
+		return -EINVAL;
+	}
+	return -ENXIO;
+}
+
+static ssize_t isapnp_info_entry_read(struct file *file, char *buffer,
+				      size_t count, loff_t * offset)
+{
+	isapnp_info_buffer_t *buf;
+	long size = 0, size1;
+	int mode;
+
+	mode = file->f_flags & O_ACCMODE;
+	if (mode != O_RDONLY)
+		return -EINVAL;
+	buf = (isapnp_info_buffer_t *) file->private_data;
+	if (!buf)
+		return -EIO;
+	if (file->f_pos >= buf->size)
+		return 0;
+	size = buf->size < count ? buf->size : count;
+	size1 = buf->size - file->f_pos;
+	if (size1 < size)
+		size = size1;
+	if (copy_to_user(buffer, buf->buffer + file->f_pos, size))
+		return -EFAULT;
+	file->f_pos += size;
+	return size;
+}
+
+static ssize_t isapnp_info_entry_write(struct file *file, const char *buffer,
+				       size_t count, loff_t * offset)
+{
+	isapnp_info_buffer_t *buf;
+	long size = 0, size1;
+	int mode;
+
+	mode = file->f_flags & O_ACCMODE;
+	if (mode != O_WRONLY)
+		return -EINVAL;
+	buf = (isapnp_info_buffer_t *) file->private_data;
+	if (!buf)
+		return -EIO;
+	if (file->f_pos < 0)
+		return -EINVAL;
+	if (file->f_pos >= buf->len)
+		return -ENOMEM;
+	size = buf->len < count ? buf->len : count;
+	size1 = buf->len - file->f_pos;
+	if (size1 < size)
+		size = size1;
+	if (copy_from_user(buf->buffer + file->f_pos, buffer, size))
+		return -EFAULT;
+	if (buf->size < file->f_pos + size)
+		buf->size = file->f_pos + size;
+	file->f_pos += size;
+	return size;
+}
+
+static int isapnp_info_entry_open(struct inode *inode, struct file *file)
+{
+	isapnp_info_buffer_t *buffer;
+	int mode;
+
+	mode = file->f_flags & O_ACCMODE;
+	if (mode != O_RDONLY && mode != O_WRONLY)
+		return -EINVAL;
+	buffer = (isapnp_info_buffer_t *)
+				isapnp_alloc(sizeof(isapnp_info_buffer_t));
+	if (!buffer)
+		return -ENOMEM;
+	buffer->len = 4 * PAGE_SIZE;
+	buffer->buffer = vmalloc(buffer->len);
+	if (!buffer->buffer) {
+		kfree(buffer);
+		return -ENOMEM;
+	}
+	buffer->curr = buffer->buffer;
+	file->private_data = buffer;
+	MOD_INC_USE_COUNT;
+	if (mode == O_RDONLY)
+		isapnp_info_read(buffer);
+	return 0;
+}
+
+static int isapnp_info_entry_release(struct inode *inode, struct file *file)
+{
+	isapnp_info_buffer_t *buffer;
+	int mode;
+
+	if ((buffer = (isapnp_info_buffer_t *) file->private_data) == NULL)
+		return -EINVAL;
+	mode = file->f_flags & O_ACCMODE;
+	if (mode == O_WRONLY)
+		isapnp_info_write(buffer);
+	vfree(buffer->buffer);
+	kfree(buffer);
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static unsigned int isapnp_info_entry_poll(struct file *file, poll_table * wait)
+{
+	if (!file->private_data)
+		return 0;
+	return POLLIN | POLLRDNORM;
+}
+
+static int isapnp_info_entry_ioctl(struct inode *inode, struct file *file,
+				   unsigned int cmd, unsigned long arg)
+{
+	return -EINVAL;
+}
+
+static int isapnp_info_entry_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	return -ENXIO;
+}
+
+static struct file_operations isapnp_info_entry_operations =
+{
+	isapnp_info_entry_lseek,	/* lseek */
+	isapnp_info_entry_read,		/* read */
+	isapnp_info_entry_write,	/* write */
+	NULL,				/* readdir */
+	isapnp_info_entry_poll,		/* poll */
+	isapnp_info_entry_ioctl,	/* ioctl - default */
+	isapnp_info_entry_mmap,		/* mmap */
+	isapnp_info_entry_open,		/* open */
+	NULL,				/* flush */
+	isapnp_info_entry_release,	/* release */
+	NULL,				/* can't fsync */
+	NULL,				/* fasync */
+	NULL,				/* check_media_change */
+	NULL,				/* revalidate */
+	NULL,				/* lock */
+};
+
+static struct inode_operations isapnp_info_entry_inode_operations =
+{
+	&isapnp_info_entry_operations,	/* default sound info 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,			/* readpage */
+	NULL,			/* writepage */
+	NULL,			/* bmap */
+	NULL,			/* truncate */
+	NULL			/* permission */
+};
+
+__initfunc(static int isapnp_proc_init(void))
+{
+	struct proc_dir_entry *p;
+
+	isapnp_proc_entry = NULL;
+	p = create_proc_entry("isapnp", S_IFREG | S_IRUGO | S_IWUSR, &proc_root);
+	if (!p)
+		return -ENOMEM;
+	p->ops = &isapnp_info_entry_inode_operations;
+	isapnp_proc_entry = p;
+	return 0;
+}
+
+#ifdef MODULE
+static int isapnp_proc_done(void)
+{
+	if (isapnp_proc_entry)
+		proc_unregister(&proc_root, isapnp_proc_entry->low_ino);
+	return 0;
+}
+#endif /* MODULE */
+
+/*
+ *
+ */
+
+static void isapnp_print_devid(isapnp_info_buffer_t *buffer, unsigned short vendor, unsigned short device)
+{
+	char tmp[8];
+	
+	sprintf(tmp, "%c%c%c%x%x%x%x",
+			'A' + ((vendor >> 2) & 0x3f) - 1,
+			'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1,
+			'A' + ((vendor >> 8) & 0x1f) - 1,
+			(device >> 4) & 0x0f,
+			device & 0x0f,
+			(device >> 12) & 0x0f,
+			(device >> 8) & 0x0f);
+	isapnp_printf(buffer, tmp);
+}
+
+static void isapnp_print_compatible(isapnp_info_buffer_t *buffer, struct pci_dev *dev)
+{
+	int idx;
+
+	for (idx = 0; idx < DEVICE_COUNT_COMPATIBLE; idx++) {
+		if (dev->vendor_compatible[idx] == 0)
+			continue;
+		isapnp_printf(buffer, "    Compatible device ");
+		isapnp_print_devid(buffer,
+				   dev->vendor_compatible[idx],
+				   dev->device_compatible[idx]);
+		isapnp_printf(buffer, "\n");
+	}
+}
+
+static void isapnp_print_port(isapnp_info_buffer_t *buffer, char *space, struct isapnp_port *port)
+{
+	isapnp_printf(buffer, "%sPort 0x%x-0x%x, align 0x%x, size 0x%x, %i-bit address decoding\n",
+			space, port->min, port->max, port->align ? (port->align-1) : 0, port->size,
+			port->flags & ISAPNP_PORT_FLAG_16BITADDR ? 16 : 10);
+}
+
+static void isapnp_print_irq(isapnp_info_buffer_t *buffer, char *space, struct isapnp_irq *irq)
+{
+	int first = 1, i;
+
+	isapnp_printf(buffer, "%sIRQ ", space);
+	for (i = 0; i < 16; i++)
+		if (irq->map & (1<<i)) {
+			if (!first) {
+				isapnp_printf(buffer, ",");
+			} else {
+				first = 0;
+			}
+			if (i == 2 || i == 9)
+				isapnp_printf(buffer, "2/9");
+			else
+				isapnp_printf(buffer, "%i", i);
+		}
+	if (!irq->map)
+		isapnp_printf(buffer, "<none>");
+	if (irq->flags & DEVICE_IRQ_FLAG_HIGHEDGE)
+		isapnp_printf(buffer, " High-Edge");
+	if (irq->flags & DEVICE_IRQ_FLAG_LOWEDGE)
+		isapnp_printf(buffer, " Low-Edge");
+	if (irq->flags & DEVICE_IRQ_FLAG_HIGHLEVEL)
+		isapnp_printf(buffer, " High-Level");
+	if (irq->flags & DEVICE_IRQ_FLAG_LOWLEVEL)
+		isapnp_printf(buffer, " Low-Level");
+	isapnp_printf(buffer, "\n");
+}
+
+static void isapnp_print_dma(isapnp_info_buffer_t *buffer, char *space, struct isapnp_dma *dma)
+{
+	int first = 1, i;
+	char *s;
+
+	isapnp_printf(buffer, "%sDMA ", space);
+	for (i = 0; i < 8; i++)
+		if (dma->map & (1<<i)) {
+			if (!first) {
+				isapnp_printf(buffer, ",");
+			} else {
+				first = 0;
+			}
+			isapnp_printf(buffer, "%i", i);
+		}
+	if (!dma->map)
+		isapnp_printf(buffer, "<none>");
+	switch (dma->type) {
+	case DEVICE_DMA_TYPE_8BIT:
+		s = "8-bit";
+		break;
+	case DEVICE_DMA_TYPE_8AND16BIT:
+		s = "8-bit&16-bit";
+		break;
+	default:
+		s = "16-bit";
+	}
+	isapnp_printf(buffer, " %s", s);
+	if (dma->flags & DEVICE_DMA_FLAG_MASTER)
+		isapnp_printf(buffer, " master");
+	if (dma->flags & DEVICE_DMA_FLAG_BYTE)
+		isapnp_printf(buffer, " byte-count");
+	if (dma->flags & DEVICE_DMA_FLAG_WORD)
+		isapnp_printf(buffer, " word-count");
+	switch (dma->speed) {
+	case DEVICE_DMA_SPEED_TYPEA:
+		s = "type-A";
+		break;
+	case DEVICE_DMA_SPEED_TYPEB:
+		s = "type-B";
+		break;
+	case DEVICE_DMA_SPEED_TYPEF:
+		s = "type-F";
+		break;
+	default:
+		s = "compatible";
+		break;
+	}
+	isapnp_printf(buffer, " %s\n", s);
+}
+
+static void isapnp_print_mem(isapnp_info_buffer_t *buffer, char *space, struct isapnp_mem *mem)
+{
+	char *s;
+
+	isapnp_printf(buffer, "%sMemory 0x%x-0x%x, align 0x%x, size 0x%x",
+			space, mem->min, mem->max, mem->align, mem->size);
+	if (mem->flags & DEVICE_IO_FLAG_WRITEABLE)
+		isapnp_printf(buffer, ", writeable");
+	if (mem->flags & DEVICE_IO_FLAG_CACHEABLE)
+		isapnp_printf(buffer, ", cacheable");
+	if (mem->flags & DEVICE_IO_FLAG_RANGELENGTH)
+		isapnp_printf(buffer, ", range-length");
+	if (mem->flags & DEVICE_IO_FLAG_SHADOWABLE)
+		isapnp_printf(buffer, ", shadowable");
+	if (mem->flags & DEVICE_IO_FLAG_EXPANSIONROM)
+		isapnp_printf(buffer, ", expansion ROM");
+	switch (mem->type) {
+	case DEVICE_IO_TYPE_8BIT:
+		s = "8-bit";
+		break;
+	case DEVICE_IO_TYPE_8AND16BIT:
+		s = "8-bit&16-bit";
+		break;
+	default:
+		s = "16-bit";
+	}
+	isapnp_printf(buffer, ", %s\n", s);
+}
+
+static void isapnp_print_mem32(isapnp_info_buffer_t *buffer, char *space, struct isapnp_mem32 *mem32)
+{
+	int first = 1, i;
+
+	isapnp_printf(buffer, "%s32-bit memory ", space);
+	for (i = 0; i < 17; i++) {
+		if (first) {
+			first = 0;
+		} else {
+			isapnp_printf(buffer, ":");
+		}
+		isapnp_printf(buffer, "%02x", mem32->data[i]);
+	}
+}
+
+static void isapnp_print_resources(isapnp_info_buffer_t *buffer, char *space, struct isapnp_resources *res)
+{
+	char *s;
+	struct isapnp_port *port;
+	struct isapnp_irq *irq;
+	struct isapnp_dma *dma;
+	struct isapnp_mem *mem;
+	struct isapnp_mem32 *mem32;
+
+	switch (res->priority) {
+	case ISAPNP_RES_PRIORITY_PREFERRED:
+		s = "preferred";
+		break;
+	case ISAPNP_RES_PRIORITY_ACCEPTABLE:
+		s = "acceptable";
+		break;
+	case ISAPNP_RES_PRIORITY_FUNCTIONAL:
+		s = "functional";
+		break;
+	default:
+		s = "invalid";
+	}
+	isapnp_printf(buffer, "%sPriority %s\n", space, s);
+	for (port = res->port; port; port = port->next)
+		isapnp_print_port(buffer, space, port);
+	for (irq = res->irq; irq; irq = irq->next)
+		isapnp_print_irq(buffer, space, irq);
+	for (dma = res->dma; dma; dma = dma->next)
+		isapnp_print_dma(buffer, space, dma);
+	for (mem = res->mem; mem; mem = mem->next)
+		isapnp_print_mem(buffer, space, mem);
+	for (mem32 = res->mem32; mem32; mem32 = mem32->next)
+		isapnp_print_mem32(buffer, space, mem32);
+}
+
+static void isapnp_print_configuration(isapnp_info_buffer_t *buffer, struct pci_dev *dev)
+{
+	int i, tmp, next;
+	char *space = "    ";
+
+	isapnp_cfg_begin(dev->bus->number, dev->devfn);
+	isapnp_printf(buffer, "%sDevice is %sactive\n",
+			space, isapnp_read_byte(ISAPNP_CFG_ACTIVATE)?"":"not ");
+	for (i = next = 0; i < 8; i++) {
+		tmp = isapnp_read_word(ISAPNP_CFG_PORT + (i << 1));
+		if (!tmp)
+			continue;
+		if (!next) {
+			isapnp_printf(buffer, "%sActive port ", space);
+			next = 1;
+		}
+		isapnp_printf(buffer, "%s0x%x", i > 0 ? "," : "", tmp);
+	}
+	if (next)
+		isapnp_printf(buffer, "\n");
+	for (i = next = 0; i < 2; i++) {
+		tmp = isapnp_read_word(ISAPNP_CFG_IRQ + (i << 1));
+		if (!(tmp >> 8))
+			continue;
+		if (!next) {
+			isapnp_printf(buffer, "%sActive IRQ ", space);
+			next = 1;
+		}
+		isapnp_printf(buffer, "%s%i", i > 0 ? "," : "", tmp >> 8);
+		if (tmp & 0xff)
+			isapnp_printf(buffer, " [0x%x]", tmp & 0xff);
+	}
+	if (next)
+		isapnp_printf(buffer, "\n");
+	for (i = next = 0; i < 2; i++) {
+		tmp = isapnp_read_byte(ISAPNP_CFG_DMA + i);
+		if (tmp == 4)
+			continue;
+		if (!next) {
+			isapnp_printf(buffer, "%sActive DMA ", space);
+			next = 1;
+		}
+		isapnp_printf(buffer, "%s%i", i > 0 ? "," : "", tmp);
+	}
+	if (next)
+		isapnp_printf(buffer, "\n");
+	for (i = next = 0; i < 4; i++) {
+		tmp = isapnp_read_dword(ISAPNP_CFG_MEM + (i << 3));
+		if (!tmp)
+			continue;
+		if (!next) {
+			isapnp_printf(buffer, "%sActive memory ", space);
+			next = 1;
+		}
+		isapnp_printf(buffer, "%s0x%x", i > 0 ? "," : "", tmp);
+	}
+	if (next)
+		isapnp_printf(buffer, "\n");
+	isapnp_cfg_end();
+}
+
+static void isapnp_print_device(isapnp_info_buffer_t *buffer, struct pci_dev *dev)
+{
+	int block, block1;
+	char *space = "    ";
+	struct isapnp_resources *res, *resa;
+
+	if (!dev)
+		return;
+	isapnp_printf(buffer, "  Logical device %i '", dev->devfn);
+	isapnp_print_devid(buffer, dev->vendor, dev->device);
+	isapnp_printf(buffer, ":%s'", dev->name[0]?dev->name:"Unknown");
+	isapnp_printf(buffer, "\n");
+#if 0
+	isapnp_cfg_begin(dev->bus->number, dev->devfn);
+	for (block = 0; block < 128; block++)
+		if ((block % 16) == 15)
+			isapnp_printf(buffer, "%02x\n", isapnp_read_byte(block));
+		else
+			isapnp_printf(buffer, "%02x:", isapnp_read_byte(block));
+	isapnp_cfg_end();
+#endif
+	if (dev->regs)
+		isapnp_printf(buffer, "%sSupported registers 0x%x\n", space, dev->regs);
+	isapnp_print_compatible(buffer, dev);
+	isapnp_print_configuration(buffer, dev);
+	for (res = (struct isapnp_resources *)dev->sysdata, block = 0; res; res = res->next, block++) {
+		isapnp_printf(buffer, "%sResources %i\n", space, block);
+		isapnp_print_resources(buffer, "      ", res);
+		for (resa = res->alt, block1 = 1; resa; resa = resa->alt, block1++) {
+			isapnp_printf(buffer, "%s  Alternate resources %i:%i\n", space, block, block1);
+			isapnp_print_resources(buffer, "        ", resa);
+		}
+	}
+}
+
+/*
+ *  Main read routine
+ */
+ 
+static void isapnp_info_read(isapnp_info_buffer_t *buffer)
+{
+	struct pci_bus *card;
+	struct pci_dev *dev;
+	
+	for (card = isapnp_cards; card; card = card->next) {
+		isapnp_printf(buffer, "Card %i '", card->number);
+		isapnp_print_devid(buffer, card->vendor, card->device);
+		isapnp_printf(buffer, ":%s'", card->name[0]?card->name:"Unknown");
+		if (card->pnpver)
+			isapnp_printf(buffer, " PnP version %x.%x", card->pnpver >> 4, card->pnpver & 0x0f);
+		if (card->productver)
+			isapnp_printf(buffer, " Product version %x.%x", card->productver >> 4, card->productver & 0x0f);
+		isapnp_printf(buffer,"\n");
+		for (dev = card->devices; dev; dev = dev->sibling)
+			isapnp_print_device(buffer, dev);
+	}
+}
+
+/*
+ *
+ */
+
+static struct pci_bus *isapnp_info_card;
+static struct pci_dev *isapnp_info_device;
+
+static char *isapnp_get_str(char *dest, char *src, int len)
+{
+	int c;
+
+	while (*src == ' ' || *src == '\t')
+		src++;
+	if (*src == '"' || *src == '\'') {
+		c = *src++;
+		while (--len > 0 && *src && *src != c) {
+			*dest++ = *src++;
+		}
+		if (*src == c)
+			src++;
+	} else {
+		while (--len > 0 && *src && *src != ' ' && *src != '\t') {
+			*dest++ = *src++;
+		}
+	}
+	*dest = 0;
+	while (*src == ' ' || *src == '\t')
+		src++;
+	return src;
+}
+
+static unsigned char isapnp_get_hex(unsigned char c)
+{
+	if (c >= '0' || c <= '9')
+		return c - '0';
+	if (c >= 'a' || c <= 'f')
+		return (c - 'a') + 10;
+	if (c >= 'A' || c <= 'F')
+		return (c - 'A') + 10;
+	return 0;
+}
+
+static unsigned int isapnp_parse_id(const char *id)
+{
+	if (strlen(id) != 7) {
+		printk("isapnp: wrong PnP ID\n");
+		return 0;
+	}
+	return (ISAPNP_VENDOR(id[0], id[1], id[2])<<16) |
+			(isapnp_get_hex(id[3])<<4) |
+			(isapnp_get_hex(id[4])<<0) |
+			(isapnp_get_hex(id[5])<<12) |
+			(isapnp_get_hex(id[6])<<8);
+}
+
+static int isapnp_set_card(char *line)
+{
+	int idx, idx1;
+	unsigned int id;
+	char index[16], value[32];
+
+	isapnp_info_card = NULL;
+	line = isapnp_get_str(index, line, sizeof(index));
+	isapnp_get_str(value, line, sizeof(value));
+	idx = idx1 = simple_strtoul(index, NULL, 0);
+	id = isapnp_parse_id(value);
+	isapnp_info_card = isapnp_find_card(id >> 16, id & 0xffff, NULL);
+	while (isapnp_info_card && idx1-- > 0)
+		isapnp_info_card = isapnp_find_card(id >> 16, id & 0xffff, isapnp_info_card);
+	if (isapnp_info_card == NULL) {
+		printk("isapnp: card '%s' order %i not found\n", value, idx);
+		return 1;
+	}
+	if (isapnp_cfg_begin(isapnp_info_card->number, -1)<0) {
+		printk("isapnp: configuration start sequence for device '%s' failed\n", value);
+		isapnp_info_card = NULL;
+		return 1;
+	}
+	return 0;
+}
+
+static int isapnp_select_csn(char *line)
+{
+	int csn;
+	char index[16], value[32];
+
+	isapnp_info_device = NULL;
+	isapnp_get_str(index, line, sizeof(index));
+	csn = simple_strtoul(index, NULL, 0);
+	for (isapnp_info_card = isapnp_cards; isapnp_info_card; isapnp_info_card = isapnp_info_card->next)
+		if (isapnp_info_card->number == csn)
+			break;
+	if (isapnp_info_card == NULL) {
+		printk("isapnp: cannot find CSN %i\n", csn);
+		return 1;
+	}
+	if (isapnp_cfg_begin(isapnp_info_card->number, -1)<0) {
+		printk("isapnp: configuration start sequence for device '%s' failed\n", value);
+		isapnp_info_card = NULL;
+		return 1;
+	}
+	return 0;
+}
+
+static int isapnp_set_device(char *line)
+{
+	int idx, idx1;
+	unsigned int id;
+	char index[16], value[32];
+
+	line = isapnp_get_str(index, line, sizeof(index));
+	isapnp_get_str(value, line, sizeof(value));
+	idx = idx1 = simple_strtoul(index, NULL, 0);
+	id = isapnp_parse_id(value);
+	isapnp_info_device = isapnp_find_dev(isapnp_info_card, id >> 16, id & 0xffff, NULL);
+	while (isapnp_info_device && idx-- > 0)
+		isapnp_info_device = isapnp_find_dev(isapnp_info_card, id >> 16, id & 0xffff, isapnp_info_device);
+	if (isapnp_info_device == NULL) {
+		printk("isapnp: device '%s' order %i not found\n", value, idx);
+		return 1;
+	}
+	isapnp_device(isapnp_info_device->devfn);
+	return 0;
+}
+
+static int isapnp_autoconfigure(void)
+{
+	if (isapnp_info_device == NULL) {
+		printk("isapnp: device is not set\n");
+		return 0;
+	}
+	if (isapnp_info_device->active)
+		isapnp_info_device->deactivate(isapnp_info_device);
+	if (isapnp_info_device->prepare(isapnp_info_device) < 0) {
+		printk("isapnp: cannot prepare device for the activation");
+		return 0;
+	}
+	if (isapnp_info_device->activate(isapnp_info_device) < 0) {
+		printk("isapnp: cannot activate device");
+		return 0;
+	}
+	return 0;
+}
+
+static int isapnp_set_port(char *line)
+{
+	int idx, port;
+	char index[16], value[32];
+
+	line = isapnp_get_str(index, line, sizeof(index));
+	isapnp_get_str(value, line, sizeof(value));
+	idx = simple_strtoul(index, NULL, 0);
+	port = simple_strtoul(value, NULL, 0);
+	if (idx < 0 || idx > 7) {
+		printk("isapnp: wrong port index %i\n", idx);
+		return 1;
+	}
+	if (port < 0 || port > 0xffff) {
+		printk("isapnp: wrong port value 0x%x\n", port);
+		return 1;
+	}
+	isapnp_write_word(ISAPNP_CFG_PORT + (idx << 1), port);
+	if (isapnp_info_device->resource[idx].start == DEVICE_IO_NOTSET)
+		return 0;
+	if (isapnp_info_device->resource[idx].start == DEVICE_IO_AUTO) {
+		isapnp_info_device->resource[idx].start = port;
+		isapnp_info_device->resource[idx].end += port - 1;
+	} else {
+		isapnp_info_device->resource[idx].end -= isapnp_info_device->resource[idx].start;
+		isapnp_info_device->resource[idx].start = port;
+		isapnp_info_device->resource[idx].end += port;
+	}
+	return 0;
+}
+ 
+static int isapnp_set_irq(char *line)
+{
+	int idx, irq;
+	char index[16], value[32];
+
+	line = isapnp_get_str(index, line, sizeof(index));
+	isapnp_get_str(value, line, sizeof(value));
+	idx = simple_strtoul(index, NULL, 0);
+	irq = simple_strtoul(value, NULL, 0);
+	if (idx < 0 || idx > 1) {
+		printk("isapnp: wrong IRQ index %i\n", idx);
+		return 1;
+	}
+	if (irq == 2)
+		irq = 9;
+	if (irq < 0 || irq > 15) {
+		printk("isapnp: wrong IRQ value %i\n", irq);
+		return 1;
+	}
+	isapnp_write_byte(ISAPNP_CFG_IRQ + (idx << 1), irq);
+	if (idx == 0) {
+		 if (isapnp_info_device->irq == DEVICE_IRQ_NOTSET)
+		 	return 0;
+		 isapnp_info_device->irq = irq;
+	} else {
+		 if (isapnp_info_device->irq2 == DEVICE_IRQ_NOTSET)
+		 	return 0;
+		 isapnp_info_device->irq2 = irq;	
+	}
+	return 0;
+}
+ 
+static int isapnp_set_dma(char *line)
+{
+	int idx, dma;
+	char index[16], value[32];
+
+	line = isapnp_get_str(index, line, sizeof(index));
+	isapnp_get_str(value, line, sizeof(value));
+	idx = simple_strtoul(index, NULL, 0);
+	dma = simple_strtoul(value, NULL, 0);
+	if (idx < 0 || idx > 1) {
+		printk("isapnp: wrong DMA index %i\n", idx);
+		return 1;
+	}
+	if (dma < 0 || dma > 7) {
+		printk("isapnp: wrong DMA value %i\n", dma);
+		return 1;
+	}
+	isapnp_write_byte(ISAPNP_CFG_DMA + idx, dma);
+	if (isapnp_info_device->dma[idx] == DEVICE_DMA_NOTSET)
+		return 0;
+	isapnp_info_device->dma[idx] = dma;
+	return 0;
+}
+ 
+static int isapnp_set_mem(char *line)
+{
+	int idx;
+	unsigned int mem;
+	char index[16], value[32];
+
+	line = isapnp_get_str(index, line, sizeof(index));
+	isapnp_get_str(value, line, sizeof(value));
+	idx = simple_strtoul(index, NULL, 0);
+	mem = simple_strtoul(value, NULL, 0);
+	if (idx < 0 || idx > 3) {
+		printk("isapnp: wrong memory index %i\n", idx);
+		return 1;
+	}
+	mem >>= 8;
+	isapnp_write_word(ISAPNP_CFG_MEM + (idx<<2), mem & 0xffff);
+	if (isapnp_info_device->resource[idx + 8].start == DEVICE_IO_NOTSET)
+		return 0;
+	if (isapnp_info_device->resource[idx + 8].start == DEVICE_IO_AUTO) {
+		isapnp_info_device->resource[idx + 8].start = mem & ~0x00ffff00;
+		isapnp_info_device->resource[idx + 8].end += (mem & ~0x00ffff00) - 1;
+	} else {
+		isapnp_info_device->resource[idx + 8].end -= isapnp_info_device->resource[idx + 8].start;
+		isapnp_info_device->resource[idx + 8].start = mem & ~0x00ffff00;
+		isapnp_info_device->resource[idx + 8].end += mem & ~0x00ffff00;
+	}
+	return 0;
+}
+ 
+static int isapnp_poke(char *line, int what)
+{
+	int reg;
+	unsigned int val;
+	char index[16], value[32];
+
+	line = isapnp_get_str(index, line, sizeof(index));
+	isapnp_get_str(value, line, sizeof(value));
+	reg = simple_strtoul(index, NULL, 0);
+	val = simple_strtoul(value, NULL, 0);
+	if (reg < 0 || reg > 127) {
+		printk("isapnp: wrong register %i\n", reg);
+		return 1;
+	}
+	switch (what) {
+	case 1:
+		isapnp_write_word(reg, val);
+		break;
+	case 2:
+		isapnp_write_dword(reg, val);
+		break;
+	default:
+		isapnp_write_byte(reg, val);
+		break;
+	}
+	return 0;
+}
+ 
+static int isapnp_decode_line(char *line)
+{
+	char cmd[32];
+
+	line = isapnp_get_str(cmd, line, sizeof(cmd));
+	if (!strcmp(cmd, "card"))
+		return isapnp_set_card(line);
+	if (!strcmp(cmd, "csn"))
+		return isapnp_select_csn(line);
+	if (!isapnp_info_card) {
+		printk("isapnp: card is not selected\n");
+		return 1;
+	}
+	if (!strncmp(cmd, "dev", 3))
+		return isapnp_set_device(line);
+	if (!isapnp_info_device) {
+		printk("isapnp: device is not selected\n");
+		return 1;
+	}
+	if (!strncmp(cmd, "auto", 4))
+		return isapnp_autoconfigure();
+	if (!strncmp(cmd, "act", 3)) {
+		isapnp_activate(isapnp_info_device->devfn);
+		isapnp_info_device->active = 1;
+		return 0;
+	}
+	if (!strncmp(cmd, "deact", 5)) {
+		isapnp_deactivate(isapnp_info_device->devfn);
+		isapnp_info_device->active = 0;
+		return 0;
+	}
+	if (!strcmp(cmd, "port"))
+		return isapnp_set_port(line);
+	if (!strcmp(cmd, "irq"))
+		return isapnp_set_irq(line);
+	if (!strcmp(cmd, "dma"))
+		return isapnp_set_dma(line);
+	if (!strncmp(cmd, "mem", 3))
+		return isapnp_set_mem(line);
+	if (!strcmp(cmd, "poke"))
+		return isapnp_poke(line, 0);
+	if (!strcmp(cmd, "pokew"))
+		return isapnp_poke(line, 1);
+	if (!strcmp(cmd, "poked"))
+		return isapnp_poke(line, 2);
+	printk("isapnp: wrong command '%s'\n", cmd);
+	return 1;
+}
+
+/*
+ *  Main write routine
+ */
+
+static void isapnp_info_write(isapnp_info_buffer_t *buffer)
+{
+	int c, idx, idx1 = 0;
+	char line[128];
+
+	if (buffer->size <= 0)
+		return;
+	isapnp_info_card = NULL;
+	isapnp_info_device = NULL;
+	for (idx = 0; idx < buffer->size; idx++) {
+		c = buffer->buffer[idx];
+		if (c == '\n') {
+			line[idx1] = '\0';
+			if (line[0] != '#') {
+				if (isapnp_decode_line(line))
+					goto __end;
+			}
+			idx1 = 0;
+			continue;
+		}
+		if (idx1 >= sizeof(line)-1) {
+			printk("isapnp: line too long, aborting\n");
+			return;
+		}
+		line[idx1++] = c;
+	}
+      __end:
+	if (isapnp_info_card)
+		isapnp_cfg_end();
+}
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/53c7xx.c linux/drivers/scsi/53c7xx.c
--- v2.3.13/linux/drivers/scsi/53c7xx.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/scsi/53c7xx.c	Sun Aug 15 11:48:32 1999
@@ -1074,7 +1074,7 @@
 
     NCR53c7x0_driver_init (host);
 
-    if (request_irq(host->irq, NCR53c7x0_intr, 0, "53c7xx", host))
+    if (request_irq(host->irq, NCR53c7x0_intr, SA_SHIRQ, "53c7xx", host))
     {
 	printk("scsi%d : IRQ%d not free, detaching\n",
 		host->host_no, host->irq);
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/BusLogic.c linux/drivers/scsi/BusLogic.c
--- v2.3.13/linux/drivers/scsi/BusLogic.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/scsi/BusLogic.c	Thu Aug 12 10:31:05 1999
@@ -783,12 +783,10 @@
       unsigned int IRQ_Channel = PCI_Device->irq;
       unsigned long BaseAddress0 = PCI_Device->resource[0].start;
       unsigned long BaseAddress1 = PCI_Device->resource[1].start;
-      BusLogic_IO_Address_T IO_Address =
-	BaseAddress0 & PCI_BASE_ADDRESS_IO_MASK;
-      BusLogic_PCI_Address_T PCI_Address =
-	BaseAddress1 & PCI_BASE_ADDRESS_MEM_MASK;
-      if ((BaseAddress0 & PCI_BASE_ADDRESS_SPACE)
-	  != PCI_BASE_ADDRESS_SPACE_IO)
+      BusLogic_IO_Address_T IO_Address = BaseAddress0;
+      BusLogic_PCI_Address_T PCI_Address = BaseAddress1;
+      
+      if (!(PCI_Device->resource[0].flags & PCI_BASE_ADDRESS_SPACE_IO))
 	{
 	  BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for "
 			 "MultiMaster Host Adapter\n", NULL, BaseAddress0);
@@ -796,8 +794,7 @@
 			 NULL, Bus, Device, IO_Address);
 	  continue;
 	}
-      if ((BaseAddress1 & PCI_BASE_ADDRESS_SPACE)
-	  != PCI_BASE_ADDRESS_SPACE_MEMORY)
+      if (PCI_Device->resource[1].flags & PCI_BASE_ADDRESS_SPACE_IO)
 	{
 	  BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for "
 			 "MultiMaster Host Adapter\n", NULL, BaseAddress1);
@@ -986,8 +983,8 @@
       unsigned char Bus = PCI_Device->bus->number;
       unsigned char Device = PCI_Device->devfn >> 3;
       unsigned int IRQ_Channel = PCI_Device->irq;
-      BusLogic_IO_Address_T IO_Address =
-	PCI_Device->resource[0].start & PCI_BASE_ADDRESS_IO_MASK;
+      BusLogic_IO_Address_T IO_Address = PCI_Device->resource[0].start;
+
       if (IO_Address == 0 || IRQ_Channel == 0) continue;
       for (i = 0; i < BusLogic_ProbeInfoCount; i++)
 	{
@@ -1032,13 +1029,10 @@
       unsigned int IRQ_Channel = PCI_Device->irq;
       unsigned long BaseAddress0 = PCI_Device->resource[0].start;
       unsigned long BaseAddress1 = PCI_Device->resource[1].start;
-      BusLogic_IO_Address_T IO_Address =
-	BaseAddress0 & PCI_BASE_ADDRESS_IO_MASK;
-      BusLogic_PCI_Address_T PCI_Address =
-	BaseAddress1 & PCI_BASE_ADDRESS_MEM_MASK;
+      BusLogic_IO_Address_T IO_Address = BaseAddress0;
+      BusLogic_PCI_Address_T PCI_Address = BaseAddress1;
 #ifndef CONFIG_SCSI_OMIT_FLASHPOINT
-      if ((BaseAddress0 & PCI_BASE_ADDRESS_SPACE)
-	  != PCI_BASE_ADDRESS_SPACE_IO)
+      if (!(PCI_Device->resource[0].flags & PCI_BASE_ADDRESS_SPACE_IO))
 	{
 	  BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for "
 			 "FlashPoint Host Adapter\n", NULL, BaseAddress0);
@@ -1046,8 +1040,7 @@
 			 NULL, Bus, Device, IO_Address);
 	  continue;
 	}
-      if ((BaseAddress1 & PCI_BASE_ADDRESS_SPACE)
-	  != PCI_BASE_ADDRESS_SPACE_MEMORY)
+      if (PCI_Device->resource[1].flags & PCI_BASE_ADDRESS_SPACE_IO)
 	{
 	  BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for "
 			 "FlashPoint Host Adapter\n", NULL, BaseAddress1);
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile
--- v2.3.13/linux/drivers/scsi/Makefile	Thu Apr 29 11:53:41 1999
+++ linux/drivers/scsi/Makefile	Wed Aug 18 10:00:52 1999
@@ -18,7 +18,7 @@
 CFLAGS_seagate.o =   -DARBITRATE -DPARITY -DSEAGATE_USE_ASM
 
 .SUFFIXES:
-.SUFFIXES: .c .o .h .a
+.SUFFIXES: .c .o .h .a .S
 
 ifeq (${CFLAGS},)
 CFLAGS = -D__KERNEL__=1 \
@@ -241,6 +241,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_OKTAGON_SCSI),y)
+L_OBJS += NCR53C9x.o oktagon_esp.o oktagon_io.o
+else
+  ifeq ($(CONFIG_OKTAGON_SCSI),m)
+  M_OBJS += NCR53C9x.o oktagon_esp.o oktagon_io.o
+  endif
+endif
+
 ifeq ($(CONFIG_ATARI_SCSI),y)
 L_OBJS += atari_scsi.o
 else
@@ -249,6 +257,22 @@
   endif
 endif
 
+ifeq ($(CONFIG_MAC_SCSI_OLD),y)
+L_OBJS += mac_scsi.o
+else
+  ifeq ($(CONFIG_MAC_SCSI_OLD),m)
+  M_OBJS += mac_scsi.o
+  endif
+endif
+
+ifeq ($(CONFIG_SCSI_MAC_ESP),y)
+L_OBJS += mac_esp.o NCR53C9x.o
+else
+	ifeq ($(CONFIG_SCSI_MAC_ESP),m)
+	M_OBJS += mac_esp.o NCR53C9x.o
+	endif
+endif
+
 ifeq ($(CONFIG_SCSI_PPA),y)
 L_OBJS += ppa.o
 else
@@ -623,6 +647,10 @@
 L_OBJS += NCR53C9x.o jazz_esp.o
 endif
 
+ifeq ($(CONFIG_SUN3X_ESP),y)
+L_OBJS += NCR53C9x.o sun3x_esp.o
+endif
+
 include $(TOPDIR)/Rules.make
 
 53c8xx_d.h: 53c7,8xx.scr script_asm.pl
@@ -643,8 +671,7 @@
 
 53c7xx_u.h: 53c7xx_d.h
 
-53c7xx.o : 53c7xx_d.h 53c7xx.c
-	$(CC) $(CFLAGS) -c 53c7xx.c
+53c7xx.o : 53c7xx_d.h
 
 initio.o: ini9100u.c i91uscsi.c
 	$(CC) $(CFLAGS) -c ini9100u.c -o ini9100u.o
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/NCR53C9x.c linux/drivers/scsi/NCR53C9x.c
--- v2.3.13/linux/drivers/scsi/NCR53C9x.c	Thu Jul  8 15:42:20 1999
+++ linux/drivers/scsi/NCR53C9x.c	Thu Aug 12 10:28:34 1999
@@ -2,12 +2,12 @@
  *
  * Originally esp.c : EnhancedScsiProcessor Sun SCSI driver code.
  *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995, 1998 David S. Miller (davem@caip.rutgers.edu)
  *
  * Most DMA dependencies put in driver specific files by 
  * Jesper Skov (jskov@cygnus.co.uk)
  *
- * Set up to use GETREG/SETREG (preprocessor macros in NCR53c9x.h) by
+ * Set up to use esp_read/esp_write (preprocessor macros in NCR53c9x.h) by
  * Tymm Twillman (tymm@coe.missouri.edu)
  */
 
@@ -21,6 +21,10 @@
  * 4) Maybe change use of "esp" to something more "NCR"'ish.
  */
 
+#ifdef MODULE
+#include <linux/module.h>
+#endif
+
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
@@ -30,28 +34,12 @@
 #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"
 
-#ifdef CONFIG_SCSI_SUNESP
-#include "sparc_esp.h"
-#include <asm/sbus.h>
-#include <asm/dma.h>
-#include <asm/machines.h>
-#include <asm/oplib.h>
-#include <asm/idprom.h>
-#endif
-
-#if defined(CONFIG_BLZ1230_SCSI)||defined(CONFIG_BLZ2060_SCSI)||defined(CONFIG_CYBERSTORMII_SCSI)
-#define SYMBIOS_HACK
-#else
-#undef SYMBIOS_HACK
-#endif
-
 #include <asm/system.h>
 #include <asm/ptrace.h>
 #include <asm/pgtable.h>
@@ -95,6 +83,17 @@
 	in_tgterror   = 0x84,  /* Target did something stupid           */
 };
 
+enum {
+	/* Zero has special meaning, see skipahead[12]. */
+/*0*/	do_never,
+
+/*1*/	do_phase_determine,
+/*2*/	do_reset_bus,
+/*3*/	do_reset_complete,
+/*4*/	do_work_bus,
+/*5*/	do_intr_end
+};
+
 struct proc_dir_entry proc_scsi_esp = {
 	PROC_SCSI_ESP, 3, "esp",
 	S_IFDIR | S_IRUGO | S_IXUGO, 2
@@ -227,7 +226,6 @@
 		    "UNKNOWN"))))));
 }
 
-#if defined(DEBUG_STATE_MACHINE) || defined(DEBUG_ESP)
 static char *phase_string(int phase)
 {
 	switch(phase) {
@@ -283,26 +281,31 @@
 		return "UNKNOWN";
 	};
 }
-#endif
 
+#ifdef DEBUG_STATE_MACHINE
 static inline void esp_advance_phase(Scsi_Cmnd *s, int newphase)
 {
-#ifdef DEBUG_STATE_MACHINE
 	ESPLOG(("<%s>", phase_string(newphase)));
-#endif
 	s->SCp.sent_command = s->SCp.phase;
 	s->SCp.phase = newphase;
 }
+#else
+#define esp_advance_phase(__s, __newphase) \
+	(__s)->SCp.sent_command = (__s)->SCp.phase; \
+	(__s)->SCp.phase = (__newphase);
+#endif
 
+#ifdef DEBUG_ESP_CMDS
 extern inline void esp_cmd(struct NCR_ESP *esp, struct ESP_regs *eregs,
 			   unchar cmd)
 {
-#ifdef DEBUG_ESP_CMDS
 	esp->espcmdlog[esp->espcmdent] = cmd;
 	esp->espcmdent = (esp->espcmdent + 1) & 31;
-#endif
-	SETREG(eregs->esp_cmnd, cmd);
+	esp_write(eregs->esp_cmnd, cmd);
 }
+#else
+#define esp_cmd(__esp, __eregs, __cmd)	esp_write((__eregs)->esp_cmnd, (__cmd))
+#endif
 
 /* How we use the various Linux SCSI data structures for operation.
  *
@@ -320,7 +323,6 @@
  *   the disconnect flag.
  */
 
-
 /* Manipulation of the ESP command queues.  Thanks to the aha152x driver
  * and its author, Juergen E. Fischer, for the methods used here.
  * Note that these are per-ESP queues, not global queues like
@@ -329,9 +331,7 @@
 static inline void append_SC(Scsi_Cmnd **SC, Scsi_Cmnd *new_SC)
 {
 	Scsi_Cmnd *end;
-	unsigned long flags;
 
-	save_flags(flags); cli();
 	new_SC->host_scribble = (unsigned char *) NULL;
 	if(!*SC)
 		*SC = new_SC;
@@ -340,38 +340,28 @@
 			;
 		end->host_scribble = (unsigned char *) new_SC;
 	}
-	restore_flags(flags);
 }
 
 static inline void prepend_SC(Scsi_Cmnd **SC, Scsi_Cmnd *new_SC)
 {
-	unsigned long flags;
-
-	save_flags(flags); cli();
 	new_SC->host_scribble = (unsigned char *) *SC;
 	*SC = new_SC;
-	restore_flags(flags);
 }
 
 static inline Scsi_Cmnd *remove_first_SC(Scsi_Cmnd **SC)
 {
 	Scsi_Cmnd *ptr;
-	unsigned long flags;
 
-	save_flags(flags); cli();
 	ptr = *SC;
 	if(ptr)
 		*SC = (Scsi_Cmnd *) (*SC)->host_scribble;
-	restore_flags(flags);
 	return ptr;
 }
 
 static inline Scsi_Cmnd *remove_SC(Scsi_Cmnd **SC, int target, int lun)
 {
 	Scsi_Cmnd *ptr, *prev;
-	unsigned long flags;
 
-	save_flags(flags); cli();
 	for(ptr = *SC, prev = NULL;
 	    ptr && ((ptr->target != target) || (ptr->lun != lun));
 	    prev = ptr, ptr = (Scsi_Cmnd *) ptr->host_scribble)
@@ -382,14 +372,13 @@
 		else
 			*SC=(Scsi_Cmnd *)ptr->host_scribble;
 	}
-	restore_flags(flags);
 	return ptr;
 }
 
 /* Resetting various pieces of the ESP scsi driver chipset */
 
 /* Reset the ESP chip, _not_ the SCSI bus. */
-static inline void esp_reset_esp(struct NCR_ESP *esp, struct ESP_regs *eregs)
+static void esp_reset_esp(struct NCR_ESP *esp, struct ESP_regs *eregs)
 {
 	int family_code, version, i;
 	volatile int trash;
@@ -397,6 +386,8 @@
 	/* Now reset the ESP chip */
 	esp_cmd(esp, eregs, ESP_CMD_RC);
 	esp_cmd(esp, eregs, ESP_CMD_NULL | ESP_CMD_DMA);
+	if(esp->erev == fast)
+		esp_write(eregs->esp_cfg2, ESP_CONFIG2_FENAB);
 	esp_cmd(esp, eregs, ESP_CMD_NULL | ESP_CMD_DMA);
 
 	/* This is the only point at which it is reliable to read
@@ -404,31 +395,45 @@
 	 */
 	esp->max_period = ((35 * esp->ccycle) / 1000);
 	if(esp->erev == fast) {
-		version = GETREG(eregs->esp_uid);
+		char *erev2string[] = {
+			"Emulex FAS236",
+			"Emulex FPESP100A",
+			"fast",
+			"QLogic FAS366",
+			"Emulex FAS216",
+			"Symbios Logic 53CF9x-2",
+			"unknown!"
+		};
+			
+		version = esp_read(eregs->esp_uid);
 		family_code = (version & 0xf8) >> 3;
-#ifdef SYMBIOS_HACK
-		if (version == 0 && family_code == 0)
-		  {
-		    printk ("Detected SymBIOS chip with no family code.\n");
-		    version = 3;
-		    family_code = 2;
-		  }
-#endif
-		if(family_code == 0x02)
+		if(family_code == 0x02) {
 		        if ((version & 7) == 2)
 			        esp->erev = fas216;	
                         else
 			        esp->erev = fas236;
-		else if(family_code == 0x0a)
-			esp->erev = fashme; /* Version is usually '5'. */
-		else
-			esp->erev = fas100a;
-		printk("esp%d: FAST chip is %s (family=%d, version=%d)\n",
-		       esp->esp_id,
-		       (esp->erev == fas236) ? "fas236" :
-		       ((esp->erev == fas216) ? "fas216" :		       
-		       (((esp->erev == fas100a) ? "fas100a" :
-		       "fasHME"))), family_code, (version & 7));
+		} else if(family_code == 0x0a)
+			esp->erev = fas366; /* Version is usually '5'. */
+		else if(family_code == 0x00) {
+			if ((version & 7) == 2)
+				esp->erev = fas100a; /* NCR53C9X */
+			else
+				esp->erev = espunknown;
+		} else if(family_code == 0x14) {
+			if ((version & 7) == 2)
+				esp->erev = fsc;
+		        else
+				esp->erev = espunknown;
+		} else if(family_code == 0x00) {
+			if ((version & 7) == 2)
+				esp->erev = fas100a; /* NCR53C9X */
+			else
+				esp->erev = espunknown;
+		} else
+			esp->erev = espunknown;
+		ESPLOG(("esp%d: FAST chip is %s (family=%d, version=%d)\n",
+			esp->esp_id, erev2string[esp->erev - fas236],
+			family_code, (version & 7)));
 
 		esp->min_period = ((4 * esp->ccycle) / 1000);
 	} else {
@@ -436,56 +441,63 @@
 	}
 
 	/* Reload the configuration registers */
-	SETREG(eregs->esp_cfact, esp->cfact);
-	SETREG(eregs->esp_stp, 0);
-	SETREG(eregs->esp_soff, 0);
-	SETREG(eregs->esp_timeo, esp->neg_defp);
+	esp_write(eregs->esp_cfact, esp->cfact);
+	esp->prev_stp = 0;
+	esp_write(eregs->esp_stp, 0);
+	esp->prev_soff = 0;
+	esp_write(eregs->esp_soff, 0);
+	esp_write(eregs->esp_timeo, esp->neg_defp);
 	esp->max_period = (esp->max_period + 3)>>2;
 	esp->min_period = (esp->min_period + 3)>>2;
 
-	SETREG(eregs->esp_cfg1, esp->config1);
+	esp_write(eregs->esp_cfg1, esp->config1);
 	switch(esp->erev) {
 	case esp100:
 		/* nothing to do */
 		break;
 	case esp100a:
-		SETREG(eregs->esp_cfg2, esp->config2);
+		esp_write(eregs->esp_cfg2, esp->config2);
 		break;
 	case esp236:
 		/* Slow 236 */
-		SETREG(eregs->esp_cfg2, esp->config2);
-		SETREG(eregs->esp_cfg3, esp->config3[0]);
+		esp_write(eregs->esp_cfg2, esp->config2);
+		esp->prev_cfg3 = esp->config3[0];
+		esp_write(eregs->esp_cfg3, esp->prev_cfg3);
+		break;
+	case fas366:
+		panic("esp: FAS366 support not present, please notify "
+		      "jongk@cs.utwente.nl");
 		break;
-	case fashme:
-		esp->config2 |= (ESP_CONFIG2_HME32 | ESP_CONFIG2_HMEFENAB);
-		/* fallthrough... */
-	case fas216:	    
+	case fas216:
 	case fas236:
-		/* Fast 236 or HME */
-		SETREG(eregs->esp_cfg2, esp->config2);
-		for(i=0; i<8; i++) {
-			if(esp->erev == fashme)
-				esp->config3[i] |=
-					(ESP_CONFIG3_FCLOCK | ESP_CONFIG3_BIGID | ESP_CONFIG3_OBPUSH);
-			else
-				esp->config3[i] |= ESP_CONFIG3_FCLK;
-		}
-		SETREG(eregs->esp_cfg3, esp->config3[0]);
-		if(esp->erev == fashme) {
-			esp->radelay = 80;
-		} else {
-			if(esp->diff)
-				esp->radelay = 0;
-			else
-				esp->radelay = 96;
-		}
+	case fsc:
+		/* Fast ESP variants */
+		esp_write(eregs->esp_cfg2, esp->config2);
+		for(i=0; i<8; i++)
+			esp->config3[i] |= ESP_CONFIG3_FCLK;
+		esp->prev_cfg3 = esp->config3[0];
+		esp_write(eregs->esp_cfg3, esp->prev_cfg3);
+		if(esp->diff)
+			esp->radelay = 0;
+		else
+			esp->radelay = 16;
+		/* Different timeout constant for these chips */
+		esp->neg_defp =
+			FSC_NEG_DEFP(esp->cfreq,
+				     (esp->cfact == ESP_CCF_F0 ?
+				      ESP_CCF_F7 + 1 : esp->cfact));
+		esp_write(eregs->esp_timeo, esp->neg_defp);
+		/* Enable Active Negotiation if possible */
+		if((esp->erev == fsc) && !esp->diff)
+			esp_write(eregs->esp_cfg4, ESP_CONFIG4_EAN);
 		break;
 	case fas100a:
 		/* Fast 100a */
-		SETREG(eregs->esp_cfg2, esp->config2);
+		esp_write(eregs->esp_cfg2, esp->config2);
 		for(i=0; i<8; i++)
 			esp->config3[i] |= ESP_CONFIG3_FCLOCK;
-		SETREG(eregs->esp_cfg3, esp->config3[0]);
+		esp->prev_cfg3 = esp->config3[0];
+		esp_write(eregs->esp_cfg3, esp->prev_cfg3);
 		esp->radelay = 32;
 		break;
 	default:
@@ -494,12 +506,12 @@
 	};
 
 	/* Eat any bitrot in the chip */
-	trash = GETREG(eregs->esp_intrpt);
+	trash = esp_read(eregs->esp_intrpt);
 	udelay(100);
 }
 
 /* This places the ESP into a known state at boot time. */
-inline void esp_bootup_reset(struct NCR_ESP *esp, struct ESP_regs *eregs)
+void esp_bootup_reset(struct NCR_ESP *esp, struct ESP_regs *eregs)
 {
 	volatile unchar trash;
 
@@ -511,13 +523,13 @@
 	esp_reset_esp(esp, eregs);
 
 	/* Reset the SCSI bus, but tell ESP not to generate an irq */
-	SETREG(eregs->esp_cfg1, GETREG(eregs->esp_cfg1) | ESP_CONFIG1_SRRDISAB);
+	esp_write(eregs->esp_cfg1, (esp_read(eregs->esp_cfg1) | ESP_CONFIG1_SRRDISAB));
 	esp_cmd(esp, eregs, ESP_CMD_RS);
 	udelay(400);
-	SETREG(eregs->esp_cfg1, esp->config1);
+	esp_write(eregs->esp_cfg1, esp->config1);
 
 	/* Eat any bitrot in the chip and we are done... */
-	trash = GETREG(eregs->esp_intrpt);
+	trash = esp_read(eregs->esp_intrpt);
 }
 
 /* Allocate structure and insert basic data such as SCSI chip frequency
@@ -538,6 +550,9 @@
 	esp->edev = esp_dev;
 	esp->esp_id = nesps++;
 
+	/* Set bitshift value (only used on Amiga with multiple ESPs) */
+	esp->shift = 2;
+
 	/* Put into the chain of esp chips detected */
 	if(espchain) {
 		elink = espchain;
@@ -551,6 +566,20 @@
 	return esp;
 }
 
+void esp_deallocate(struct NCR_ESP *esp)
+{
+	struct NCR_ESP *elink;
+
+	if(espchain == esp) {
+		espchain = 0;
+	} else {
+		for(elink = espchain; elink && (elink->next != esp); elink = elink->next);
+		if(elink) 
+			elink->next = esp->next;
+	}
+	nesps--;
+}
+
 /* Complete initialization of ESP structure and device
  * Caller must have initialized appropriate parts of the ESP structure
  * between the call to esp_allocate and this function.
@@ -639,9 +668,9 @@
 	esp->neg_defp = ESP_NEG_DEFP(fmhz, ccf);
 	esp->sync_defp = SYNC_DEFP_SLOW;
 
-	printk("SCSI ID %d  Clock %d MHz CCF=%d Time-Out %d ",
+	printk("SCSI ID %d Clk %dMHz CCF=%d TOut %d ",
 	       esp->scsi_id, (esp->cfreq / 1000000),
-	       esp->ccf, (int) esp->neg_defp);
+	       ccf, (int) esp->neg_defp);
 
 	/* Fill in ehost data */
 	esp->ehost->base = (unsigned char *) eregs;
@@ -654,61 +683,46 @@
 	/* Probe the revision of this esp */
 	esp->config1 = (ESP_CONFIG1_PENABLE | (esp->scsi_id & 7));
 	esp->config2 = (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY);
-	SETREG(eregs->esp_cfg2, esp->config2);
-#ifndef SYMBIOS_HACK
-	if((GETREG(eregs->esp_cfg2) & ~(ESP_CONFIG2_MAGIC)) !=
+	esp_write(eregs->esp_cfg2, esp->config2);
+	if((esp_read(eregs->esp_cfg2) & ~(ESP_CONFIG2_MAGIC)) !=
 	   (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) {
-		printk("NCR53C90(esp100) detected\n");
+		printk("NCR53C90(esp100)\n");
 		esp->erev = esp100;
 	} else {
-#endif
 		esp->config2 = 0;
-		SETREG(eregs->esp_cfg2, esp->config2);
-		SETREG(eregs->esp_cfg3, 0);
-		esp->config3[0] = 5;
-		SETREG(eregs->esp_cfg3, esp->config3[0]);
-#ifndef SYMBIOS_HACK
-		if(GETREG(eregs->esp_cfg3) != 5) {
-			printk("NCR53C90A(esp100a) detected\n");
+		esp_write(eregs->esp_cfg2, 0);
+		esp_write(eregs->esp_cfg3, 5);
+		if(esp_read(eregs->esp_cfg3) != 5) {
+			printk("NCR53C90A(esp100a)\n");
 			esp->erev = esp100a;
 		} else {
-#else
-		  {
-#endif
 			int target;
-			
+
 			for(target=0; target<8; target++)
 				esp->config3[target] = 0;
-			SETREG(eregs->esp_cfg3, 0);
-#ifndef SYMBIOS_HACK
+			esp->prev_cfg3 = 0;
+			esp_write(eregs->esp_cfg3, 0);
 			if(ccf > ESP_CCF_F5) {
-#endif
-				printk("NCR53C9XF(espfast) detected\n");
+				printk("NCR53C9XF(espfast)\n");
 				esp->erev = fast;
-				esp->config2 = 0;
-				SETREG(eregs->esp_cfg2, esp->config2);
 				esp->sync_defp = SYNC_DEFP_FAST;
-#ifndef SYMBIOS_HACK
 			} else {
-				printk("NCR53C9x(esp236) detected\n");
+				printk("NCR53C9x(esp236)\n");
 				esp->erev = esp236;
-				esp->config2 = 0;
-				SETREG(eregs->esp_cfg2, esp->config2);
 			}
 		}
-#endif
 	}				
-	
+
 	/* Initialize the command queues */
 	esp->current_SC = 0;
 	esp->disconnected_SC = 0;
 	esp->issue_SC = 0;
-	
+
 	/* Clear the state machines. */
 	esp->targets_present = 0;
 	esp->resetting_bus = 0;
 	esp->snip = 0;
-	esp->targets_present = 0;
+	esp->fas_premature_intr_workaround = 0;
 	for(i = 0; i < 32; i++)
 		esp->espcmdlog[i] = 0;
 	esp->espcmdent = 0;
@@ -719,9 +733,15 @@
 	esp->prevmsgout = esp->prevmsgin = 0;
 	esp->msgout_len = esp->msgin_len = 0;
 
+	/* Clear the one behind caches to hold unmatchable values. */
+	esp->prev_soff = esp->prev_stp = esp->prev_cfg3 = 0xff;
+
 	/* Reset the thing before we try anything... */
 	esp_bootup_reset(esp, eregs);
-	
+
+#ifdef MODULE
+	MOD_INC_USE_COUNT;
+#endif
 	esps_in_use++;
 }
 
@@ -740,15 +760,17 @@
 	case esp100a:
 		return "ESP100A (NCR53C90A)";
 	case esp236:
-		return "ESP236";
+		return "ESP236 (NCR53C9x)";
 	case fas216:
-		return "ESP216-FAST";
+		return "Emulex FAS216";
 	case fas236:
-		return "ESP236-FAST";
-	case fashme:
-		return "ESP366-HME";
+		return "Emulex FAS236";
+	case fas366:
+		return "QLogic FAS366";
 	case fas100a:
-		return "ESP100A-FAST";
+		return "FPESP100A";
+	case fsc:
+		return "Symbios Logic 53CF9x-2";
 	default:
 		panic("Bogon ESP revision");
 	};
@@ -807,69 +829,41 @@
 	info.offset	= offset;
 	info.pos	= 0;
 
-	copy_info(&info, "Sparc ESP Host Adapter:\n");
-	copy_info(&info, "\tPROM node\t\t%08lx\n", (unsigned long) esp->prom_node);
-	copy_info(&info, "\tPROM name\t\t%s\n", esp->prom_name);
+	copy_info(&info, "ESP Host Adapter:\n");
 	copy_info(&info, "\tESP Model\t\t");
 	switch(esp->erev) {
 	case esp100:
-		copy_info(&info, "ESP100\n");
+		copy_info(&info, "ESP100 (NCR53C90)\n");
 		break;
 	case esp100a:
-		copy_info(&info, "ESP100A\n");
+		copy_info(&info, "ESP100A (NCR53C90A)\n");
 		break;
 	case esp236:
-		copy_info(&info, "ESP236\n");
+		copy_info(&info, "ESP236 (NCR53C9x)\n");
 		break;
 	case fas216:
-		copy_info(&info, "FAS216\n");
+		copy_info(&info, "Emulex FAS216\n");
 		break;
 	case fas236:
-		copy_info(&info, "FAS236\n");
+		copy_info(&info, "Emulex FAS236\n");
 		break;
 	case fas100a:
-		copy_info(&info, "FAS100A\n");
+		copy_info(&info, "FPESP100A\n");
 		break;
 	case fast:
-		copy_info(&info, "FAST\n");
-		break;
-	case fashme:
-		copy_info(&info, "Happy Meal FAS\n");
-		break;
-	case espunknown:
-	default:
-		copy_info(&info, "Unknown!\n");
-		break;
-	};
-#ifdef CONFIG_SCSI_SUNESP
-	copy_info(&info, "\tDMA Revision\t\t");
-	switch(((struct Linux_SBus_DMA*) (esp->dma))->revision) {
-	case dvmarev0:
-		copy_info(&info, "Rev 0\n");
-		break;
-	case dvmaesc1:
-		copy_info(&info, "ESC Rev 1\n");
-		break;
-	case dvmarev1:
-		copy_info(&info, "Rev 1\n");
-		break;
-	case dvmarev2:
-		copy_info(&info, "Rev 2\n");
+		copy_info(&info, "Generic FAST\n");
 		break;
-	case dvmarev3:
-		copy_info(&info, "Rev 3\n");
+	case fas366:
+		copy_info(&info, "QLogic FAS366\n");
 		break;
-	case dvmarevplus:
-		copy_info(&info, "Rev 1+\n");
-		break;
-	case dvmahme:
-		copy_info(&info, "Rev HME/FAS\n");
+	case fsc:
+		copy_info(&info, "Symbios Logic 53C9x-2\n");
 		break;
+	case espunknown:
 	default:
 		copy_info(&info, "Unknown!\n");
 		break;
 	};
-#endif
 	copy_info(&info, "\tLive Targets\t\t[ ");
 	for(i = 0; i < 15; i++) {
 		if(esp->targets_present & (1 << i))
@@ -878,7 +872,7 @@
 	copy_info(&info, "]\n\n");
 	
 	/* Now describe the state of each existing target. */
-	copy_info(&info, "Target #\tconfig3\t\tSync Capabilities\tDisconnect\tWide\n");
+	copy_info(&info, "Target #\tconfig3\t\tSync Capabilities\tDisconnect\n");
 	for(i = 0; i < 15; i++) {
 		if(esp->targets_present & (1 << i)) {
 			Scsi_Device *SDptr = esp->ehost->host_queue;
@@ -892,9 +886,7 @@
 			copy_info(&info, "%08lx\t", esp->config3[i]);
 			copy_info(&info, "[%02lx,%02lx]\t\t\t", SDptr->sync_max_offset,
 				  SDptr->sync_min_period);
-			copy_info(&info, "%s\t\t", SDptr->disconnect ? "yes" : "no");
-			copy_info(&info, "%s\n",
-				  (esp->config3[i] & ESP_CONFIG3_EWIDE) ? "yes" : "no");
+			copy_info(&info, "%s\n", SDptr->disconnect ? "yes" : "no");
 		}
 	}
 
@@ -923,6 +915,60 @@
 	return esp_host_info(esp, buffer, offset, length);
 }
 
+static void esp_get_dmabufs(struct NCR_ESP *esp, Scsi_Cmnd *sp)
+{
+	if(sp->use_sg == 0) {
+		sp->SCp.this_residual = sp->request_bufflen;
+		sp->SCp.buffer = (struct scatterlist *) sp->request_buffer;
+		sp->SCp.buffers_residual = 0;
+		if (esp->dma_mmu_get_scsi_one)
+			esp->dma_mmu_get_scsi_one(esp, sp);
+		else
+			sp->SCp.have_data_in = (int) sp->SCp.ptr =
+				(char *) virt_to_phys(sp->request_buffer);
+	} else {
+		sp->SCp.buffer = (struct scatterlist *) sp->buffer;
+		sp->SCp.buffers_residual = sp->use_sg - 1;
+		sp->SCp.this_residual = sp->SCp.buffer->length;
+		if (esp->dma_mmu_get_scsi_sgl)
+			esp->dma_mmu_get_scsi_sgl(esp, sp);
+		else
+			sp->SCp.ptr =
+				(char *) virt_to_phys(sp->SCp.buffer->address);
+	}
+}
+
+static void esp_release_dmabufs(struct NCR_ESP *esp, Scsi_Cmnd *sp)
+{
+	if(sp->use_sg == 0) {
+		if (esp->dma_mmu_release_scsi_one)
+			esp->dma_mmu_release_scsi_one(esp, sp);
+	} else {
+		if (esp->dma_mmu_release_scsi_sgl)
+			esp->dma_mmu_release_scsi_sgl(esp, sp);
+	}
+}
+
+static void esp_restore_pointers(struct NCR_ESP *esp, Scsi_Cmnd *sp)
+{
+	struct esp_pointers *ep = &esp->data_pointers[sp->target];
+
+	sp->SCp.ptr = ep->saved_ptr;
+	sp->SCp.buffer = ep->saved_buffer;
+	sp->SCp.this_residual = ep->saved_this_residual;
+	sp->SCp.buffers_residual = ep->saved_buffers_residual;
+}
+
+static void esp_save_pointers(struct NCR_ESP *esp, Scsi_Cmnd *sp)
+{
+	struct esp_pointers *ep = &esp->data_pointers[sp->target];
+
+	ep->saved_ptr = sp->SCp.ptr;
+	ep->saved_buffer = sp->SCp.buffer;
+	ep->saved_this_residual = sp->SCp.this_residual;
+	ep->saved_buffers_residual = sp->SCp.buffers_residual;
+}
+
 /* Some rules:
  *
  *   1) Never ever panic while something is live on the bus.
@@ -970,29 +1016,7 @@
 	esp->msgout_len = 5;
 }
 
-/* SIZE is in bits, currently HME only supports 16 bit wide transfers. */
-static inline void build_wide_nego_msg(struct NCR_ESP *esp, int size)
-{
-	esp->cur_msgout[0] = EXTENDED_MESSAGE;
-	esp->cur_msgout[1] = 2;
-	esp->cur_msgout[2] = EXTENDED_WDTR;
-	switch(size) {
-	case 32:
-		esp->cur_msgout[3] = 2;
-		break;
-	case 16:
-		esp->cur_msgout[3] = 1;
-		break;
-	case 8:
-	default:
-		esp->cur_msgout[3] = 0;
-		break;
-	};
-
-	esp->msgout_len = 4;
-}
-
-static inline void esp_exec_cmd(struct NCR_ESP *esp)
+static void esp_exec_cmd(struct NCR_ESP *esp)
 {
 	struct ESP_regs *eregs = esp->eregs;
 	Scsi_Cmnd *SCptr;
@@ -1002,15 +1026,18 @@
 	int lun, target;
 	int i;
 
-	/* Hold off if we've been reselected or an IRQ is showing... */
-	if(esp->disconnected_SC || esp->dma_irq_p(esp))
+	/* Hold off if we have disconnected commands and
+	 * an IRQ is showing...
+	 */
+	if(esp->disconnected_SC && esp->dma_irq_p(esp))
 		return;
 
 	/* Grab first member of the issue queue. */
 	SCptr = esp->current_SC = remove_first_SC(&esp->issue_SC);
 
 	/* Safe to panic here because current_SC is null. */
-	if(!SCptr) panic("esp: esp_exec_cmd and issue queue is NULL");
+	if(!SCptr)
+		panic("esp: esp_exec_cmd and issue queue is NULL");
 
 	SDptr = SCptr->device;
 	lun = SCptr->lun;
@@ -1053,7 +1080,7 @@
 
 	if(SDptr->sync) {
 		/* this targets sync is known */
-#ifdef CONFIG_SCSI_SUNESP
+#ifdef CONFIG_SCSI_MAC_ESP
 do_sync_known:
 #endif
 		if(SDptr->disconnect)
@@ -1090,51 +1117,28 @@
 	} else {
 		int toshiba_cdrom_hwbug_wkaround = 0;
 
-#ifdef CONFIG_SCSI_SUNESP
-		/* Never allow disconnects or synchronous transfers on
-		 * SparcStation1 and SparcStation1+.  Allowing those
-		 * to be enabled seems to lockup the machine completely.
-		 */
-		if((idprom->id_machtype == (SM_SUN4C | SM_4C_SS1)) ||
-		   (idprom->id_machtype == (SM_SUN4C | SM_4C_SS1PLUS))) {
-			/* But we are nice and allow tapes to disconnect. */
-			if(SDptr->type == TYPE_TAPE)
-				SDptr->disconnect = 1;
-			else
-				SDptr->disconnect = 0;
-			SDptr->sync_max_offset = 0;
-			SDptr->sync_min_period = 0;
-			SDptr->sync = 1;
-			esp->snip = 0;
-			goto do_sync_known;
-		}
+#ifdef CONFIG_SCSI_MAC_ESP
+		/* Never allow synchronous transfers (disconnect OK) on
+		 * Macintosh. Well, maybe later when we figured out how to 
+		 * do DMA on the machines that support it ...
+		 */
+		SDptr->disconnect = 1;
+		SDptr->sync_max_offset = 0;
+		SDptr->sync_min_period = 0;
+		SDptr->sync = 1;
+		esp->snip = 0;
+		goto do_sync_known;
 #endif
 		/* We've talked to this guy before,
-		 * but never negotiated.  Let's try,
-		 * need to attempt WIDE first, before
-		 * sync nego, as per SCSI 2 standard.
-		 */
-		if(esp->erev == fashme && !SDptr->wide) {
-			if(!SDptr->borken &&
-			   (SDptr->type != TYPE_ROM ||
-			    strncmp(SDptr->vendor, "TOSHIBA", 7))) {
-				build_wide_nego_msg(esp, 16);
-				esp->config3[SCptr->target] |= ESP_CONFIG3_EWIDE;
-				SDptr->wide = 1;
-				esp->wnip = 1;
-				goto after_nego_msg_built;
-			} else {
-				SDptr->wide = 1;
-				/* Fall through and try sync. */
-			}
-		}
-
+		 * but never negotiated.  Let's try
+		 * sync negotiation.
+		 */
 		if(!SDptr->borken) {
 			if((SDptr->type == TYPE_ROM) &&
 			   (!strncmp(SDptr->vendor, "TOSHIBA", 7))) {
 				/* Nice try sucker... */
-				printk(KERN_INFO "esp%d: Disabling sync for buggy "
-				       "Toshiba CDROM.\n", esp->esp_id);
+				ESPMISC(("esp%d: Disabling sync for buggy "
+					 "Toshiba CDROM.\n", esp->esp_id));
 				toshiba_cdrom_hwbug_wkaround = 1;
 				build_sync_nego_msg(esp, 0, 0);
 			} else {
@@ -1146,7 +1150,6 @@
 		SDptr->sync = 1;
 		esp->snip = 1;
 
-after_nego_msg_built:
 		/* A fix for broken SCSI1 targets, when they disconnect
 		 * they lock up the bus and confuse ESP.  So disallow
 		 * disconnects for SCSI1 targets for now until we
@@ -1171,13 +1174,9 @@
 		 *           thank you very much. ;-)
 		 */
 		if(((SDptr->scsi_level < 3) && (SDptr->type != TYPE_TAPE)) ||
-#if 1 /* Until I find out why HME barfs with disconnects enabled... */
-		   toshiba_cdrom_hwbug_wkaround || SDptr->borken || esp->erev == fashme) {
-#else
 		   toshiba_cdrom_hwbug_wkaround || SDptr->borken) {
-#endif
-			printk(KERN_INFO "esp%d: Disabling DISCONNECT for target %d "
-			       "lun %d\n", esp->esp_id, SCptr->target, SCptr->lun);
+			ESPMISC((KERN_INFO "esp%d: Disabling DISCONNECT for target %d "
+				 "lun %d\n", esp->esp_id, SCptr->target, SCptr->lun));
 			SDptr->disconnect = 0;
 			*cmdp++ = IDENTIFY(0, lun);
 		} else {
@@ -1199,49 +1198,48 @@
 		for(i = 0; i < SCptr->cmd_len; i++)
 			*cmdp++ = SCptr->cmnd[i];
 
-	/* HME sucks... */
-	if(esp->erev == fashme)
-		SETREG(eregs->esp_busid, (target & 0xf) |
-			(ESP_BUSID_RESELID | ESP_BUSID_CTR32BIT));
-	else
-		SETREG(eregs->esp_busid, (target & 7));
-	SETREG(eregs->esp_soff, SDptr->sync_max_offset);
-	SETREG(eregs->esp_stp, SDptr->sync_min_period);
-	if(esp->erev > esp100a)
-		SETREG(eregs->esp_cfg3, esp->config3[target]);
-
+	esp_write(eregs->esp_busid, (target & 7));
+	if (esp->prev_soff != SDptr->sync_max_offset ||
+	    esp->prev_stp  != SDptr->sync_min_period ||
+	    (esp->erev > esp100a &&
+	     esp->prev_cfg3 != esp->config3[target])) {
+		esp->prev_soff = SDptr->sync_max_offset;
+		esp_write(eregs->esp_soff, esp->prev_soff);
+		esp->prev_stp = SDptr->sync_min_period;
+		esp_write(eregs->esp_stp, esp->prev_stp); 
+		if(esp->erev > esp100a) {
+			esp->prev_cfg3 = esp->config3[target];
+			esp_write(eregs->esp_cfg3, esp->prev_cfg3);
+		}
+	}
 	i = (cmdp - esp->esp_command);
 
 	/* Set up the DMA and ESP counters */
 	if(esp->do_pio_cmds){
 		int j = 0;
 
+		/* 
+		 * XXX MSch:
+		 *
+		 * It seems this is required, at least to clean up
+		 * after failed commands when using PIO mode ...
+		 */
+		esp_cmd(esp, eregs, ESP_CMD_FLUSH);
+
 		for(;j<i;j++)
-			SETREG(eregs->esp_fdata, esp->esp_command[j]);
+			esp_write(eregs->esp_fdata, esp->esp_command[j]);
 		the_esp_command &= ~ESP_CMD_DMA;
 
 		/* Tell ESP to "go". */
 		esp_cmd(esp, eregs, the_esp_command);
 	} else {
-		if(esp->erev == fashme) {
-			esp_cmd(esp, eregs, ESP_CMD_FLUSH); /* Grrr! */
-
-			/* Set up the HME counters */
-			SETREG(eregs->esp_tclow, i);
-			SETREG(eregs->esp_tcmed, 0);
-			SETREG(eregs->fas_rlo, 0);
-			SETREG(eregs->fas_rhi, 0);
-			esp_cmd(esp, eregs, the_esp_command);
-			esp->dma_init_write(esp, esp->esp_command_dvma, 16);
-		} else {
-			/* Set up the ESP counters */
-			SETREG(eregs->esp_tclow, i);
-			SETREG(eregs->esp_tcmed, 0);
-			esp->dma_init_write(esp, esp->esp_command_dvma, i);
+		/* Set up the ESP counters */
+		esp_write(eregs->esp_tclow, i);
+		esp_write(eregs->esp_tcmed, 0);
+		esp->dma_init_write(esp, esp->esp_command_dvma, i);
 
-			/* Tell ESP to "go". */
-			esp_cmd(esp, eregs, the_esp_command);
-		}
+		/* Tell ESP to "go". */
+		esp_cmd(esp, eregs, the_esp_command);
 	}
 }
 
@@ -1249,7 +1247,6 @@
 int esp_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
 {
 	struct NCR_ESP *esp;
-	unsigned long flags;
 
 	/* Set up func ptr and initial driver cmd-phase. */
 	SCpnt->scsi_done = done;
@@ -1263,32 +1260,10 @@
 	/* We use the scratch area. */
 	ESPQUEUE(("esp_queue: target=%d lun=%d ", SCpnt->target, SCpnt->lun));
 	ESPDISC(("N<%02x,%02x>", SCpnt->target, SCpnt->lun));
-	if(!SCpnt->use_sg) {
-		ESPQUEUE(("!use_sg\n"));
-		SCpnt->SCp.this_residual    = SCpnt->request_bufflen;
-		SCpnt->SCp.buffer           =
-			(struct scatterlist *) SCpnt->request_buffer;
-		SCpnt->SCp.buffers_residual = 0;
-	        if (esp->dma_mmu_get_scsi_one)
-		        esp->dma_mmu_get_scsi_one (esp, SCpnt);
-	        else
-		        SCpnt->SCp.have_data_in = (int) SCpnt->SCp.ptr =
-		                (char *) virt_to_phys(SCpnt->request_buffer);
-	} else {
-		ESPQUEUE(("use_sg "));
-#ifdef DEBUG_ESP_SG
-		printk("esp%d: sglist at %p with %d buffers\n",
-		       esp->esp_id, SCpnt->buffer, SCpnt->use_sg);
-#endif
-		SCpnt->SCp.buffer           = (struct scatterlist *) SCpnt->buffer;
-		SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1;
-		SCpnt->SCp.this_residual    = SCpnt->SCp.buffer->length;
-	        if (esp->dma_mmu_get_scsi_sgl)
-		        esp->dma_mmu_get_scsi_sgl (esp, SCpnt);
-	        else
-		        SCpnt->SCp.ptr = 
-		                (char *) virt_to_phys(SCpnt->SCp.buffer->address);
-	}
+
+	esp_get_dmabufs(esp, SCpnt);
+	esp_save_pointers(esp, SCpnt); /* FIXME for tag queueing */
+
 	SCpnt->SCp.Status           = CHECK_CONDITION;
 	SCpnt->SCp.Message          = 0xff;
 	SCpnt->SCp.sent_command     = 0;
@@ -1302,13 +1277,10 @@
 		append_SC(&esp->issue_SC, SCpnt);
 	}
 
- 	save_and_cli(flags);
-
 	/* Run it now if we can. */
 	if(!esp->current_SC && !esp->resetting_bus)
 		esp_exec_cmd(esp);
 
-	restore_flags(flags);
 	return 0;
 }
 
@@ -1324,7 +1296,7 @@
 }
 
 /* Dump driver state. */
-static inline void esp_dump_cmd(Scsi_Cmnd *SCptr)
+static void esp_dump_cmd(Scsi_Cmnd *SCptr)
 {
 	ESPLOG(("[tgt<%02x> lun<%02x> "
 		"pphase<%s> cphase<%s>]",
@@ -1333,8 +1305,8 @@
 		phase_string(SCptr->SCp.phase)));
 }
 
-static inline void esp_dump_state(struct NCR_ESP *esp, 
-				  struct ESP_regs *eregs)
+static void esp_dump_state(struct NCR_ESP *esp, 
+			   struct ESP_regs *eregs)
 {
 	Scsi_Cmnd *SCptr = esp->current_SC;
 #ifdef DEBUG_ESP_CMDS
@@ -1349,8 +1321,8 @@
 	ESPLOG(("esp%d: SW [sreg<%02x> sstep<%02x> ireg<%02x>]\n",
 		esp->esp_id, esp->sreg, esp->seqreg, esp->ireg));
 	ESPLOG(("esp%d: HW reread [sreg<%02x> sstep<%02x> ireg<%02x>]\n",
-		esp->esp_id, GETREG(eregs->esp_status), 
-		GETREG(eregs->esp_sstep), GETREG(eregs->esp_intrpt)));
+		esp->esp_id, esp_read(eregs->esp_status), esp_read(eregs->esp_sstep),
+		esp_read(eregs->esp_intrpt)));
 #ifdef DEBUG_ESP_CMDS
 	printk("esp%d: last ESP cmds [", esp->esp_id);
 	i = (esp->espcmdent - 1) & 31;
@@ -1392,7 +1364,6 @@
 	struct NCR_ESP *esp = (struct NCR_ESP *) SCptr->host->hostdata;
 	struct ESP_regs *eregs = esp->eregs;
 	int don;
-	unsigned long flags;
 
 	ESPLOG(("esp%d: Aborting command\n", esp->esp_id));
 	esp_dump_state(esp, eregs);
@@ -1403,16 +1374,13 @@
 	 * in the driver and timeout because the eventual phase change
 	 * will cause the ESP to (eventually) give an interrupt.
 	 */
-	save_and_cli(flags);
 	if(esp->current_SC == SCptr) {
 		esp->cur_msgout[0] = ABORT;
 		esp->msgout_len = 1;
 		esp->msgout_ctr = 0;
 		esp_cmd(esp, eregs, ESP_CMD_SATN);
-		restore_flags(flags);
 		return SCSI_ABORT_PENDING;
 	}
-	restore_flags(flags);
 
 	/* If it is still in the issue queue then we can safely
 	 * call the completion routine and report abort success.
@@ -1431,6 +1399,7 @@
 			if(this == SCptr) {
 				*prev = (Scsi_Cmnd *) this->host_scribble;
 				this->host_scribble = NULL;
+				esp_release_dmabufs(esp, this);
 				this->result = DID_ABORT << 16;
 				this->done(this);
 				if(don)
@@ -1445,8 +1414,11 @@
 	 * on the bus at this time.  So, we let the SCSI code wait
 	 * a little bit and try again later.
 	 */
-	if(esp->current_SC)
+	if(esp->current_SC) {
+		if(don)
+			esp->dma_ints_on(esp);
 		return SCSI_ABORT_BUSY;
+	}
 
 	/* It's disconnected, we have to reconnect to re-establish
 	 * the nexus and tell the device to abort.  However, we really
@@ -1455,20 +1427,68 @@
 	 * happens, we are really hung so reset the bus.
 	 */
 
+	if(don)
+		esp->dma_ints_on(esp);
 	return SCSI_ABORT_SNOOZE;
 }
 
+/* We've sent ESP_CMD_RS to the ESP, the interrupt had just
+ * arrived indicating the end of the SCSI bus reset.  Our job
+ * is to clean out the command queues and begin re-execution
+ * of SCSI commands once more.
+ */
+static int esp_finish_reset(struct NCR_ESP *esp,
+			    struct ESP_regs *eregs)
+{
+	Scsi_Cmnd *sp = esp->current_SC;
+
+	/* Clean up currently executing command, if any. */
+	if (sp != NULL) {
+		esp_release_dmabufs(esp, sp);
+		sp->result = (DID_RESET << 16);
+		sp->scsi_done(sp);
+		esp->current_SC = NULL;
+	}
+
+	/* Clean up disconnected queue, they have been invalidated
+	 * by the bus reset.
+	 */
+	if (esp->disconnected_SC) {
+		while((sp = remove_first_SC(&esp->disconnected_SC)) != NULL) {
+			esp_release_dmabufs(esp, sp);
+			sp->result = (DID_RESET << 16);
+			sp->scsi_done(sp);
+		}
+	}
+
+	/* SCSI bus reset is complete. */
+	esp->resetting_bus = 0;
+
+	/* Ok, now it is safe to get commands going once more. */
+	if(esp->issue_SC)
+		esp_exec_cmd(esp);
+
+	return do_intr_end;
+}
+
+static int esp_do_resetbus(struct NCR_ESP *esp,
+			   struct ESP_regs *eregs)
+{
+	ESPLOG(("esp%d: Resetting scsi bus\n", esp->esp_id));
+	esp->resetting_bus = 1;
+	esp_cmd(esp, eregs, ESP_CMD_RS);
+
+	return do_intr_end;
+}
+
 /* Reset ESP chip, reset hanging bus, then kill active and
  * disconnected commands for targets without soft reset.
  */
 int esp_reset(Scsi_Cmnd *SCptr, unsigned int how)
 {
 	struct NCR_ESP *esp = (struct NCR_ESP *) SCptr->host->hostdata;
-	struct ESP_regs *eregs = esp->eregs;
 
-	ESPLOG(("esp%d: Resetting scsi bus\n", esp->esp_id));
-	esp->resetting_bus = 1;
-	esp_cmd(esp, eregs, ESP_CMD_RS);
+	(void) esp_do_resetbus(esp, esp->eregs);
 	return SCSI_RESET_PENDING;
 }
 
@@ -1478,36 +1498,15 @@
 	Scsi_Cmnd *done_SC;
 
 	if(esp->current_SC) {
-		unsigned long flags;
-
 		done_SC = esp->current_SC;
 		esp->current_SC = NULL;
-
-		/* Free dvma entry. */
-		if(!done_SC->use_sg) {
-		        if (esp->dma_mmu_release_scsi_one)
-			        esp->dma_mmu_release_scsi_one (esp, done_SC);
-		} else {
-#ifdef DEBUG_ESP_SG
-			printk("esp%d: unmapping sg ", esp->esp_id);
-#endif
-		        if (esp->dma_mmu_release_scsi_sgl)
-			        esp->dma_mmu_release_scsi_sgl (esp, done_SC);
-#ifdef DEBUG_ESP_SG
-			printk("done.\n");
-#endif
-		}
-
+		esp_release_dmabufs(esp, done_SC);
 		done_SC->result = error;
 		done_SC->scsi_done(done_SC);
 
-		save_and_cli(flags);
-
 		/* Bus is free, issue any commands in the queue. */
 		if(esp->issue_SC && !esp->current_SC)
 			esp_exec_cmd(esp);
-
-		restore_flags(flags);
 	} else {
 		/* Panic is safe as current_SC is null so we may still
 		 * be able to accept more commands to sync disk buffers.
@@ -1519,11 +1518,6 @@
 
 /* Wheee, ESP interrupt engine. */  
 
-enum {
-	do_phase_determine, do_reset_bus, do_reset_complete,
-	do_work_bus, do_intr_end,
-};
-
 /* Forward declarations. */
 static int esp_do_phase_determine(struct NCR_ESP *esp, 
 				  struct ESP_regs *eregs);
@@ -1535,67 +1529,8 @@
 static int esp_do_msgout(struct NCR_ESP *esp, struct ESP_regs *eregs);
 static int esp_do_cmdbegin(struct NCR_ESP *esp, struct ESP_regs *eregs);
 
-static inline int sreg_datainp(unchar sreg)
-{
-	return (sreg & ESP_STAT_PMASK) == ESP_DIP;
-}
-
-static inline int sreg_dataoutp(unchar sreg)
-{
-	return (sreg & ESP_STAT_PMASK) == ESP_DOP;
-}
-
-/* Did they drop these fabs on the floor or what?!?!! */
-static inline void hme_fifo_hwbug_workaround(struct NCR_ESP *esp,
-					     struct ESP_regs *eregs)
-{
-	unchar status = esp->sreg;
-
-	/* Cannot safely frob the fifo for these following cases. */
-	if(sreg_datainp(status) || sreg_dataoutp(status) ||
-	   (esp->current_SC && esp->current_SC->SCp.phase == in_data_done)) {
-		ESPHME(("<wkaround_skipped>"));
-		return;
-	} else {
-		unsigned long count = 0;
-		unsigned long fcnt = GETREG(eregs->esp_fflags) & ESP_FF_FBYTES;
-
-		/* The HME stores bytes in multiples of 2 in the fifo. */
-		ESPHME(("hme_fifo[fcnt=%d", (int)fcnt));
-		while(fcnt) {
-			esp->hme_fifo_workaround_buffer[count++] = 
-			 GETREG(eregs->esp_fdata);
-			esp->hme_fifo_workaround_buffer[count++] = 
-			 GETREG(eregs->esp_fdata);
-			ESPHME(("<%02x,%02x>", esp->hme_fifo_workaround_buffer[count-2], esp->hme_fifo_workaround_buffer[count-1]));
-			fcnt--;
-		}
-		if(GETREG(eregs->esp_status2) & ESP_STAT2_F1BYTE) {
-			ESPHME(("<poke_byte>"));
-			SETREG(eregs->esp_fdata, 0);
-			esp->hme_fifo_workaround_buffer[count++] = 
-			 GETREG(eregs->esp_fdata);
-			ESPHME(("<%02x,0x00>", esp->hme_fifo_workaround_buffer[count-1]));
-			ESPHME(("CMD_FLUSH"));
-			esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-		} else {
-			ESPHME(("no_xtra_byte"));
-		}
-		esp->hme_fifo_workaround_count = count;
-		ESPHME(("wkarnd_cnt=%d]", (int)count));
-	}
-}
-
-static inline void hme_fifo_push(struct NCR_ESP *esp, struct ESP_regs *eregs,
-				 unchar *bytes, unchar count)
-{
-	esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-	while(count) {
-		SETREG(eregs->esp_fdata, *bytes++);
-		SETREG(eregs->esp_fdata, 0);
-		count--;
-	}
-}
+#define sreg_datainp(__sreg)  (((__sreg) & ESP_STAT_PMASK) == ESP_DIP)
+#define sreg_dataoutp(__sreg) (((__sreg) & ESP_STAT_PMASK) == ESP_DOP)
 
 /* We try to avoid some interrupts by jumping ahead and see if the ESP
  * has gotten far enough yet.  Hence the following.
@@ -1608,20 +1543,8 @@
 
 	if(esp->dma_irq_p(esp)) {
 		/* Yes, we are able to save an interrupt. */
-		esp->sreg = GETREG(eregs->esp_status);
-		if(esp->erev == fashme) {
-			/* This chip is really losing. */
-			ESPHME(("HME["));
-			/* Must latch fifo before reading the interrupt
-			 * register else garbage ends up in the FIFO
-			 * which confuses the driver utterly.
-			 * Happy Meal indeed....
-			 */
-			ESPHME(("fifo_workaround]"));
-			hme_fifo_hwbug_workaround(esp, eregs);
-		}
-		esp->ireg = GETREG(eregs->esp_intrpt);
-		esp->sreg &= ~(ESP_STAT_INTR);
+		esp->sreg = (esp_read(eregs->esp_status) & ~(ESP_STAT_INTR));
+		esp->ireg = esp_read(eregs->esp_intrpt);
 		if(!(esp->ireg & ESP_INTR_SR))
 			return 0;
 		else
@@ -1642,21 +1565,8 @@
 		return 0;
 	if(esp->dma_irq_p(esp)) {
 		/* Yes, we are able to save an interrupt. */
-		esp->sreg = GETREG(eregs->esp_status);
-		if(esp->erev == fashme) {
-			/* This chip is really losing. */
-			ESPHME(("HME["));
-
-			/* Must latch fifo before reading the interrupt
-			 * register else garbage ends up in the FIFO
-			 * which confuses the driver utterly.
-			 * Happy Meal indeed....
-			 */
-			ESPHME(("fifo_workaround]"));
-			hme_fifo_hwbug_workaround(esp, eregs);
-		}
-		esp->ireg = GETREG(eregs->esp_intrpt);
-		esp->sreg &= ~(ESP_STAT_INTR);
+		esp->sreg = (esp_read(eregs->esp_status) & ~(ESP_STAT_INTR));
+		esp->ireg = esp_read(eregs->esp_intrpt);
 		if(!(esp->ireg & ESP_INTR_SR))
 			return 0;
 		else
@@ -1667,56 +1577,31 @@
 	return do_intr_end;
 }
 
-/* Misc. esp helper routines. */
-static inline void esp_setcount(struct ESP_regs *eregs, int cnt, int hme)
-{
-	SETREG(eregs->esp_tclow, (cnt & 0xff));
-	SETREG(eregs->esp_tcmed, ((cnt >> 8) & 0xff));
-	if(hme) {
-		SETREG(eregs->fas_rlo, 0);
-		SETREG(eregs->fas_rhi, 0);
-	}
-}
-
-static inline int esp_getcount(struct ESP_regs *eregs)
-{
-	return (((GETREG(eregs->esp_tclow))&0xff) |
-		(((GETREG(eregs->esp_tcmed))&0xff) << 8));
-}
+/* Misc. esp helper macros. */
+#define esp_setcount(__eregs, __cnt) \
+	esp_write((__eregs)->esp_tclow, ((__cnt) & 0xff)); \
+	esp_write((__eregs)->esp_tcmed, (((__cnt) >> 8) & 0xff))
+
+#define esp_getcount(__eregs) \
+	((esp_read((__eregs)->esp_tclow)&0xff) | \
+	 ((esp_read((__eregs)->esp_tcmed)&0xff) << 8))
 
-static inline int fcount(struct NCR_ESP *esp, struct ESP_regs *eregs)
-{
-	if(esp->erev == fashme)
-		return esp->hme_fifo_workaround_count;
-	else
-		return GETREG(eregs->esp_fflags) & ESP_FF_FBYTES;
-}
+#define fcount(__esp, __eregs) \
+	(esp_read((__eregs)->esp_fflags) & ESP_FF_FBYTES)
 
-static inline int fnzero(struct NCR_ESP *esp, struct ESP_regs *eregs)
-{
-	if(esp->erev == fashme)
-		return 0;
-	else
-		return GETREG(eregs->esp_fflags) & ESP_FF_ONOTZERO;
-}
+#define fnzero(__esp, __eregs) \
+	(esp_read((__eregs)->esp_fflags) & ESP_FF_ONOTZERO)
 
 /* XXX speculative nops unnecessary when continuing amidst a data phase
  * XXX even on esp100!!!  another case of flooding the bus with I/O reg
  * XXX writes...
  */
-static inline void esp_maybe_nop(struct NCR_ESP *esp, struct ESP_regs *eregs)
-{
-	if(esp->erev == esp100)
-		esp_cmd(esp, eregs, ESP_CMD_NULL);
-}
+#define esp_maybe_nop(__esp, __eregs) \
+	if((__esp)->erev == esp100) \
+		esp_cmd((__esp), (__eregs), ESP_CMD_NULL)
 
-static inline int sreg_to_dataphase(unchar sreg)
-{
-	if((sreg & ESP_STAT_PMASK) == ESP_DOP)
-		return in_dataout;
-	else
-		return in_datain;
-}
+#define sreg_to_dataphase(__sreg) \
+	((((__sreg) & ESP_STAT_PMASK) == ESP_DOP) ? in_dataout : in_datain)
 
 /* The ESP100 when in synchronous data phase, can mistake a long final
  * REQ pulse from the target as an extra byte, it places whatever is on
@@ -1731,8 +1616,8 @@
 {
 	/* Do not touch this piece of code. */
 	if((!(esp->erev == esp100)) ||
-	   (!(sreg_datainp((esp->sreg = GETREG(eregs->esp_status))) && !fifocnt)
-	    && !(sreg_dataoutp(esp->sreg) && !fnzero(esp, eregs)))) {
+	   (!(sreg_datainp((esp->sreg = esp_read(eregs->esp_status))) && !fifocnt) &&
+	    !(sreg_dataoutp(esp->sreg) && !fnzero(esp, eregs)))) {
 		if(sp->SCp.phase == in_dataout)
 			esp_cmd(esp, eregs, ESP_CMD_FLUSH);
 		return 0;
@@ -1759,7 +1644,7 @@
 
 	if(esp->erev != esp100)
 		return 0;
-	junk = GETREG(eregs->esp_intrpt);
+	junk = esp_read(eregs->esp_intrpt);
 
 	if(junk & ESP_INTR_SR)
 		return 1;
@@ -1775,24 +1660,14 @@
 
 	if(2 != fcount(esp, eregs))
 		return -1;
-	if(esp->erev == fashme) {
-		/* HME does not latch it's own BUS ID bits during
-		 * a reselection.  Also the target number is given
-		 * as an unsigned char, not as a sole bit number
-		 * like the other ESP's do.
-		 * Happy Meal indeed....
-		 */
-		targ = esp->hme_fifo_workaround_buffer[0];
-	} else {
-		it = GETREG(eregs->esp_fdata);
-		if(!(it & me))
-			return -1;
-		it &= ~me;
-		if(it & (it - 1))
-			return -1;
-		while(!(it & 1))
-			targ++, it >>= 1;
-	}
+	it = esp_read(eregs->esp_fdata);
+	if(!(it & me))
+		return -1;
+	it &= ~me;
+	if(it & (it - 1))
+		return -1;
+	while(!(it & 1))
+		targ++, it >>= 1;
 	return targ;
 }
 
@@ -1805,14 +1680,20 @@
 
 	if((esp->sreg & ESP_STAT_PMASK) != ESP_MIP)
 		return -1;
-	if(esp->erev == fashme)
-		lun = esp->hme_fifo_workaround_buffer[1];
-	else
-		lun = GETREG(eregs->esp_fdata);
+	lun = esp_read(eregs->esp_fdata);
+
+	/* Yes, you read this correctly.  We report lun of zero
+	 * if we see parity error.  ESP reports parity error for
+	 * the lun byte, and this is the only way to hope to recover
+	 * because the target is connected.
+	 */
 	if(esp->sreg & ESP_STAT_PERR)
 		return 0;
+
+	/* Check for illegal bits being set in the lun. */
 	if((lun & 0x40) || !(lun & 0x80))
 		return -1;
+
 	return lun & 7;
 }
 
@@ -1823,13 +1704,20 @@
 			       Scsi_Cmnd *sp)
 {
 	Scsi_Device *dp = sp->device;
-	SETREG(eregs->esp_soff, dp->sync_max_offset);
-	SETREG(eregs->esp_stp, dp->sync_min_period);
-	if(esp->erev > esp100a)
-		SETREG(eregs->esp_cfg3, esp->config3[sp->target]);
-	if(esp->erev == fashme)
-		SETREG(eregs->esp_busid, (sp->target & 0xf) |
-			(ESP_BUSID_RESELID | ESP_BUSID_CTR32BIT));
+
+	if(esp->prev_soff  != dp->sync_max_offset ||
+	   esp->prev_stp   != dp->sync_min_period ||
+	   (esp->erev > esp100a &&
+	    esp->prev_cfg3 != esp->config3[sp->target])) {
+		esp->prev_soff = dp->sync_max_offset;
+		esp_write(eregs->esp_soff, esp->prev_soff);
+		esp->prev_stp = dp->sync_min_period;
+		esp_write(eregs->esp_stp, esp->prev_stp);
+		if(esp->erev > esp100a) {
+			esp->prev_cfg3 = esp->config3[sp->target];
+			esp_write(eregs->esp_cfg3, esp->prev_cfg3);
+		} 
+	}
 	esp->current_SC = sp;
 }
 
@@ -1839,8 +1727,8 @@
 static inline void esp_reconnect(struct NCR_ESP *esp, Scsi_Cmnd *sp)
 {
 	if(!esp->disconnected_SC)
-		printk("esp%d: Weird, being reselected but disconnected "
-		       "command queue is empty.\n", esp->esp_id);
+		ESPLOG(("esp%d: Weird, being reselected but disconnected "
+			"command queue is empty.\n", esp->esp_id));
 	esp->snip = 0;
 	esp->current_SC = 0;
 	sp->SCp.phase = not_issued;
@@ -1848,12 +1736,9 @@
 }
 
 /* Begin message in phase. */
-static inline int esp_do_msgin(struct NCR_ESP *esp, struct ESP_regs *eregs)
+static int esp_do_msgin(struct NCR_ESP *esp, struct ESP_regs *eregs)
 {
-	/* Must be very careful with the fifo on the HME */
-	if((esp->erev != fashme) || !(GETREG(eregs->esp_status2) & 
-	 ESP_STAT2_FEMPTY))
-		esp_cmd(esp, eregs, ESP_CMD_FLUSH);
+	esp_cmd(esp, eregs, ESP_CMD_FLUSH);
 	esp_maybe_nop(esp, eregs);
 	esp_cmd(esp, eregs, ESP_CMD_TI);
 	esp->msgin_len = 1;
@@ -1867,10 +1752,10 @@
 	++sp->SCp.buffer;
 	--sp->SCp.buffers_residual;
 	sp->SCp.this_residual = sp->SCp.buffer->length;
-        if (esp->dma_advance_sg)
-	       esp->dma_advance_sg (sp);
-        else
-	       sp->SCp.ptr = (char *)virt_to_phys(sp->SCp.buffer->address);
+	if (esp->dma_advance_sg)
+		esp->dma_advance_sg (sp);
+	else
+		sp->SCp.ptr = (char *)virt_to_phys(sp->SCp.buffer->address);
 }
 
 /* Please note that the way I've coded these routines is that I _always_
@@ -1891,8 +1776,7 @@
  * within a buffer or sub-buffer should not upset us at all no matter
  * how bad the target and/or ESP fucks things up.
  */
-
-static inline int esp_do_data(struct NCR_ESP *esp, struct ESP_regs *eregs)
+static int esp_do_data(struct NCR_ESP *esp, struct ESP_regs *eregs)
 {
 	Scsi_Cmnd *SCptr = esp->current_SC;
 	int thisphase, hmuch;
@@ -1903,31 +1787,204 @@
 	esp_advance_phase(SCptr, thisphase);
 	ESPDATA(("newphase<%s> ", (thisphase == in_datain) ? "DATAIN" : "DATAOUT"));
 	hmuch = esp->dma_can_transfer(esp, SCptr);
-	ESPDATA(("hmuch<%d> ", hmuch));
-	esp->current_transfer_size = hmuch;
-	if(esp->erev == fashme) {
-		/* Touchy chip, this stupid HME scsi adapter... */
-		esp_setcount(eregs, hmuch, 1);
-		esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
 
-		if(thisphase == in_datain)
-			esp->dma_init_read(esp, (__u32)((unsigned long)SCptr->SCp.ptr), hmuch);
-		else
-			esp->dma_init_write(esp, (__u32)((unsigned long)SCptr->SCp.ptr), hmuch);
-	} else {
-		esp_setcount(eregs, hmuch, 0);
-		esp->dma_setup(esp, 
-			       (__u32)((unsigned long)SCptr->SCp.ptr), 
+	/*
+	 * XXX MSch: cater for PIO transfer here; PIO used if hmuch == 0
+	 */
+	if (hmuch) {	/* DMA */
+		/*
+		 * DMA
+		 */
+		ESPDATA(("hmuch<%d> ", hmuch));
+		esp->current_transfer_size = hmuch;
+		esp_setcount(eregs, (esp->fas_premature_intr_workaround ?
+				     (hmuch + 0x40) : hmuch));
+		esp->dma_setup(esp, (__u32)((unsigned long)SCptr->SCp.ptr), 
 			       hmuch, (thisphase == in_datain));
 		ESPDATA(("DMA|TI --> do_intr_end\n"));
 		esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
-	}
+		return do_intr_end;
+		/*
+		 * end DMA
+		 */
+	} else {
+		/*
+		 * PIO
+		 */
+		int oldphase, i = 0; /* or where we left off last time ?? esp->current_data ?? */
+		int fifocnt = 0;
+
+		oldphase = esp_read(eregs->esp_status) & ESP_STAT_PMASK;
+
+		/*
+		 * polled transfer; ugly, can we make this happen in a DRQ 
+		 * interrupt handler ??
+		 * requires keeping track of state information in host or 
+		 * command struct!
+		 * Problem: I've never seen a DRQ happen on Mac, not even
+		 * with ESP_CMD_DMA ...
+		 */
+
+		/* figure out how much needs to be transfered */
+		hmuch = SCptr->SCp.this_residual;
+		ESPDATA(("hmuch<%d> pio ", hmuch));
+		esp->current_transfer_size = hmuch;
+
+		/* tell the ESP ... */
+		esp_setcount(eregs, hmuch);
+
+		/* loop */
+		while (hmuch) {
+			int j, fifo_stuck = 0, newphase;
+			unsigned long flags, timeout;
+#if 0
+			if ( i % 10 )
+				ESPDATA(("\r"));
+			else
+				ESPDATA(( /*"\n"*/ "\r"));
+#endif
+			save_flags(flags);
+#if 0
+			cli();
+#endif
+			if(thisphase == in_datain) {
+				/* 'go' ... */ 
+				esp_cmd(esp, eregs, ESP_CMD_TI);
+
+				/* wait for data */
+				timeout = 1000000;
+				while (!((esp->sreg=esp_read(eregs->esp_status)) & ESP_STAT_INTR) && --timeout)
+					udelay(2);
+				if (timeout == 0)
+					printk("DRQ datain timeout! \n");
+
+				newphase = esp->sreg & ESP_STAT_PMASK;
+
+				/* see how much we got ... */
+				fifocnt = (esp_read(eregs->esp_fflags) & ESP_FF_FBYTES);
+
+				if (!fifocnt)
+					fifo_stuck++;
+				else
+					fifo_stuck = 0;
+
+				ESPDATA(("\rgot %d st %x ph %x", fifocnt, esp->sreg, newphase));
+
+				/* read fifo */
+				for(j=0;j<fifocnt;j++)
+					SCptr->SCp.ptr[i++] = esp_read(eregs->esp_fdata);
+
+				ESPDATA(("(%d) ", i));
+
+				/* how many to go ?? */
+				hmuch -= fifocnt;
+
+				/* break if status phase !! */
+				if(newphase == ESP_STATP) {
+					/* clear int. */
+					esp->ireg = esp_read(eregs->esp_intrpt);
+					break;
+				}
+			} else {
+#define MAX_FIFO 8
+				/* how much will fit ? */
+				int this_count = MAX_FIFO - fifocnt;
+				if (this_count > hmuch)
+					this_count = hmuch;
+
+				/* fill fifo */
+				for(j=0;j<this_count;j++)
+					esp_write(eregs->esp_fdata, SCptr->SCp.ptr[i++]);
+
+				/* how many left if this goes out ?? */
+				hmuch -= this_count;
+
+				/* 'go' ... */ 
+				esp_cmd(esp, eregs, ESP_CMD_TI);
+
+				/* wait for 'got it' */
+				timeout = 1000000;
+				while (!((esp->sreg=esp_read(eregs->esp_status)) & ESP_STAT_INTR) && --timeout)
+					udelay(2);
+				if (timeout == 0)
+					printk("DRQ dataout timeout!  \n");
+
+				newphase = esp->sreg & ESP_STAT_PMASK;
+
+				/* need to check how much was sent ?? */
+				fifocnt = (esp_read(eregs->esp_fflags) & ESP_FF_FBYTES);
+
+				ESPDATA(("\rsent %d st %x ph %x", this_count - fifocnt, esp->sreg, newphase));
+
+				ESPDATA(("(%d) ", i));
+
+				/* break if status phase !! */
+				if(newphase == ESP_STATP) {
+					/* clear int. */
+					esp->ireg = esp_read(eregs->esp_intrpt);
+					break;
+				}
+
+			}
+
+			/* clear int. */
+			esp->ireg = esp_read(eregs->esp_intrpt);
+
+			ESPDATA(("ir %x ... ", esp->ireg));
+
+			if (hmuch == 0)
+				ESPDATA(("done! \n"));
+
+			restore_flags(flags);
+
+			/* check new bus phase */
+			if (newphase != oldphase && i < esp->current_transfer_size) {
+				/* something happened; disconnect ?? */
+				ESPDATA(("phase change, dropped out with %d done ... ", i));
+				break;
+			}
+
+			/* check int. status */
+			if (esp->ireg & ESP_INTR_DC) {
+				/* disconnect */
+				ESPDATA(("disconnect; %d transfered ... ", i));
+				break;
+			} else if (esp->ireg & ESP_INTR_FDONE) {
+				/* function done */
+				ESPDATA(("function done; %d transfered ... ", i));
+				break;
+			}
+
+			/* XXX fixme: bail out on stall */
+			if (fifo_stuck > 10) {
+				/* we're stuck */
+				ESPDATA(("fifo stall; %d transfered ... ", i));
+				break;
+			}
+		}
+
+		ESPDATA(("\n"));
+		/* check successful completion ?? */
+
+		if (thisphase == in_dataout)
+			hmuch += fifocnt; /* stuck?? adjust data pointer ...*/
+
+		/* tell do_data_finale how much was transfered */
+		esp->current_transfer_size -= hmuch;
+
+		/* still not completely sure on this one ... */		
+		return /*do_intr_end*/ do_work_bus /*do_phase_determine*/ ;
+
+		/*
+		 * end PIO
+		 */
+	}
 	return do_intr_end;
 }
 
 /* See how successful the data transfer was. */
-static inline int esp_do_data_finale(struct NCR_ESP *esp,
-				     struct ESP_regs *eregs)
+static int esp_do_data_finale(struct NCR_ESP *esp,
+			      struct ESP_regs *eregs)
 {
 	Scsi_Cmnd *SCptr = esp->current_SC;
 	int bogus_data = 0, bytes_sent = 0, fifocnt, ecount = 0;
@@ -1963,77 +2020,83 @@
 		return esp_do_phase_determine(esp, eregs);
 	}	
 
-	/* Check for partial transfers and other horrible events.
-	 * Note, here we read the real fifo flags register even
-	 * on HME broken adapters because we skip the HME fifo
-	 * workaround code in esp_handle() if we are doing data
-	 * phase things.  We don't want to fuck directly with
-	 * the fifo like that, especially if doing syncronous
-	 * transfers!  Also, will need to double the count on
-	 * HME if we are doing wide transfers, as the HME fifo
-	 * will move and count 16-bit quantities during wide data.
-	 * SMCC _and_ Qlogic can both bite me.
-	 */
-	fifocnt = GETREG(eregs->esp_fflags) & ESP_FF_FBYTES;
-	if(esp->erev != fashme)
-		ecount = esp_getcount(eregs);
+	/* Check for partial transfers and other horrible events. */
+	fifocnt = (esp_read(eregs->esp_fflags) & ESP_FF_FBYTES);
+	ecount = esp_getcount(eregs);
+	if(esp->fas_premature_intr_workaround)
+		ecount -= 0x40;
 	bytes_sent = esp->current_transfer_size;
 
-	/* Uhhh, might not want both of these conditionals to run
-	 * at once on HME due to the fifo problems it has.  Consider
-	 * changing it to:
-	 *
-	 * 	if(!(esp->sreg & ESP_STAT_TCNT)) {
-	 * 		bytes_sent -= ecount;
-	 * 	} else if(SCptr->SCp.phase == in_dataout) {
-	 * 		bytes_sent -= fifocnt;
-	 *	}
-	 *
-	 * But only for the HME case, leave the current code alone
-	 * for all other ESP revisions as we know the existing code
-	 * works just fine for them.
-	 */
 	ESPDATA(("trans_sz=%d, ", bytes_sent));
-	if(esp->erev == fashme) {
-		if(!(esp->sreg & ESP_STAT_TCNT)) {
-			bytes_sent -= esp_getcount(eregs);
-		} else if(SCptr->SCp.phase == in_dataout) {
-			bytes_sent -= fifocnt;
-		}
-	} else {
-		if(!(esp->sreg & ESP_STAT_TCNT))
-			bytes_sent -= ecount;
-		if(SCptr->SCp.phase == in_dataout)
-			bytes_sent -= fifocnt;
-	}
+	if(!(esp->sreg & ESP_STAT_TCNT))
+		bytes_sent -= ecount;
+	if(SCptr->SCp.phase == in_dataout)
+		bytes_sent -= fifocnt;
 
-	ESPDATA(("bytes_sent=%d, ", bytes_sent));
+	ESPDATA(("bytes_sent=%d (ecount=%d, fifocnt=%d), ", bytes_sent,
+		 ecount, fifocnt));
 
 	/* If we were in synchronous mode, check for peculiarities. */
-	if(esp->erev == fashme) {
-		if(SCptr->device->sync_max_offset) {
-			if(SCptr->SCp.phase == in_dataout)
-				esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-		} else {
-			esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-		}
-	} else {
-		if(SCptr->device->sync_max_offset)
-			bogus_data = esp100_sync_hwbug(esp, eregs, SCptr, fifocnt);
-		else
-			esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-	}
+	if(SCptr->device->sync_max_offset)
+		bogus_data = esp100_sync_hwbug(esp, eregs, SCptr, fifocnt);
+	else
+		esp_cmd(esp, eregs, ESP_CMD_FLUSH);
 
 	/* Until we are sure of what has happened, we are certainly
 	 * in the dark.
 	 */
 	esp_advance_phase(SCptr, in_the_dark);
 
+	/* Check for premature interrupt condition. Can happen on FAS2x6
+	 * chips. QLogic recommends a workaround by overprogramming the
+	 * transfer counters, but this makes doing scatter-gather impossible.
+	 * Until there is a way to disable scatter-gather for a single target,
+	 * and not only for the entire host adapter as it is now, the workaround
+	 * is way to expensive performance wise.
+	 * Instead, it turns out that when this happens the target has disconnected
+	 * allready but it doesn't show in the interrupt register. Compensate for
+	 * that here to try and avoid a SCSI bus reset.
+	 */
+	if(!esp->fas_premature_intr_workaround && (fifocnt == 1) &&
+	   sreg_dataoutp(esp->sreg)) {
+		ESPLOG(("esp%d: Premature interrupt, enabling workaround\n",
+			esp->esp_id));
+#if 0
+		/* Disable scatter-gather operations, they are not possible
+		 * when using this workaround.
+		 */
+		esp->ehost->sg_tablesize = 0;
+		esp->ehost->use_clustering = ENABLE_CLUSTERING;
+		esp->fas_premature_intr_workaround = 1;
+		bytes_sent = 0;
+		if(SCptr->use_sg) {
+			ESPLOG(("esp%d: Aborting scatter-gather operation\n",
+				esp->esp_id));
+			esp->cur_msgout[0] = ABORT;
+			esp->msgout_len = 1;
+			esp->msgout_ctr = 0;
+			esp_cmd(esp, eregs, ESP_CMD_SATN);
+			esp_setcount(eregs, 0xffff);
+			esp_cmd(esp, eregs, ESP_CMD_NULL);
+			esp_cmd(esp, eregs, ESP_CMD_TPAD | ESP_CMD_DMA);
+			return do_intr_end;
+		}
+#else
+		/* Just set the disconnected bit. That's what appears to
+		 * happen anyway. The state machine will pick it up when
+		 * we return.
+		 */
+		esp->ireg |= ESP_INTR_DC;
+#endif
+        }
+
 	if(bytes_sent < 0) {
 		/* I've seen this happen due to lost state in this
 		 * driver.  No idea why it happened, but allowing
 		 * this value to be negative caused things to
 		 * lock up.  This allows greater chance of recovery.
+		 * In fact every time I've seen this, it has been
+		 * a driver bug without question.
 		 */
 		ESPLOG(("esp%d: yieee, bytes_sent < 0!\n", esp->esp_id));
 		ESPLOG(("esp%d: csz=%d fifocount=%d ecount=%d\n",
@@ -2042,6 +2105,10 @@
 		ESPLOG(("esp%d: use_sg=%d ptr=%p this_residual=%d\n",
 			esp->esp_id,
 			SCptr->use_sg, SCptr->SCp.ptr, SCptr->SCp.this_residual));
+		ESPLOG(("esp%d: Forcing async for target %d\n", esp->esp_id, 
+			SCptr->target));
+		SCptr->device->borken = 1;
+		SCptr->device->sync = 0;
 		bytes_sent = 0;
 	}
 
@@ -2050,7 +2117,7 @@
 	SCptr->SCp.this_residual -= bytes_sent;
 	if(SCptr->SCp.this_residual < 0) {
 		/* shit */
-		printk("esp%d: Data transfer overrun.\n", esp->esp_id);
+		ESPLOG(("esp%d: Data transfer overrun.\n", esp->esp_id));
 		SCptr->SCp.this_residual = 0;
 	}
 
@@ -2066,13 +2133,15 @@
 		 * imagine the hell I went through trying to
 		 * figure this out.
 		 */
-		if(SCptr->use_sg && !SCptr->SCp.this_residual)
+		if(!SCptr->SCp.this_residual && SCptr->SCp.buffers_residual)
 			advance_sg(esp, SCptr);
+#ifdef DEBUG_ESP_DATA
 		if(sreg_datainp(esp->sreg) || sreg_dataoutp(esp->sreg)) {
 			ESPDATA(("to more data\n"));
-			return esp_do_data(esp, eregs);
+		} else {
+			ESPDATA(("to new phase\n"));
 		}
-		ESPDATA(("to new phase\n"));
+#endif
 		return esp_do_phase_determine(esp, eregs);
 	}
 	/* Bogus data, just wait for next interrupt. */
@@ -2081,10 +2150,48 @@
 	return do_intr_end;
 }
 
+/* We received a non-good status return at the end of
+ * running a SCSI command.  This is used to decide if
+ * we should clear our synchronous transfer state for
+ * such a device when that happens.
+ *
+ * The idea is that when spinning up a disk or rewinding
+ * a tape, we don't want to go into a loop re-negotiating
+ * synchronous capabilities over and over.
+ */
+static int esp_should_clear_sync(Scsi_Cmnd *sp)
+{
+	unchar cmd1 = sp->cmnd[0];
+	unchar cmd2 = sp->data_cmnd[0];
+
+	/* These cases are for spinning up a disk and
+	 * waiting for that spinup to complete.
+	 */
+	if(cmd1 == START_STOP ||
+	   cmd2 == START_STOP)
+		return 0;
+
+	if(cmd1 == TEST_UNIT_READY ||
+	   cmd2 == TEST_UNIT_READY)
+		return 0;
+
+	/* One more special case for SCSI tape drives,
+	 * this is what is used to probe the device for
+	 * completion of a rewind or tape load operation.
+	 */
+	if(sp->device->type == TYPE_TAPE) {
+		if(cmd1 == MODE_SENSE ||
+		   cmd2 == MODE_SENSE)
+			return 0;
+	}
+
+	return 1;
+}
+
 /* Either a command is completing or a target is dropping off the bus
  * to continue the command in the background so we can do other work.
  */
-static inline int esp_do_freebus(struct NCR_ESP *esp, struct ESP_regs *eregs)
+static int esp_do_freebus(struct NCR_ESP *esp, struct ESP_regs *eregs)
 {
 	Scsi_Cmnd *SCptr = esp->current_SC;
 	int rval;
@@ -2101,12 +2208,14 @@
 	esp->prevmsgout = NOP;
 	if(esp->prevmsgin == COMMAND_COMPLETE) {
 		/* Normal end of nexus. */
-		if(esp->disconnected_SC || (esp->erev == fashme))
+		if(esp->disconnected_SC)
 			esp_cmd(esp, eregs, ESP_CMD_ESEL);
 
-		if(SCptr->SCp.Status != GOOD && SCptr->SCp.Status != CONDITION_GOOD &&
+		if(SCptr->SCp.Status != GOOD &&
+		   SCptr->SCp.Status != CONDITION_GOOD &&
 		   ((1<<SCptr->target) & esp->targets_present) &&
-		   SCptr->device->sync && SCptr->device->sync_max_offset) {
+		   SCptr->device->sync &&
+		   SCptr->device->sync_max_offset) {
 			/* SCSI standard says that the synchronous capabilities
 			 * should be renegotiated at this point.  Most likely
 			 * we are about to request sense from this target
@@ -2123,15 +2232,7 @@
 			 * can report not ready many times right after
 			 * loading up a tape.
 			 */
-			if(SCptr->cmnd[0] != START_STOP &&
-			   SCptr->data_cmnd[0] != START_STOP &&
-			   SCptr->cmnd[0] != TEST_UNIT_READY &&
-			   SCptr->data_cmnd[0] != TEST_UNIT_READY &&
-			   !(SCptr->device->type == TYPE_TAPE &&
-			     (SCptr->cmnd[0] == TEST_UNIT_READY ||
-			      SCptr->data_cmnd[0] == TEST_UNIT_READY ||
-			      SCptr->cmnd[0] == MODE_SENSE ||
-			      SCptr->data_cmnd[0] == MODE_SENSE)))
+			if(esp_should_clear_sync(SCptr) != 0)
 				SCptr->device->sync = 0;
 		}
 		ESPDISC(("F<%02x,%02x>", SCptr->target, SCptr->lun));
@@ -2158,9 +2259,43 @@
 	return do_intr_end;
 }
 
+/* When a reselect occurs, and we cannot find the command to
+ * reconnect to in our queues, we do this.
+ */
+static int esp_bad_reconnect(struct NCR_ESP *esp)
+{
+	Scsi_Cmnd *sp;
+
+	ESPLOG(("esp%d: Eieeee, reconnecting unknown command!\n",
+		esp->esp_id));
+	ESPLOG(("QUEUE DUMP\n"));
+	sp = esp->issue_SC;
+	ESPLOG(("esp%d: issue_SC[", esp->esp_id));
+	while(sp) {
+		ESPLOG(("<%02x,%02x>", sp->target, sp->lun));
+		sp = (Scsi_Cmnd *) sp->host_scribble;
+	}
+	ESPLOG(("]\n"));
+	sp = esp->current_SC;
+	ESPLOG(("esp%d: current_SC[", esp->esp_id));
+	while(sp) {
+		ESPLOG(("<%02x,%02x>", sp->target, sp->lun));
+		sp = (Scsi_Cmnd *) sp->host_scribble;
+	}
+	ESPLOG(("]\n"));
+	sp = esp->disconnected_SC;
+	ESPLOG(("esp%d: disconnected_SC[", esp->esp_id));
+	while(sp) {
+		ESPLOG(("<%02x,%02x>", sp->target, sp->lun));
+		sp = (Scsi_Cmnd *) sp->host_scribble;
+	}
+	ESPLOG(("]\n"));
+	return do_reset_bus;
+}
+
 /* Do the needy when a target tries to reconnect to us. */
-static inline int esp_do_reconnect(struct NCR_ESP *esp, 
-				   struct ESP_regs *eregs)
+static int esp_do_reconnect(struct NCR_ESP *esp, 
+			    struct ESP_regs *eregs)
 {
 	int lun, target;
 	Scsi_Cmnd *SCptr;
@@ -2180,53 +2315,21 @@
 	/* Things look ok... */
 	ESPDISC(("R<%02x,%02x>", target, lun));
 
-	/* Must flush both FIFO and the DVMA on HME. */
-	if(esp->erev == fashme) {
-		/* XXX this still doesn't fix the problem... */
-		esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-		if(esp->dma_invalidate)
-			esp->dma_invalidate(esp);
-	} else {
-		esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-		if(esp100_reconnect_hwbug(esp, eregs))
-			return do_reset_bus;
-		esp_cmd(esp, eregs, ESP_CMD_NULL);
-	}
+	esp_cmd(esp, eregs, ESP_CMD_FLUSH);
+	if(esp100_reconnect_hwbug(esp, eregs))
+		return do_reset_bus;
+	esp_cmd(esp, eregs, ESP_CMD_NULL);
 
 	SCptr = remove_SC(&esp->disconnected_SC, (unchar) target, (unchar) lun);
-	if(!SCptr) {
-		Scsi_Cmnd *sp;
+	if(!SCptr)
+		return esp_bad_reconnect(esp);
 
-		ESPLOG(("esp%d: Eieeee, reconnecting unknown command!\n",
-			esp->esp_id));
-		ESPLOG(("QUEUE DUMP\n"));
-		sp = esp->issue_SC;
-		ESPLOG(("esp%d: issue_SC[", esp->esp_id));
-		while(sp) {
-			ESPLOG(("<%02x,%02x>", sp->target, sp->lun));
-			sp = (Scsi_Cmnd *) sp->host_scribble;
-		}
-		ESPLOG(("]\n"));
-		sp = esp->current_SC;
-		ESPLOG(("esp%d: current_SC[", esp->esp_id));
-		while(sp) {
-			ESPLOG(("<%02x,%02x>", sp->target, sp->lun));
-			sp = (Scsi_Cmnd *) sp->host_scribble;
-		}
-		ESPLOG(("]\n"));
-		sp = esp->disconnected_SC;
-		ESPLOG(("esp%d: disconnected_SC[", esp->esp_id));
-		while(sp) {
-			ESPLOG(("<%02x,%02x>", sp->target, sp->lun));
-			sp = (Scsi_Cmnd *) sp->host_scribble;
-		}
-		ESPLOG(("]\n"));
-		return do_reset_bus;
-	}
 	esp_connect(esp, eregs, SCptr);
 	esp_cmd(esp, eregs, ESP_CMD_MOK);
 
-	/* No need for explicit restore pointers operation. */
+	/* Reconnect implies a restore pointers operation. */
+	esp_restore_pointers(esp, SCptr);
+
 	esp->snip = 0;
 	esp_advance_phase(SCptr, in_the_dark);
 	return do_intr_end;
@@ -2348,121 +2451,132 @@
 	}
 }
 
-/* The target has control of the bus and we have to see where it has
- * taken us.
- */
-static int esp_do_phase_determine(struct NCR_ESP *esp,
-				  struct ESP_regs *eregs)
+static int esp_enter_status(struct NCR_ESP *esp,
+			    struct ESP_regs *eregs)
 {
-	Scsi_Cmnd *SCptr = esp->current_SC;
+	unchar thecmd = ESP_CMD_ICCSEQ;
 
-	ESPPHASE(("esp_do_phase_determine: "));
-	if(!(esp->ireg & ESP_INTR_DC)) {
-		switch(esp->sreg & ESP_STAT_PMASK) {
-		case ESP_DOP:
-		case ESP_DIP:
-			ESPPHASE(("to data phase\n"));
-			return esp_do_data(esp, eregs);
+	esp_cmd(esp, eregs, ESP_CMD_FLUSH);
 
-		case ESP_STATP:
-			/* Whee, status phase, finish up the command. */
-			ESPPHASE(("to status phase\n"));
+	if(esp->do_pio_cmds) {
+		esp_advance_phase(esp->current_SC, in_status);
+		esp_cmd(esp, eregs, thecmd);
+		while(!(esp_read(esp->eregs->esp_status) & ESP_STAT_INTR));
+		esp->esp_command[0] = esp_read(eregs->esp_fdata);
+                while(!(esp_read(esp->eregs->esp_status) & ESP_STAT_INTR));
+                esp->esp_command[1] = esp_read(eregs->esp_fdata);
+	} else {
+		esp->esp_command[0] = esp->esp_command[1] = 0xff;
+		esp_write(eregs->esp_tclow, 2);
+		esp_write(eregs->esp_tcmed, 0);
+		esp->dma_init_read(esp, esp->esp_command_dvma, 2);
+		thecmd |= ESP_CMD_DMA;
+		esp_cmd(esp, eregs, thecmd);
+		esp_advance_phase(esp->current_SC, in_status);
+	}
 
-			esp_cmd(esp, eregs, ESP_CMD_FLUSH);
+	return esp_do_status(esp, eregs);
+}
 
-			if(esp->do_pio_cmds){
-				esp_advance_phase(SCptr, in_status);
-				esp_cmd(esp, eregs, ESP_CMD_ICCSEQ);
-				while(!(GETREG(esp->eregs->esp_status)
-				 & ESP_STAT_INTR));
-				esp->esp_command[0] = GETREG(eregs->esp_fdata);
-				while(!(GETREG(esp->eregs->esp_status)
-				 & ESP_STAT_INTR));
-				esp->esp_command[1] = GETREG(eregs->esp_fdata);
-			} else {				
-				if(esp->erev != fashme) {
-					esp->esp_command[0] = 0xff;
-					esp->esp_command[1] = 0xff;
-					SETREG(eregs->esp_tclow, 2);
-					SETREG(eregs->esp_tcmed, 0);
-					esp->dma_init_read(esp, esp->esp_command_dvma, 2);
-					esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_ICCSEQ);
-				} else {
-					/* Using DVMA for status/message bytes is
-					 * unreliable on HME, nice job QLogic.
-					 * Happy Meal indeed....
-					 */
-					esp_cmd(esp, eregs, ESP_CMD_ICCSEQ);
-				}
-				esp_advance_phase(SCptr, in_status);
-			}
-			return esp_do_status(esp, eregs);
+static int esp_disconnect_amidst_phases(struct NCR_ESP *esp,
+					struct ESP_regs *eregs)
+{
+	Scsi_Cmnd *sp = esp->current_SC;
+	Scsi_Device *dp = sp->device;
 
-		case ESP_MOP:
-			ESPPHASE(("to msgout phase\n"));
-			esp_advance_phase(SCptr, in_msgout);
-			return esp_do_msgout(esp, eregs);
-
-		case ESP_MIP:
-			ESPPHASE(("to msgin phase\n"));
-			esp_advance_phase(SCptr, in_msgin);
-			return esp_do_msgin(esp, eregs);
-
-		case ESP_CMDP:
-			/* Ugh, we're running a non-standard command the
-			 * ESP doesn't understand, one byte at a time.
-			 */
-			ESPPHASE(("to cmd phase\n"));
-			esp_advance_phase(SCptr, in_cmdbegin);
-			return esp_do_cmdbegin(esp, eregs);
-		};
-	} else {
-		Scsi_Device *dp = SCptr->device;
+	/* This means real problems if we see this
+	 * here.  Unless we were actually trying
+	 * to force the device to abort/reset.
+	 */
+	ESPLOG(("esp%d: Disconnect amidst phases, ", esp->esp_id));
+	ESPLOG(("pphase<%s> cphase<%s>, ",
+		phase_string(sp->SCp.phase),
+		phase_string(sp->SCp.sent_command)));
 
-		/* This means real problems if we see this
-		 * here.  Unless we were actually trying
-		 * to force the device to abort/reset.
-		 */
-		ESPLOG(("esp%d Disconnect amidst phases, ", esp->esp_id));
-		ESPLOG(("pphase<%s> cphase<%s>, ",
-			phase_string(SCptr->SCp.phase),
-			phase_string(SCptr->SCp.sent_command)));
-		if(esp->disconnected_SC || (esp->erev == fashme))
-			esp_cmd(esp, eregs, ESP_CMD_ESEL);
+	if(esp->disconnected_SC)
+		esp_cmd(esp, eregs, ESP_CMD_ESEL);
 
-		switch(esp->cur_msgout[0]) {
-		default:
-			/* We didn't expect this to happen at all. */
-			ESPLOG(("device is bolixed\n"));
-			esp_advance_phase(SCptr, in_tgterror);
-			esp_done(esp, (DID_ERROR << 16));
-			break;
+	switch(esp->cur_msgout[0]) {
+	default:
+		/* We didn't expect this to happen at all. */
+		ESPLOG(("device is bolixed\n"));
+		esp_advance_phase(sp, in_tgterror);
+		esp_done(esp, (DID_ERROR << 16));
+		break;
+
+	case BUS_DEVICE_RESET:
+		ESPLOG(("device reset successful\n"));
+		dp->sync_max_offset = 0;
+		dp->sync_min_period = 0;
+		dp->sync = 0;
+		esp_advance_phase(sp, in_resetdev);
+		esp_done(esp, (DID_RESET << 16));
+		break;
+
+	case ABORT:
+		ESPLOG(("device abort successful\n"));
+		esp_advance_phase(sp, in_abortone);
+		esp_done(esp, (DID_ABORT << 16));
+		break;
 
-		case BUS_DEVICE_RESET:
-			ESPLOG(("device reset successful\n"));
-			dp->sync_max_offset = 0;
-			dp->sync_min_period = 0;
-			dp->sync = 0;
-			esp_advance_phase(SCptr, in_resetdev);
-			esp_done(esp, (DID_RESET << 16));
-			break;
+	};
+	return do_intr_end;
+}
 
-		case ABORT:
-			ESPLOG(("device abort successful\n"));
-			esp_advance_phase(SCptr, in_abortone);
-			esp_done(esp, (DID_ABORT << 16));
-			break;
+static int esp_enter_msgout(struct NCR_ESP *esp,
+			    struct ESP_regs *eregs)
+{
+	esp_advance_phase(esp->current_SC, in_msgout);
+	return esp_do_msgout(esp, eregs);
+}
 
-		};
-		return do_intr_end;
-	}
+static int esp_enter_msgin(struct NCR_ESP *esp,
+			   struct ESP_regs *eregs)
+{
+	esp_advance_phase(esp->current_SC, in_msgin);
+	return esp_do_msgin(esp, eregs);
+}
+
+static int esp_enter_cmd(struct NCR_ESP *esp,
+			 struct ESP_regs *eregs)
+{
+	esp_advance_phase(esp->current_SC, in_cmdbegin);
+	return esp_do_cmdbegin(esp, eregs);
+}
 
-	ESPLOG(("esp%d: to unknown phase\n", esp->esp_id));
-	printk("esp%d: Bizarre bus phase %2x.\n", esp->esp_id,
-	       esp->sreg & ESP_STAT_PMASK);
+static int esp_enter_badphase(struct NCR_ESP *esp,
+			      struct ESP_regs *eregs)
+{
+	ESPLOG(("esp%d: Bizarre bus phase %2x.\n", esp->esp_id,
+		esp->sreg & ESP_STAT_PMASK));
 	return do_reset_bus;
 }
 
+typedef int (*espfunc_t)(struct NCR_ESP *,
+			 struct ESP_regs *);
+
+static espfunc_t phase_vector[] = {
+	esp_do_data,		/* ESP_DOP */
+	esp_do_data,		/* ESP_DIP */
+	esp_enter_cmd,		/* ESP_CMDP */
+	esp_enter_status,	/* ESP_STATP */
+	esp_enter_badphase,	/* ESP_STAT_PMSG */
+	esp_enter_badphase,	/* ESP_STAT_PMSG | ESP_STAT_PIO */
+	esp_enter_msgout,	/* ESP_MOP */
+	esp_enter_msgin,	/* ESP_MIP */
+};
+
+/* The target has control of the bus and we have to see where it has
+ * taken us.
+ */
+static int esp_do_phase_determine(struct NCR_ESP *esp,
+				  struct ESP_regs *eregs)
+{
+	if ((esp->ireg & ESP_INTR_DC) != 0)
+		return esp_disconnect_amidst_phases(esp, eregs);
+	return phase_vector[esp->sreg & ESP_STAT_PMASK](esp, eregs);
+}
+
 /* First interrupt after exec'ing a cmd comes here. */
 static int esp_select_complete(struct NCR_ESP *esp, struct ESP_regs *eregs)
 {
@@ -2470,12 +2584,7 @@
 	Scsi_Device *SDptr = SCptr->device;
 	int cmd_bytes_sent, fcnt;
 
-	if(esp->erev != fashme)
-		esp->seqreg = (GETREG(eregs->esp_sstep) & ESP_STEP_VBITS);
-	if(esp->erev == fashme)
-		fcnt = esp->hme_fifo_workaround_count;
-	else
-		fcnt = (GETREG(eregs->esp_fflags) & ESP_FF_FBYTES);
+	fcnt = (esp_read(eregs->esp_fflags) & ESP_FF_FBYTES);
 	cmd_bytes_sent = esp->dma_bytes_sent(esp, fcnt);
 	if(esp->dma_invalidate)
 		esp->dma_invalidate(esp);
@@ -2583,14 +2692,12 @@
 			if(SCptr->SCp.phase == in_slct_norm)
 				cmd_bytes_sent -= 1;
 		};
-		if(esp->erev != fashme)
-			esp_cmd(esp, eregs, ESP_CMD_NULL);
+		esp_cmd(esp, eregs, ESP_CMD_NULL);
 
 		/* Be careful, we could really get fucked during synchronous
 		 * data transfers if we try to flush the fifo now.
 		 */
-		if((esp->erev != fashme) && /* not a Happy Meal and... */
-		   !fcnt && /* Fifo is empty and... */
+		if(!fcnt && /* Fifo is empty and... */
 		   /* either we are not doing synchronous transfers or... */
 		   (!SDptr->sync_max_offset ||
 		    /* We are not going into data in phase. */
@@ -2651,9 +2758,8 @@
 		    SCptr->SCp.phase == in_slct_stop)) {
 			/* shit */
 			esp->snip = 0;
-			printk("esp%d: Failed synchronous negotiation for target %d "
-			       "lun %d\n",
-			       esp->esp_id, SCptr->target, SCptr->lun);
+			ESPLOG(("esp%d: Failed synchronous negotiation for target %d "
+				"lun %d\n", esp->esp_id, SCptr->target, SCptr->lun));
 			SDptr->sync_max_offset = 0;
 			SDptr->sync_min_period = 0;
 			SDptr->sync = 1; /* so we don't negotiate again */
@@ -2680,8 +2786,8 @@
 		 * But first make sure that is really what is happening.
 		 */
 		if(((1<<SCptr->target) & esp->targets_present)) {
-			printk("esp%d: Warning, live target %d not responding to "
-			       "selection.\n", esp->esp_id, SCptr->target);
+			ESPLOG(("esp%d: Warning, live target %d not responding to "
+				"selection.\n", esp->esp_id, SCptr->target));
 
 			/* This _CAN_ happen.  The SCSI standard states that
 			 * the target is to _not_ respond to selection if
@@ -2710,9 +2816,9 @@
 	esp_print_seqreg(esp->seqreg);
 	printk("\n");
 	printk("esp%d: New -- ", esp->esp_id);
-	esp->sreg = GETREG(eregs->esp_status);
-	esp->seqreg = GETREG(eregs->esp_sstep);
-	esp->ireg = GETREG(eregs->esp_intrpt);
+	esp->sreg = esp_read(eregs->esp_status);
+	esp->seqreg = esp_read(eregs->esp_sstep);
+	esp->ireg = esp_read(eregs->esp_intrpt);
 	esp_print_ireg(esp->ireg);
 	printk(" ");
 	esp_print_statreg(esp->sreg);
@@ -2743,14 +2849,14 @@
 		 * have miscoded something..... so, try to
 		 * recover as best we can.
 		 */
-		printk("esp%d: message in mis-carriage.\n", esp->esp_id);
+		ESPLOG(("esp%d: message in mis-carriage.\n", esp->esp_id));
 	}
 	esp_advance_phase(esp->current_SC, in_the_dark);
 	return do_phase_determine;
 }
 
-static inline int check_singlebyte_msg(struct NCR_ESP *esp,
-				       struct ESP_regs *eregs)
+static int check_singlebyte_msg(struct NCR_ESP *esp,
+				struct ESP_regs *eregs)
 {
 	esp->prevmsgin = esp->cur_msgin[0];
 	if(esp->cur_msgin[0] & 0x80) {
@@ -2779,8 +2885,20 @@
 		return 0;
 
 	case RESTORE_POINTERS:
+		/* In this case we might also have to backup the
+		 * "slow command" pointer.  It is rare to get such
+		 * a save/restore pointer sequence so early in the
+		 * bus transition sequences, but cover it.
+		 */
+		if(esp->esp_slowcmd) {
+			esp->esp_scmdleft = esp->current_SC->cmd_len;
+			esp->esp_scmdp = &esp->current_SC->cmnd[0];
+		}
+		esp_restore_pointers(esp, esp->current_SC);
+		return 0;
+
 	case SAVE_POINTERS:
-		/* We handle this all automatically. */
+		esp_save_pointers(esp, esp->current_SC);
 		return 0;
 
 	case COMMAND_COMPLETE:
@@ -2815,9 +2933,9 @@
  * the SCSI2 standard specifically recommends against targets doing
  * this because so many initiators cannot cope with this occuring.
  */
-static inline int target_with_ants_in_pants(struct NCR_ESP *esp,
-					    Scsi_Cmnd *SCptr,
-					    Scsi_Device *SDptr)
+static int target_with_ants_in_pants(struct NCR_ESP *esp,
+				     Scsi_Cmnd *SCptr,
+				     Scsi_Device *SDptr)
 {
 	if(SDptr->sync || SDptr->borken) {
 		/* sorry, no can do */
@@ -2834,7 +2952,7 @@
 	return 0;
 }
 
-static inline void sync_report(struct NCR_ESP *esp)
+static void sync_report(struct NCR_ESP *esp)
 {
 	int msg3, msg4;
 	char *type;
@@ -2845,30 +2963,31 @@
 		int hz = 1000000000 / (msg3 * 4);
 		int integer = hz / 1000000;
 		int fraction = (hz - (integer * 1000000)) / 10000;
-		if((esp->erev == fashme) &&
-		   (esp->config3[esp->current_SC->target] & ESP_CONFIG3_EWIDE)) {
-			type = "FAST-WIDE";
-			integer <<= 1;
-			fraction <<= 1;
-		} else if((msg3 * 4) < 200) {
+		if((msg3 * 4) < 200) {
 			type = "FAST";
 		} else {
 			type = "synchronous";
 		}
-		printk(KERN_INFO "esp%d: target %d [period %dns offset %d %d.%02dMHz %s SCSI%s]\n",
-		       esp->esp_id, esp->current_SC->target,
-		       (int) msg3 * 4,
-		       (int) msg4,
-		       integer, fraction, type,
-		       (((msg3 * 4) < 200) ? "-II" : ""));
+
+		/* Do not transform this back into one big printk
+		 * again, it triggers a bug in our sparc64-gcc272
+		 * sibling call optimization.  -DaveM
+		 */
+		ESPLOG((KERN_INFO "esp%d: target %d ",
+			esp->esp_id, esp->current_SC->target));
+		ESPLOG(("[period %dns offset %d %d.%02dMHz ",
+			(int) msg3 * 4, (int) msg4,
+			integer, fraction));
+		ESPLOG(("%s SCSI%s]\n", type,
+			(((msg3 * 4) < 200) ? "-II" : "")));
 	} else {
-		printk(KERN_INFO "esp%d: target %d asynchronous\n",
-		       esp->esp_id, esp->current_SC->target);
+		ESPLOG((KERN_INFO "esp%d: target %d asynchronous\n",
+			esp->esp_id, esp->current_SC->target));
 	}
 }
 
-static inline int check_multibyte_msg(struct NCR_ESP *esp,
-				       struct ESP_regs *eregs)
+static int check_multibyte_msg(struct NCR_ESP *esp,
+			       struct ESP_regs *eregs)
 {
 	Scsi_Cmnd *SCptr = esp->current_SC;
 	Scsi_Device *SDptr = SCptr->device;
@@ -2923,10 +3042,7 @@
 			ESPSDTR(("period is ok, "));
 			tmp = esp->ccycle / 1000;
 			regval = (((period << 2) + tmp - 1) / tmp);
-			if(regval && ((esp->erev == fas100a ||
-				       esp->erev == fas216 ||				       
-				       esp->erev == fas236 ||
-				       esp->erev == fashme))) {
+			if(regval && (esp->erev > esp236)) {
 				if(period >= 50)
 					regval--;
 			}
@@ -2937,8 +3053,8 @@
 
 			SDptr->sync_min_period = (regval & 0x1f);
 			SDptr->sync_max_offset = (offset | esp->radelay);
-			if((esp->erev == fas100a || esp->erev == fas216 || esp->erev == fas236 || esp->erev == fashme)) {
-				if((esp->erev == fas100a) || (esp->erev == fashme))
+			if(esp->erev > esp236) {
+				if(esp->erev == fas100a)
 					bit = ESP_CONFIG3_FAST;
 				else
 					bit = ESP_CONFIG3_FSCSI;
@@ -2946,11 +3062,13 @@
 					esp->config3[SCptr->target] |= bit;
 				else
 					esp->config3[SCptr->target] &= ~bit;
-				SETREG(eregs->esp_cfg3,
-				 esp->config3[SCptr->target]);
+				esp->prev_cfg3 = esp->config3[SCptr->target];
+				esp_write(eregs->esp_cfg3, esp->prev_cfg3);
 			}
-			SETREG(eregs->esp_soff, SDptr->sync_min_period);
-			SETREG(eregs->esp_stp, SDptr->sync_max_offset);
+			esp->prev_soff = SDptr->sync_min_period;
+			esp_write(eregs->esp_soff, esp->prev_soff);
+			esp->prev_stp = SDptr->sync_max_offset;
+			esp_write(eregs->esp_stp, esp->prev_stp);
 
 			ESPSDTR(("soff=%2x stp=%2x cfg3=%2x\n",
 				SDptr->sync_max_offset,
@@ -2965,16 +3083,18 @@
 			ESPSDTR(("unaccaptable sync nego, forcing async\n"));
 			SDptr->sync_max_offset = 0;
 			SDptr->sync_min_period = 0;
-			SETREG(eregs->esp_soff, 0);
-			SETREG(eregs->esp_stp, 0);
-			if((esp->erev == fas100a || esp->erev == fas216 || esp->erev == fas236 || esp->erev == fashme)) {
-				if((esp->erev == fas100a) || (esp->erev == fashme))
+			esp->prev_soff = 0;
+			esp_write(eregs->esp_soff, 0);
+			esp->prev_stp = 0;
+			esp_write(eregs->esp_stp, 0);
+			if(esp->erev > esp236) {
+				if(esp->erev == fas100a)
 					bit = ESP_CONFIG3_FAST;
 				else
 					bit = ESP_CONFIG3_FSCSI;
 				esp->config3[SCptr->target] &= ~bit;
-				SETREG(eregs->esp_cfg3,
-				 esp->config3[SCptr->target]);
+				esp->prev_cfg3 = esp->config3[SCptr->target];
+				esp_write(eregs->esp_cfg3, esp->prev_cfg3);
 			}
 		}
 
@@ -2995,48 +3115,12 @@
 		esp_advance_phase(SCptr, in_the_dark); /* ...or else! */
 		return 0;
 	} else if(esp->cur_msgin[2] == EXTENDED_WDTR) {
-		int size = 8 << esp->cur_msgin[3];
-
-		esp->wnip = 0;
-		if(esp->erev != fashme) {
-			printk("esp%d: AIEEE wide msg received and not HME.\n",
-			       esp->esp_id);
-			message_out = MESSAGE_REJECT;
-		} else if(size > 16) {
-			printk("esp%d: AIEEE wide transfer for %d size not supported.\n",
-			       esp->esp_id, size);
-			message_out = MESSAGE_REJECT;
-		} else {
-			/* Things look good; let's see what we got. */
-			if(size == 16) {
-				/* Set config 3 register for this target. */
-				printk("esp%d: 16 byte WIDE transfers enabled for target %d.\n",
-				       esp->esp_id, SCptr->target);
-				esp->config3[SCptr->target] |= ESP_CONFIG3_EWIDE;
-			} else {
-				/* Just make sure it was one byte sized. */
-				if(size != 8) {
-					printk("esp%d: Aieee, wide nego of %d size.\n",
-					       esp->esp_id, size);
-					message_out = MESSAGE_REJECT;
-					goto finish;
-				}
-				/* Pure paranoia. */
-				esp->config3[SCptr->target] &= ~(ESP_CONFIG3_EWIDE);
-			}
-			SETREG(eregs->esp_cfg3, esp->config3[SCptr->target]);
-
-			/* Regardless, next try for sync transfers. */
-			build_sync_nego_msg(esp, esp->sync_defp, 15);
-			SDptr->sync = 1;
-			esp->snip = 1;
-			message_out = EXTENDED_MESSAGE;
-		}
+		ESPLOG(("esp%d: AIEEE wide msg received\n", esp->esp_id));
+		message_out = MESSAGE_REJECT;
 	} else if(esp->cur_msgin[2] == EXTENDED_MODIFY_DATA_POINTER) {
 		ESPLOG(("esp%d: rejecting modify data ptr msg\n", esp->esp_id));
 		message_out = MESSAGE_REJECT;
 	}
-finish:
 	esp_advance_phase(SCptr, in_the_dark);
 	return message_out;
 }
@@ -3054,26 +3138,17 @@
 			if(esp->msgin_len && (esp->sreg & ESP_STAT_PERR)) {
 				message_out = MSG_PARITY_ERROR;
 				esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-			} else if(esp->erev != fashme &&
-				  (it = (GETREG(eregs->esp_fflags)
-				  & ESP_FF_FBYTES))!=1) {
+			} else if((it = (esp_read(eregs->esp_fflags) & ESP_FF_FBYTES))!=1) {
 				/* We certainly dropped the ball somewhere. */
 				message_out = INITIATOR_ERROR;
 				esp_cmd(esp, eregs, ESP_CMD_FLUSH);
 			} else if(!esp->msgin_len) {
-				if(esp->erev == fashme)
-					it = esp->hme_fifo_workaround_buffer[0];
-				else
-					it = GETREG(eregs->esp_fdata);
+				it = esp_read(eregs->esp_fdata);
 				esp_advance_phase(SCptr, in_msgincont);
 			} else {
 				/* it is ok and we want it */
-				if(esp->erev == fashme)
-					it = esp->cur_msgin[esp->msgin_ctr] =
-						esp->hme_fifo_workaround_buffer[0];
-				else
-					it = esp->cur_msgin[esp->msgin_ctr] =
-						GETREG(eregs->esp_fdata);
+				it = esp->cur_msgin[esp->msgin_ctr] =
+					esp_read(eregs->esp_fdata);
 				esp->msgin_ctr++;
 			}
 		} else {
@@ -3114,7 +3189,7 @@
 		esp_advance_phase(SCptr, in_the_dark);
 		esp->msgin_len = 0;
 	}
-	esp->sreg = GETREG(eregs->esp_status);
+	esp->sreg = esp_read(eregs->esp_status);
 	esp->sreg &= ~(ESP_STAT_INTR);
 	if((esp->sreg & (ESP_STAT_PMSG|ESP_STAT_PCD)) == (ESP_STAT_PMSG|ESP_STAT_PCD))
 		esp_cmd(esp, eregs, ESP_CMD_MOK);
@@ -3126,35 +3201,21 @@
 
 static int esp_do_cmdbegin(struct NCR_ESP *esp, struct ESP_regs *eregs)
 {
+	unsigned char tmp;
 	Scsi_Cmnd *SCptr = esp->current_SC;
 
 	esp_advance_phase(SCptr, in_cmdend);
-	if(esp->erev == fashme) {
-		int i;
-
-		for(i = 0; i < esp->esp_scmdleft; i++)
-			esp->esp_command[i] = *esp->esp_scmdp++;
-		esp->esp_scmdleft = 0;
-		esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-		esp_setcount(eregs, i, 1);
-		esp_cmd(esp, eregs, (ESP_CMD_DMA | ESP_CMD_TI));
-		esp->dma_init_write(esp, esp->esp_command_dvma, i);
-	} else {
-		esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-		SETREG(eregs->esp_fdata, *esp->esp_scmdp++);
-		esp->esp_scmdleft--;
-		esp_cmd(esp, eregs, ESP_CMD_TI);
-	}
+	esp_cmd(esp, eregs, ESP_CMD_FLUSH);
+	tmp = *esp->esp_scmdp++;
+	esp->esp_scmdleft--;
+	esp_write(eregs->esp_fdata, tmp);
+	esp_cmd(esp, eregs, ESP_CMD_TI);
 	return do_intr_end;
 }
 
-static inline int esp_do_cmddone(struct NCR_ESP *esp, struct ESP_regs *eregs)
+static int esp_do_cmddone(struct NCR_ESP *esp, struct ESP_regs *eregs)
 {
-	if(esp->erev == fashme){
-		if(esp->dma_invalidate)
-			esp->dma_invalidate(esp);
-	} else
-		esp_cmd(esp, eregs, ESP_CMD_NULL);
+	esp_cmd(esp, eregs, ESP_CMD_NULL);
 	if(esp->ireg & ESP_INTR_BSERV) {
 		esp_advance_phase(esp->current_SC, in_the_dark);
 		return esp_do_phase_determine(esp, eregs);
@@ -3169,79 +3230,61 @@
 	esp_cmd(esp, eregs, ESP_CMD_FLUSH);
 	switch(esp->msgout_len) {
 	case 1:
-		if(esp->erev == fashme)
-			hme_fifo_push(esp, eregs, &esp->cur_msgout[0], 1);
-		else
-			SETREG(eregs->esp_fdata, esp->cur_msgout[0]);
+		esp_write(eregs->esp_fdata, esp->cur_msgout[0]);
 		esp_cmd(esp, eregs, ESP_CMD_TI);
 		break;
 
 	case 2:
 		if(esp->do_pio_cmds){
-			SETREG(eregs->esp_fdata, esp->cur_msgout[0]);
-			SETREG(eregs->esp_fdata, esp->cur_msgout[1]);
+			esp_write(eregs->esp_fdata, esp->cur_msgout[0]);
+			esp_write(eregs->esp_fdata, esp->cur_msgout[1]);
 			esp_cmd(esp, eregs, ESP_CMD_TI);
 		} else {
 			esp->esp_command[0] = esp->cur_msgout[0];
 			esp->esp_command[1] = esp->cur_msgout[1];
-			if(esp->erev == fashme) {
-				hme_fifo_push(esp, eregs, &esp->cur_msgout[0], 2);
-				esp_cmd(esp, eregs, ESP_CMD_TI);
-			} else {
-				esp->dma_setup(esp, esp->esp_command_dvma, 2, 0);
-				esp_setcount(eregs, 2, 0);
-				esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
-			}
+			esp->dma_setup(esp, esp->esp_command_dvma, 2, 0);
+			esp_setcount(eregs, 2);
+			esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
 		}
 		break;
 
 	case 4:
 		esp->snip = 1;
 		if(esp->do_pio_cmds){
-			SETREG(eregs->esp_fdata, esp->cur_msgout[0]);
-			SETREG(eregs->esp_fdata, esp->cur_msgout[1]);
-			SETREG(eregs->esp_fdata, esp->cur_msgout[2]);
-			SETREG(eregs->esp_fdata, esp->cur_msgout[3]);
+			esp_write(eregs->esp_fdata, esp->cur_msgout[0]);
+			esp_write(eregs->esp_fdata, esp->cur_msgout[1]);
+			esp_write(eregs->esp_fdata, esp->cur_msgout[2]);
+			esp_write(eregs->esp_fdata, esp->cur_msgout[3]);
 			esp_cmd(esp, eregs, ESP_CMD_TI);
 		} else {
 			esp->esp_command[0] = esp->cur_msgout[0];
 			esp->esp_command[1] = esp->cur_msgout[1];
 			esp->esp_command[2] = esp->cur_msgout[2];
 			esp->esp_command[3] = esp->cur_msgout[3];
-			if(esp->erev == fashme) {
-				hme_fifo_push(esp, eregs, &esp->cur_msgout[0], 4);
-				esp_cmd(esp, eregs, ESP_CMD_TI);
-			} else {
-				esp->dma_setup(esp, esp->esp_command_dvma, 4, 0);
-				esp_setcount(eregs, 4, 0);
-				esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
-			}
+			esp->dma_setup(esp, esp->esp_command_dvma, 4, 0);
+			esp_setcount(eregs, 4);
+			esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
 		}
 		break;
 
 	case 5:
 		esp->snip = 1;
 		if(esp->do_pio_cmds){
-			SETREG(eregs->esp_fdata, esp->cur_msgout[0]);
-			SETREG(eregs->esp_fdata, esp->cur_msgout[1]);
-			SETREG(eregs->esp_fdata, esp->cur_msgout[2]);
-			SETREG(eregs->esp_fdata, esp->cur_msgout[3]);
-			SETREG(eregs->esp_fdata, esp->cur_msgout[4]);
+			esp_write(eregs->esp_fdata, esp->cur_msgout[0]);
+			esp_write(eregs->esp_fdata, esp->cur_msgout[1]);
+			esp_write(eregs->esp_fdata, esp->cur_msgout[2]);
+			esp_write(eregs->esp_fdata, esp->cur_msgout[3]);
+			esp_write(eregs->esp_fdata, esp->cur_msgout[4]);
 			esp_cmd(esp, eregs, ESP_CMD_TI);
 		} else {
-			SETREG(esp->esp_command[0], esp->cur_msgout[0]);
-			SETREG(esp->esp_command[1], esp->cur_msgout[1]);
-			SETREG(esp->esp_command[2], esp->cur_msgout[2]);
-			SETREG(esp->esp_command[3], esp->cur_msgout[3]);
-			SETREG(esp->esp_command[4], esp->cur_msgout[4]);
-			if(esp->erev == fashme) {
-				hme_fifo_push(esp, eregs, &esp->cur_msgout[0], 5);
-				esp_cmd(esp, eregs, ESP_CMD_TI);
-			} else {
-				esp->dma_setup(esp, esp->esp_command_dvma, 5, 0);
-				esp_setcount(eregs, 5, 0);
-				esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
-			}
+			esp->esp_command[0] = esp->cur_msgout[0];
+			esp->esp_command[1] = esp->cur_msgout[1];
+			esp->esp_command[2] = esp->cur_msgout[2];
+			esp->esp_command[3] = esp->cur_msgout[3];
+			esp->esp_command[4] = esp->cur_msgout[4];
+			esp->dma_setup(esp, esp->esp_command_dvma, 5, 0);
+			esp_setcount(eregs, 5);
+			esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
 		}
 		break;
 
@@ -3249,11 +3292,7 @@
 		/* whoops */
 		ESPMISC(("bogus msgout sending NOP\n"));
 		esp->cur_msgout[0] = NOP;
-		if(esp->erev == fashme) {
-			hme_fifo_push(esp, eregs, &esp->cur_msgout[0], 1);
-		} else {
-			SETREG(eregs->esp_fdata, esp->cur_msgout[0]);
-		}
+		esp_write(eregs->esp_fdata, esp->cur_msgout[0]);
 		esp->msgout_len = 1;
 		esp_cmd(esp, eregs, ESP_CMD_TI);
 		break;
@@ -3262,15 +3301,14 @@
 	return do_intr_end;
 }
 
-static inline int esp_do_msgoutdone(struct NCR_ESP *esp, 
-				    struct ESP_regs *eregs)
+static int esp_do_msgoutdone(struct NCR_ESP *esp, 
+			     struct ESP_regs *eregs)
 {
 	if((esp->msgout_len > 1) && esp->dma_barrier)
 		esp->dma_barrier(esp);
 
 	if(!(esp->ireg & ESP_INTR_DC)) {
-		if(esp->erev != fashme)
-			esp_cmd(esp, eregs, ESP_CMD_NULL);
+		esp_cmd(esp, eregs, ESP_CMD_NULL);
 		switch(esp->sreg & ESP_STAT_PMASK) {
 		case ESP_MOP:
 			/* whoops, parity error */
@@ -3285,17 +3323,12 @@
 			break;
 
 		default:
-			/* Happy Meal fifo is touchy... */
-			if((esp->erev != fashme) &&
-			   !fcount(esp, eregs) &&
+			if(!fcount(esp, eregs) &&
 			   !(esp->current_SC->device->sync_max_offset))
 				esp_cmd(esp, eregs, ESP_CMD_FLUSH);
 			break;
 
 		};
-	} else {
-		ESPLOG(("esp%d: disconnect, resetting bus\n", esp->esp_id));
-		return do_reset_bus;
 	}
 
 	/* If we sent out a synchronous negotiation message, update
@@ -3312,89 +3345,66 @@
 	return esp_do_phase_determine(esp, eregs);
 }
 
+static int esp_bus_unexpected(struct NCR_ESP *esp, struct ESP_regs *eregs)
+{
+	ESPLOG(("esp%d: command in weird state %2x\n",
+		esp->esp_id, esp->current_SC->SCp.phase));
+	return do_reset_bus;
+}
+
+static espfunc_t bus_vector[] = {
+	esp_do_data_finale,
+	esp_do_data_finale,
+	esp_bus_unexpected,
+	esp_do_msgin,
+	esp_do_msgincont,
+	esp_do_msgindone,
+	esp_do_msgout,
+	esp_do_msgoutdone,
+	esp_do_cmdbegin,
+	esp_do_cmddone,
+	esp_do_status,
+	esp_do_freebus,
+	esp_do_phase_determine,
+	esp_bus_unexpected,
+	esp_bus_unexpected,
+	esp_bus_unexpected,
+};
+
 /* This is the second tier in our dual-level SCSI state machine. */
-static inline int esp_work_bus(struct NCR_ESP *esp, struct ESP_regs *eregs)
+static int esp_work_bus(struct NCR_ESP *esp, struct ESP_regs *eregs)
 {
 	Scsi_Cmnd *SCptr = esp->current_SC;
+	unsigned int phase;
 
 	ESPBUS(("esp_work_bus: "));
 	if(!SCptr) {
 		ESPBUS(("reconnect\n"));
 		return esp_do_reconnect(esp, eregs);
 	}
-
-	switch(SCptr->SCp.phase) {
-	case in_the_dark:
-		ESPBUS(("in the dark\n"));
-		return esp_do_phase_determine(esp, eregs);
-
-	case in_slct_norm:
-	case in_slct_stop:
-	case in_slct_msg:
-	case in_slct_tag:
-	case in_slct_sneg:
-		ESPBUS(("finish selection\n"));
+	phase = SCptr->SCp.phase;
+	if ((phase & 0xf0) == in_phases_mask)
+		return bus_vector[(phase & 0x0f)](esp, eregs);
+	else if((phase & 0xf0) == in_slct_mask)
 		return esp_select_complete(esp, eregs);
-
-	case in_datain:
-	case in_dataout:
-		ESPBUS(("finish data\n"));
-		return esp_do_data_finale(esp, eregs);
-
-	case in_msgout:
-		ESPBUS(("message out "));
-		return esp_do_msgout(esp, eregs);
-
-	case in_msgoutdone:
-		ESPBUS(("finish message out "));
-		return esp_do_msgoutdone(esp, eregs);
-
-	case in_msgin:
-		ESPBUS(("message in "));
-		return esp_do_msgin(esp, eregs);
-
-	case in_msgincont:
-		ESPBUS(("continue message in "));
-		return esp_do_msgincont(esp, eregs);
-
-	case in_msgindone:
-		ESPBUS(("finish message in "));
-		return esp_do_msgindone(esp, eregs);
-
-	case in_status:
-		ESPBUS(("status phase "));
-		return esp_do_status(esp, eregs);
-
-	case in_freeing:
-		ESPBUS(("freeing the bus "));
-		return esp_do_freebus(esp, eregs);
-
-	case in_cmdbegin:
-		ESPBUS(("begin slow cmd "));
-		return esp_do_cmdbegin(esp, eregs);
-
-	case in_cmdend:
-		ESPBUS(("end slow cmd "));
-		return esp_do_cmddone(esp, eregs);
-
-	default:
-		printk("esp%d: command in weird state %2x\n",
-		       esp->esp_id, esp->current_SC->SCp.phase);
-		return do_reset_bus;
-	};
+	else
+		return esp_bus_unexpected(esp, eregs);
 }
 
+static espfunc_t isvc_vector[] = {
+	0,
+	esp_do_phase_determine,
+	esp_do_resetbus,
+	esp_finish_reset,
+	esp_work_bus
+};
+
 /* Main interrupt handler for an esp adapter. */
-inline void esp_handle(struct NCR_ESP *esp)
+void esp_handle(struct NCR_ESP *esp)
 {
 	struct ESP_regs *eregs;
 	Scsi_Cmnd *SCptr;
 	int what_next = do_intr_end;
-	unsigned long flags;
-#ifdef CONFIG_SCSI_SUNESP
-	struct sparc_dma_registers *dregs = 
-	  (struct sparc_dma_registers*) esp->dregs;
-#endif
 	eregs = esp->eregs;
 	SCptr = esp->current_SC;
 
@@ -3402,12 +3412,12 @@
 		esp->dma_irq_entry(esp);
 
 	/* Check for errors. */
-	esp->sreg = GETREG(eregs->esp_status);
+	esp->sreg = esp_read(eregs->esp_status);
 	esp->sreg &= (~ESP_STAT_INTR);
-	if(esp->erev == fashme) {
-		esp->sreg2 = GETREG(eregs->esp_status2);
-		esp->seqreg = (GETREG(eregs->esp_sstep) & ESP_STEP_VBITS);
-	}
+	esp->seqreg = (esp_read(eregs->esp_sstep) & ESP_STEP_VBITS);
+	esp->ireg = esp_read(eregs->esp_intrpt);   /* Unlatch intr and stat regs */
+	ESPIRQ(("handle_irq: [sreg<%02x> sstep<%02x> ireg<%02x>]\n",
+		esp->sreg, esp->seqreg, esp->ireg));
 	if(esp->sreg & (ESP_STAT_SPAM)) {
 		/* Gross error, could be due to one of:
 		 *
@@ -3435,56 +3445,10 @@
 			ESPLOG(("esp%d: No current cmd during gross error, "
 				"resetting bus\n", esp->esp_id));
 			what_next = do_reset_bus;
-			goto again;
+			goto state_machine;
 		}
 	}
 
-#ifdef CONFIG_SCSI_SUNESP
-	if(dregs->cond_reg & DMA_HNDL_ERROR) {
-		/* A DMA gate array error.  Here we must
-		 * be seeing one of two things.  Either the
-		 * virtual to physical address translation
-		 * on the SBUS could not occur, else the
-		 * translation it did get pointed to a bogus
-		 * page.  Ho hum...
-		 */
-		ESPLOG(("esp%d: DMA error %08x\n", esp->esp_id,
-			dregs->cond_reg));
-
-		/* DMA gate array itself must be reset to clear the
-		 * error condition.
-		 */
-		if(esp->dma_reset)
-			esp->dma_reset(esp);
-
-		what_next = do_reset_bus;
-		goto again;
-	}
-#endif /* CONFIG_SCSI_SUNESP */
-
-	if(esp->erev == fashme) {
-		/* This chip is really losing. */
-		ESPHME(("HME["));
-
-		ESPHME(("sreg2=%02x,", esp->sreg2));
-		/* Must latch fifo before reading the interrupt
-		 * register else garbage ends up in the FIFO
-		 * which confuses the driver utterly.
-		 */
-		if(!(esp->sreg2 & ESP_STAT2_FEMPTY) ||
-		   (esp->sreg2 & ESP_STAT2_F1BYTE)) {
-			ESPHME(("fifo_workaround]"));
-			hme_fifo_hwbug_workaround(esp, eregs);
-		} else {
-			ESPHME(("no_fifo_workaround]"));
-		}
-	}
-
-	esp->ireg = GETREG(eregs->esp_intrpt);   /* Unlatch intr and stat regs */
-
-	/* This cannot be done until this very moment. -DaveM */
-	synchronize_irq();
-
 	/* No current cmd is only valid at this point when there are
 	 * commands off the bus or we are trying a reset.
 	 */
@@ -3497,7 +3461,7 @@
 	if(esp->ireg & (ESP_INTR_IC)) {
 		/* Illegal command fed to ESP.  Outside of obvious
 		 * software bugs that could cause this, there is
-		 * a condition with esp100 where we can confuse the
+		 * a condition with ESP100 where we can confuse the
 		 * ESP into an erroneous illegal command interrupt
 		 * because it does not scrape the FIFO properly
 		 * for reselection.  See esp100_reconnect_hwbug()
@@ -3523,10 +3487,7 @@
 		}
 
 		what_next = do_reset_bus;
-		goto again;
-	}
-
-	if(!(esp->ireg & ~(ESP_INTR_FDONE | ESP_INTR_BSERV | ESP_INTR_DC))) {
+	} else if(!(esp->ireg & ~(ESP_INTR_FDONE | ESP_INTR_BSERV | ESP_INTR_DC))) {
 		int phase;
 
 		if(SCptr) {
@@ -3538,13 +3499,12 @@
 			} else {
 				ESPLOG(("esp%d: interrupt for no good reason...\n",
 					esp->esp_id));
-				goto esp_handle_done;
+				what_next = do_intr_end;
 			}
 		} else {
 			ESPLOG(("esp%d: BSERV or FDONE or DC while SCptr==NULL\n",
 				esp->esp_id));
 			what_next = do_reset_bus;
-			goto again;
 		}
 	} else if(esp->ireg & ESP_INTR_SR) {
 		ESPLOG(("esp%d: SCSI bus reset interrupt\n", esp->esp_id));
@@ -3553,7 +3513,6 @@
 		ESPLOG(("esp%d: AIEEE we have been selected by another initiator!\n",
 			esp->esp_id));
 		what_next = do_reset_bus;
-		goto again;
 	} else if(esp->ireg & ESP_INTR_RSEL) {
 		if(!SCptr) {
 			/* This is ok. */
@@ -3568,114 +3527,40 @@
 			ESPLOG(("esp%d: Reselected while bus is busy\n",
 				esp->esp_id));
 			what_next = do_reset_bus;
-			goto again;
 		}
 	}
 
-	/* We're trying to fight stack problems, and inline as much as
-	 * possible without making this driver a mess. hate hate hate
-	 * This is tier-one in our dual level SCSI state machine.
-	 */
-again:
-	switch(what_next) {
-	case do_intr_end:
-		goto esp_handle_done;
-
-	case do_work_bus:
-		what_next = esp_work_bus(esp, eregs);
-		break;
-
-	case do_phase_determine:
-		what_next = esp_do_phase_determine(esp, eregs);
-		break;
-
-	case do_reset_bus:
-		ESPLOG(("esp%d: resetting bus...\n", esp->esp_id));
-		esp->resetting_bus = 1;
-		esp_cmd(esp, eregs, ESP_CMD_RS);
-		goto esp_handle_done;
-
-	case do_reset_complete:
-		/* Tricky, we don't want to cause any more commands to
-		 * go out until we clear all the live cmds by hand.
-		 */
-		if(esp->current_SC) {
-			Scsi_Cmnd *SCptr = esp->current_SC;
-
-			if(!SCptr->use_sg) {
-			        if (esp->dma_mmu_release_scsi_one)
-			                esp->dma_mmu_release_scsi_one (esp, SCptr);
-			} else {
-			        if (esp->dma_mmu_release_scsi_sgl)
-			                esp->dma_mmu_release_scsi_sgl (esp, SCptr);
-			}
-			SCptr->result = (DID_RESET << 16);
-
-			spin_lock_irqsave(&io_request_lock,flags);
-			SCptr->scsi_done(SCptr);
-			spin_unlock_irqrestore(&io_request_lock, flags);
-		}
-		esp->current_SC = NULL;
-		if(esp->disconnected_SC) {
-			Scsi_Cmnd *SCptr;
-			while((SCptr = remove_first_SC(&esp->disconnected_SC))) {
-				if(!SCptr->use_sg) {
-			                if (esp->dma_mmu_release_scsi_one)
-			                        esp->dma_mmu_release_scsi_one (esp, SCptr);
-				} else {
-			                if (esp->dma_mmu_release_scsi_sgl)
-			                        esp->dma_mmu_release_scsi_sgl (esp, SCptr);
-				}
-				SCptr->result = (DID_RESET << 16);
-
-				spin_lock_irqsave(&io_request_lock,flags);
-				SCptr->scsi_done(SCptr);
-				spin_unlock_irqrestore(&io_request_lock, flags);
-			}
-		}
-		esp->resetting_bus = 0;
-
-		if(esp->current_SC) {
-			printk("esp%d: weird weird weird, current_SC not NULL after "
-			       "SCSI bus reset.\n", esp->esp_id);
-			goto esp_handle_done;
+	/* This is tier-one in our dual level SCSI state machine. */
+state_machine:
+	while(what_next != do_intr_end) {
+		if (what_next >= do_phase_determine &&
+		    what_next < do_intr_end)
+			what_next = isvc_vector[what_next](esp, eregs);
+		else {
+			/* state is completely lost ;-( */
+			ESPLOG(("esp%d: interrupt engine loses state, resetting bus\n",
+				esp->esp_id));
+			what_next = do_reset_bus;
 		}
-
-		/* Now it is safe to execute more things. */
-		if(esp->issue_SC)
-			esp_exec_cmd(esp);
-		goto esp_handle_done;
-
-	default:
-		/* state is completely lost ;-( */
-		ESPLOG(("esp%d: interrupt engine loses state, resetting bus\n",
-			esp->esp_id));
-		what_next = do_reset_bus;
-		break;
-
-	};
-	goto again;
-
-esp_handle_done:
+	}
 	if(esp->dma_irq_exit)
 		esp->dma_irq_exit(esp);
-	return;
 }
 
-#ifndef __sparc_v9__
-
 #ifndef __SMP__
 void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
 {
 	struct NCR_ESP *esp;
+	unsigned long flags;
 	int again;
 
 	/* Handle all ESP interrupts showing at this IRQ level. */
+	spin_lock_irqsave(&io_request_lock, flags);
 repeat:
 	again = 0;
 	for_each_esp(esp) {
 #ifndef __mips__	    
-		if(((esp)->irq & 0xf) == irq) {
+		if(((esp)->irq & 0xff) == irq) {
 #endif		    
 			if(esp->dma_irq_p(esp)) {
 				again = 1;
@@ -3694,14 +3579,17 @@
 	}
 	if(again)
 		goto repeat;
+	spin_unlock_irqrestore(&io_request_lock, flags);
 }
 #else
 /* For SMP we only service one ESP on the list list at our IRQ level! */
-void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
+static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
 {
 	struct NCR_ESP *esp;
+	unsigned long flags;
 
 	/* Handle all ESP interrupts showing at this IRQ level. */
+	spin_lock_irqsave(&io_request_lock, flags);
 	for_each_esp(esp) {
 		if(((esp)->irq & 0xf) == irq) {
 			if(esp->dma_irq_p(esp)) {
@@ -3713,28 +3601,22 @@
 				ESPIRQ((")"));
 
 				esp->dma_ints_on(esp);
-				return;
+				goto out;
 			}
 		}
 	}
+out:
+	spin_unlock_irqrestore(&io_request_lock, flags);
 }
 #endif
 
-#else /* __sparc_v9__ */
-
-static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
+#ifdef MODULE
+int init_module(void) { return 0; }
+void cleanup_module(void) {}
+void esp_release(void)
 {
-	struct NCR_ESP *esp = dev_id;
-
-	if(esp->dma_irq_p(esp)) {
-		esp->dma_ints_off(dregs);
-
-		ESPIRQ(("I[%d:%d](", smp_processor_id(), esp->esp_id));
-		esp_handle(esp);
-		ESPIRQ((")"));
-
-		esp->dma_ints_on(esp);
-	}
+	MOD_DEC_USE_COUNT;
+	esps_in_use--;
+	esps_running = esps_in_use;
 }
-
 #endif
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/NCR53C9x.h linux/drivers/scsi/NCR53C9x.h
--- v2.3.13/linux/drivers/scsi/NCR53C9x.h	Tue Jun 22 14:42:32 1999
+++ linux/drivers/scsi/NCR53C9x.h	Thu Aug 12 10:28:34 1999
@@ -1,4 +1,4 @@
-/* NCR53C9x.h:  Defines and structures for the NCR53C9x generic driver.
+/* NCR53C9x.c:  Defines and structures for the NCR53C9x generic driver.
  *
  * Originaly esp.h:  Defines and structures for the Sparc ESP 
  *                   (Enhanced SCSI Processor) driver under Linux.
@@ -15,10 +15,32 @@
 
 #include <linux/config.h>
 
+/* djweis for mac driver */
+#if defined(CONFIG_MAC)
+#define PAD_SIZE 15
+#else
+#define PAD_SIZE 3
+#endif
+
+/* Handle multiple hostadapters on Amiga
+ * generally PAD_SIZE = 3
+ * but there is one exception: Oktagon (PAD_SIZE = 1) */
+#if defined(CONFIG_OKTAGON_SCSI) || defined(CONFIG_OKTAGON_SCSI_MODULE)
+#undef PAD_SIZE
+#if defined(CONFIG_BLZ1230_SCSI) || defined(CONFIG_BLZ1230_SCSI_MODULE) || \
+    defined(CONFIG_BLZ2060_SCSI) || defined(CONFIG_BLZ2060_SCSI_MODULE) || \
+    defined(CONFIG_CYBERSTORM_SCSI) || defined(CONFIG_CYBERSTORM_SCSI_MODULE) || \
+    defined(CONFIG_CYBERSTORMII_SCSI) || defined(CONFIG_CYBERSTORMII_SCSI_MODULE) || \
+    defined(CONFIG_FASTLANE_SCSI) || defined(CONFIG_FASTLANE_SCSI_MODULE)
+#define MULTIPLE_PAD_SIZES
+#else
+#define PAD_SIZE 1
+#endif
+#endif
+
 /* Macros for debugging messages */
 
-/* #define DEBUG_ESP */
-/* #define DEBUG_ESP_HME */
+#define DEBUG_ESP
 /* #define DEBUG_ESP_DATA */
 /* #define DEBUG_ESP_QUEUE */
 /* #define DEBUG_ESP_DISCONNECT */
@@ -43,12 +65,6 @@
 #define ESPLOG(foo)
 #endif /* (DEBUG_ESP) */
 
-#if defined(DEBUG_ESP_HME)
-#define ESPHME(foo)  printk foo
-#else
-#define ESPHME(foo)
-#endif
-
 #if defined(DEBUG_ESP_DATA)
 #define ESPDATA(foo)  printk foo
 #else
@@ -103,21 +119,15 @@
 #define ESPMISC(foo)
 #endif
 
-#define INTERNAL_ESP_ERROR \
-        (panic ("Internal ESP driver error in file %s, line %d\n", \
-		__FILE__, __LINE__))
-
-#define INTERNAL_ESP_ERROR_NOPANIC \
-        (printk ("Internal ESP driver error in file %s, line %d\n", \
-		 __FILE__, __LINE__))
-
 /*
  * padding for register structure
  */
 #ifdef CONFIG_JAZZ_ESP
 #define EREGS_PAD(n)
 #else
-#define EREGS_PAD(n)    unchar n[3];
+#ifndef MULTIPLE_PAD_SIZES
+#define EREGS_PAD(n)    unchar n[PAD_SIZE];
+#endif
 #endif
 
 /* The ESP SCSI controllers have their register sets in three
@@ -130,18 +140,12 @@
  * Yet, they all live within the same IO space.
  */
 
-/* All the ESP registers are one byte each and are accessed longwords
- * apart with a big-endian ordering to the bytes.
- */
- 
-/*
- * On intel, we must use inb() and outb() for register access, and the registers
- *  are consecutive; no padding.
- */ 
-
 #ifndef __i386__
-#define SETREG(reg, val) (reg = val)
-#define GETREG(reg)      (reg)
+
+#ifndef MULTIPLE_PAD_SIZES
+
+#define esp_write(__reg, __val) ((__reg) = (__val))
+#define esp_read(__reg) (__reg)
 
 struct ESP_regs {
                                 /* Access    Description              Offset */
@@ -151,7 +155,7 @@
                                 EREGS_PAD(fdpad);
     volatile unchar esp_fdata;  /* rw  FIFO data bits                 0x08   */
                                 EREGS_PAD(cbpad);
-    volatile unchar esp_cmnd;    /* rw  SCSI command bits              0x0c   */
+    volatile unchar esp_cmnd;   /* rw  SCSI command bits              0x0c   */
                                 EREGS_PAD(stpad);
     volatile unchar esp_status; /* ro  ESP status register            0x10   */
 #define esp_busid   esp_status  /* wo  Bus ID for select/reselect     0x10   */
@@ -168,7 +172,6 @@
     volatile unchar esp_cfg1;   /* rw  First configuration register   0x20   */
                                 EREGS_PAD(cfpad);
     volatile unchar esp_cfact;  /* wo  Clock conversion factor        0x24   */
-#define esp_status2 esp_cfact   /* ro  HME status2 register           0x24   */
                                 EREGS_PAD(ctpad);
     volatile unchar esp_ctest;  /* wo  Chip test register             0x28   */
                                 EREGS_PAD(cf2pd);
@@ -177,63 +180,89 @@
 
     /* The following is only found on the 53C9X series SCSI chips */
     volatile unchar esp_cfg3;   /* rw  Third configuration register   0x30  */
-                                EREGS_PAD(holep);
-    volatile unchar esp_hole;   /* hole in register map               0x34  */
-                                EREGS_PAD(thpd);    
+                                EREGS_PAD(cf4pd);
+    volatile unchar esp_cfg4;   /* rw  Fourth configuration register  0x34  */
+                                EREGS_PAD(thpd);
     /* The following is found on all chips except the NCR53C90 (ESP100) */
     volatile unchar esp_tchi;   /* rw  High bits of transfer count    0x38  */
 #define esp_uid     esp_tchi    /* ro  Unique ID code                 0x38  */
-#define fas_rlo     esp_tchi    /* rw  HME extended counter           0x38  */
                                 EREGS_PAD(fgpad);    
     volatile unchar esp_fgrnd;  /* rw  Data base for fifo             0x3c  */
-#define fas_rhi     esp_fgrnd   /* rw  HME extended counter           0x3c  */
 };
 
-#else
-#define SETREG(reg, val) outb(val, reg)
-#define GETREG(reg)      inb(reg)
+#else /* MULTIPLE_PAD_SIZES */
+
+#define esp_write(__reg, __val) (*(__reg) = (__val))
+#define esp_read(__reg) (*(__reg))
 
 struct ESP_regs {
-#ifdef CONFIG_MCA
-    unsigned int slot;
+    unsigned char io_addr[64]; /* dummy */
+                                                 /* Access    Description              Offset */
+#define esp_tclow   io_addr                      /* rw  Low bits of the transfer count 0x00   */
+#define esp_tcmed   io_addr + (1<<(esp->shift))  /* rw  Mid bits of the transfer count 0x04   */
+#define esp_fdata   io_addr + (2<<(esp->shift))  /* rw  FIFO data bits                 0x08   */
+#define esp_cmnd    io_addr + (3<<(esp->shift))  /* rw  SCSI command bits              0x0c   */
+#define esp_status  io_addr + (4<<(esp->shift))  /* ro  ESP status register            0x10   */
+#define esp_busid   esp_status                   /* wo  Bus ID for select/reselect     0x10   */
+#define esp_intrpt  io_addr + (5<<(esp->shift))  /* ro  Kind of interrupt              0x14   */
+#define esp_timeo   esp_intrpt                   /* wo  Timeout value for select/resel 0x14   */
+#define esp_sstep   io_addr + (6<<(esp->shift))  /* ro  Sequence step register         0x18   */
+#define esp_stp     esp_sstep                    /* wo  Transfer period per sync       0x18   */
+#define esp_fflags  io_addr + (7<<(esp->shift))  /* ro  Bits of current FIFO info      0x1c   */
+#define esp_soff    esp_fflags                   /* wo  Sync offset                    0x1c   */
+#define esp_cfg1    io_addr + (8<<(esp->shift))  /* rw  First configuration register   0x20   */
+#define esp_cfact   io_addr + (9<<(esp->shift))  /* wo  Clock conversion factor        0x24   */
+#define esp_ctest   io_addr + (10<<(esp->shift)) /* wo  Chip test register             0x28   */
+#define esp_cfg2    io_addr + (11<<(esp->shift)) /* rw  Second configuration register  0x2c   */
+
+    /* The following is only found on the 53C9X series SCSI chips */
+#define esp_cfg3    io_addr + (12<<(esp->shift)) /* rw  Third configuration register   0x30  */
+#define esp_cfg4    io_addr + (13<<(esp->shift)) /* rw  Fourth configuration register  0x34  */
+
+    /* The following is found on all chips except the NCR53C90 (ESP100) */
+#define esp_tchi    io_addr + (14<<(esp->shift)) /* rw  High bits of transfer count    0x38  */
+#define esp_uid     esp_tchi                     /* ro  Unique ID code                 0x38  */
+#define esp_fgrnd   io_addr + (15<<(esp->shift)) /* rw  Data base for fifo             0x3c  */
+};
+
 #endif
+
+#else /* !defined __i386__ */
+
+#define esp_write(__reg, __val) outb((__val), (__reg))
+#define esp_read(__reg) inb((__reg))
+
+struct ESP_regs {
     unsigned int io_addr;
-                                  /* Access    Description              Offset */
+                                 /* Access    Description              Offset */
 #define esp_tclow   io_addr      /* rw  Low bits of the transfer count 0x00   */
 #define esp_tcmed   io_addr + 1  /* rw  Mid bits of the transfer count 0x04   */
 #define esp_fdata   io_addr + 2  /* rw  FIFO data bits                 0x08   */
-#define esp_cmnd     io_addr + 3  /* rw  SCSI command bits              0x0c   */
+#define esp_cmnd    io_addr + 3  /* rw  SCSI command bits              0x0c   */
 #define esp_status  io_addr + 4  /* ro  ESP status register            0x10   */
-#define esp_busid    esp_status   /* wo  Bus ID for select/reselect     0x10   */
+#define esp_busid   esp_status   /* wo  Bus ID for select/reselect     0x10   */
 #define esp_intrpt  io_addr + 5  /* ro  Kind of interrupt              0x14   */
-#define esp_timeo    esp_intrpt   /* wo  Timeout value for select/resel 0x14   */
+#define esp_timeo   esp_intrpt   /* wo  Timeout value for select/resel 0x14   */
 #define esp_sstep   io_addr + 6  /* ro  Sequence step register         0x18   */
-#define esp_stp      esp_sstep    /* wo  Transfer period per sync       0x18   */
+#define esp_stp     esp_sstep    /* wo  Transfer period per sync       0x18   */
 #define esp_fflags  io_addr + 7  /* ro  Bits of current FIFO info      0x1c   */
-#define esp_soff     esp_fflags   /* wo  Sync offset                    0x1c   */
+#define esp_soff    esp_fflags   /* wo  Sync offset                    0x1c   */
 #define esp_cfg1    io_addr + 8  /* rw  First configuration register   0x20   */
 #define esp_cfact   io_addr + 9  /* wo  Clock conversion factor        0x24   */
-#define esp_status2  esp_cfact    /* ro  HME status2 register           0x24   */
 #define esp_ctest   io_addr + 10 /* wo  Chip test register             0x28   */
 #define esp_cfg2    io_addr + 11 /* rw  Second configuration register  0x2c   */
 
     /* The following is only found on the 53C9X series SCSI chips */
 #define esp_cfg3    io_addr + 12 /* rw  Third configuration register   0x30  */
-#define esp_hole    io_addr + 13 /* hole in register map               0x34  */
+#define esp_cfg4    io_addr + 13 /* rw  Fourth configuration register  0x34  */
 
     /* The following is found on all chips except the NCR53C90 (ESP100) */
 #define esp_tchi    io_addr + 14 /* rw  High bits of transfer count    0x38  */
-#define esp_uid      esp_tchi     /* ro  Unique ID code                 0x38  */
-#define fas_rlo      esp_tchi     /* rw  HME extended counter           0x38  */
+#define esp_uid     esp_tchi     /* ro  Unique ID code                 0x38  */
 #define esp_fgrnd   io_addr + 15 /* rw  Data base for fifo             0x3c  */
-#define fas_rhi      esp_fgrnd    /* rw  HME extended counter           0x3c  */
 };
 
-#ifndef save_and_cli
-#define save_and_cli(flags)  save_flags(flags); cli();
-#endif
-
-#endif
+#endif /* !defined(__i386__) */
 
 /* Various revisions of the ESP board. */
 enum esp_rev {
@@ -243,26 +272,21 @@
   fas236     = 0x03,
   fas100a    = 0x04,
   fast       = 0x05,
-  fashme     = 0x06,
-  fas216     = 0x07,    
-  espunknown = 0x08
+  fas366     = 0x06,
+  fas216     = 0x07,
+  fsc        = 0x08,  /* SYM53C94-2 */
+  espunknown = 0x09
 };
 
 /* We get one of these for each ESP probed. */
 struct NCR_ESP {
   struct NCR_ESP *next;                   /* Next ESP on probed or NULL */
   struct ESP_regs *eregs;	          /* All esp registers */
-#ifndef __i386__
-  struct Linux_DMA *dma;                  /* Who I do transfers with. */
-#else
-  int dma;
-#endif
+  int dma;                                /* Who I do transfers with. */
   void *dregs;		  		  /* And his registers. */
   struct Scsi_Host *ehost;                /* Backpointer to SCSI Host */
 
   void *edev;        		          /* Pointer to controller base/SBus */
-  char prom_name[64];                     /* Name of ESP device from prom */
-  int prom_node;                          /* Prom node where ESP found */
   int esp_id;                             /* Unique per-ESP ID number */
 
   /* ESP Configuration Registers */
@@ -292,11 +316,29 @@
   unchar ireg;                            /* Copy of ESP interrupt register */
   unchar sreg;                            /* Same for ESP status register */
   unchar seqreg;                          /* The ESP sequence register */
-  unchar sreg2;                           /* Copy of HME status2 register */
 
-  /* The HME is the biggest piece of shit I have ever seen. */
-  unchar hme_fifo_workaround_buffer[16 * 2]; /* 16-bit/entry fifo for wide scsi */
-  unchar hme_fifo_workaround_count;
+  /* The following is set when a premature interrupt condition is detected
+   * in some FAS revisions.
+   */
+  unchar fas_premature_intr_workaround;
+
+  /* To save register writes to the ESP, which can be expensive, we
+   * keep track of the previous value that various registers had for
+   * the last target we connected to.  If they are the same for the
+   * current target, we skip the register writes as they are not needed.
+   */
+  unchar prev_soff, prev_stp, prev_cfg3;
+
+  /* For each target we keep track of save/restore data
+   * pointer information.  This needs to be updated majorly
+   * when we add support for tagged queueing.  -DaveM
+   */
+  struct esp_pointers {
+	  char *saved_ptr;
+	  struct scatterlist *saved_buffer;
+	  int saved_this_residual;
+	  int saved_buffers_residual;
+  } data_pointers[16] /*XXX [MAX_TAGS_PER_TARGET]*/;
 
   /* Clock periods, frequencies, synchronization, etc. */
   unsigned int cfreq;                    /* Clock frequency in HZ */
@@ -308,7 +350,6 @@
   unsigned int sync_defp;                /* Default sync transfer period */
   unsigned int max_period;               /* longest our period can be */
   unsigned int min_period;               /* shortest period we can withstand */
-  unsigned char ccf;			 /* Clock conversion factor */
   /* For slow to medium speed input clock rates we shoot for 5mb/s,
    * but for high input clock rates we try to do 10mb/s although I
    * don't think a transfer can even run that fast with an ESP even
@@ -328,15 +369,11 @@
 
   /* Misc. info about this ESP */
   enum esp_rev erev;                      /* ESP revision */
-  int irq;                                /* SBus IRQ for this ESP */
+  int irq;                                /* IRQ for this ESP */
   int scsi_id;                            /* Who am I as initiator? */
   int scsi_id_mask;                       /* Bitmask of 'me'. */
   int diff;                               /* Differential SCSI bus? */
-  int bursts;                             /* Burst sizes our DVMA supports */
-
-#ifdef CONFIG_MCA
-  int slot;				  /* MCA slot the adapter occupies */
-#endif
+  int slot;                               /* Slot the adapter occupies */
 
   /* Our command queues, only one cmd lives in the current_SC queue. */
   Scsi_Cmnd *issue_SC;           /* Commands to be issued */
@@ -357,6 +394,9 @@
 
   unchar do_pio_cmds;		/* Do command transfer with pio */
 
+  /* How much bits do we have to shift the registers */
+  unsigned char shift;
+
   /* Functions handling DMA
    */ 
   /* Required functions */
@@ -400,38 +440,38 @@
 #define ESP_CONFIG1_SRRDISAB  0x40             /* Disable SCSI reset reports */
 #define ESP_CONFIG1_SLCABLE   0x80             /* Enable slow cable mode */
 
-/* ESP config reg 2, read-write, found only on esp100a+esp200+esp236 chips */
-#define ESP_CONFIG2_DMAPARITY 0x01             /* enable DMA Parity (200,236) */
-#define ESP_CONFIG2_REGPARITY 0x02             /* enable reg Parity (200,236) */
+/* ESP config reg 2, read-write, found only on esp100a+esp200+esp236+fsc chips */
+#define ESP_CONFIG2_DMAPARITY 0x01             /* enable DMA Parity (200,236,fsc) */
+#define ESP_CONFIG2_REGPARITY 0x02             /* enable reg Parity (200,236,fsc) */
 #define ESP_CONFIG2_BADPARITY 0x04             /* Bad parity target abort  */
 #define ESP_CONFIG2_SCSI2ENAB 0x08             /* Enable SCSI-2 features (tmode only) */
 #define ESP_CONFIG2_HI        0x10             /* High Impedance DREQ ???  */
 #define ESP_CONFIG2_HMEFENAB  0x10             /* HME features enable */
-#define ESP_CONFIG2_BCM       0x20             /* Enable byte-ctrl (236)   */
-#define ESP_CONFIG2_DISPINT   0x20             /* Disable pause irq (hme) */
-#define ESP_CONFIG2_FENAB     0x40             /* Enable features (fas100,esp216)      */
+#define ESP_CONFIG2_BCM       0x20             /* Enable byte-ctrl (236,fsc)   */
+#define ESP_CONFIG2_FENAB     0x40             /* Enable features (fas100,esp216,fsc)      */
 #define ESP_CONFIG2_SPL       0x40             /* Enable status-phase latch (esp236)   */
-#define ESP_CONFIG2_MKDONE    0x40             /* HME magic feature */
-#define ESP_CONFIG2_HME32     0x80             /* HME 32 extended */
+#define ESP_CONFIG2_RFB       0x80             /* Reserve FIFO byte (fsc) */
 #define ESP_CONFIG2_MAGIC     0xe0             /* Invalid bits... */
 
-/* ESP config register 3 read-write, found only esp236+fas236+fas100a+hme chips */
-#define ESP_CONFIG3_FCLOCK    0x01             /* FAST SCSI clock rate (esp100a/hme) */
-#define ESP_CONFIG3_TEM       0x01             /* Enable thresh-8 mode (esp/fas236)  */
-#define ESP_CONFIG3_FAST      0x02             /* Enable FAST SCSI     (esp100a/hme) */
-#define ESP_CONFIG3_ADMA      0x02             /* Enable alternate-dma (esp/fas236)  */
-#define ESP_CONFIG3_TENB      0x04             /* group2 SCSI2 support (esp100a/hme) */
-#define ESP_CONFIG3_SRB       0x04             /* Save residual byte   (esp/fas236)  */
-#define ESP_CONFIG3_TMS       0x08             /* Three-byte msg's ok  (esp100a/hme) */
-#define ESP_CONFIG3_FCLK      0x08             /* Fast SCSI clock rate (esp/fas236)  */
-#define ESP_CONFIG3_IDMSG     0x10             /* ID message checking  (esp100a/hme) */
-#define ESP_CONFIG3_FSCSI     0x10             /* Enable FAST SCSI     (esp/fas236)  */
-#define ESP_CONFIG3_GTM       0x20             /* group2 SCSI2 support (esp/fas236)  */
-#define ESP_CONFIG3_BIGID     0x20             /* SCSI-ID's are 4bits  (hme)         */
-#define ESP_CONFIG3_TBMS      0x40             /* Three-byte msg's ok  (esp/fas236)  */
-#define ESP_CONFIG3_EWIDE     0x40             /* Enable Wide-SCSI     (hme)         */
-#define ESP_CONFIG3_IMS       0x80             /* ID msg chk'ng        (esp/fas236)  */
-#define ESP_CONFIG3_OBPUSH    0x80             /* Push odd-byte to dma (hme)         */
+/* ESP config register 3 read-write, found only esp236+fas236+fas100a+fsc chips */
+#define ESP_CONFIG3_FCLOCK    0x01             /* FAST SCSI clock rate (esp100a/fas366) */
+#define ESP_CONFIG3_TEM       0x01             /* Enable thresh-8 mode (esp/fas236/fsc)  */
+#define ESP_CONFIG3_FAST      0x02             /* Enable FAST SCSI     (esp100a) */
+#define ESP_CONFIG3_ADMA      0x02             /* Enable alternate-dma (esp/fas236/fsc)  */
+#define ESP_CONFIG3_TENB      0x04             /* group2 SCSI2 support (esp100a) */
+#define ESP_CONFIG3_SRB       0x04             /* Save residual byte   (esp/fas236/fsc)  */
+#define ESP_CONFIG3_TMS       0x08             /* Three-byte msg's ok  (esp100a) */
+#define ESP_CONFIG3_FCLK      0x08             /* Fast SCSI clock rate (esp/fas236/fsc)  */
+#define ESP_CONFIG3_IDMSG     0x10             /* ID message checking  (esp100a) */
+#define ESP_CONFIG3_FSCSI     0x10             /* Enable FAST SCSI     (esp/fas236/fsc)  */
+#define ESP_CONFIG3_GTM       0x20             /* group2 SCSI2 support (esp/fas236/fsc)  */
+#define ESP_CONFIG3_TBMS      0x40             /* Three-byte msg's ok  (esp/fas236/fsc)  */
+#define ESP_CONFIG3_IMS       0x80             /* ID msg chk'ng        (esp/fas236/fsc)  */
+
+/* ESP config register 4 read-write, found only on fsc chips */
+#define ESP_CONFIG4_BBTE      0x01             /* Back-to-Back transfer enable */
+#define ESP_CONFIG4_TEST      0x02             /* Transfer counter test mode */
+#define ESP_CONFIG4_EAN       0x04             /* Enable Active Negotiation */
 
 /* ESP command register read-write */
 /* Group 1 commands:  These may be sent at any point in time to the ESP
@@ -482,10 +522,9 @@
 #define ESP_CMD_SA3           0x46             /* Select w/ATN3 */
 #define ESP_CMD_RSEL3         0x47             /* Reselect3 */
 
-/* This bit enables the ESP's DMA on the SBus */
+/* This bit enables the ESP's DMA */
 #define ESP_CMD_DMA           0x80             /* Do DMA? */
 
-
 /* ESP status register read-only */
 #define ESP_STAT_PIO          0x01             /* IO phase bit */
 #define ESP_STAT_PCD          0x02             /* CD phase bit */
@@ -495,21 +534,11 @@
 #define ESP_STAT_TCNT         0x10             /* Transfer Counter Is Zero */
 #define ESP_STAT_PERR         0x20             /* Parity error */
 #define ESP_STAT_SPAM         0x40             /* Real bad error */
-/* This indicates the 'interrupt pending' condition on esp236, it is a reserved
- * bit on other revs of the ESP.
+/* This indicates the 'interrupt pending' condition, it is a reserved
+ * bit on old revs of the ESP (ESP100, ESP100A, FAS100A).
  */
 #define ESP_STAT_INTR         0x80             /* Interrupt */
 
-/* HME only: status 2 register */
-#define ESP_STAT2_SCHBIT      0x01 /* Upper bits 3-7 of sstep enabled */
-#define ESP_STAT2_FFLAGS      0x02 /* The fifo flags are now latched */
-#define ESP_STAT2_XCNT        0x04 /* The transfer counter is latched */
-#define ESP_STAT2_CREGA       0x08 /* The command reg is active now */
-#define ESP_STAT2_WIDE        0x10 /* Interface on this adapter is wide */
-#define ESP_STAT2_F1BYTE      0x20 /* There is one byte at top of fifo */
-#define ESP_STAT2_FMSB        0x40 /* Next byte in fifo is most significant */
-#define ESP_STAT2_FEMPTY      0x80 /* FIFO is empty */
-
 /* The status register can be masked with ESP_STAT_PMASK and compared
  * with the following values to determine the current phase the ESP
  * (at least thinks it) is in.  For our purposes we also add our own
@@ -555,22 +584,24 @@
 #define ESP_STEP_FINI5        0x05
 #define ESP_STEP_FINI6        0x06
 #define ESP_STEP_FINI7        0x07
+#define ESP_STEP_SOM          0x08             /* Synchronous Offset Max */
 
 /* ESP chip-test register read-write */
 #define ESP_TEST_TARG         0x01             /* Target test mode */
 #define ESP_TEST_INI          0x02             /* Initiator test mode */
 #define ESP_TEST_TS           0x04             /* Tristate test mode */
 
-/* ESP unique ID register read-only, found on fas236+fas100a only */
-#define ESP_UID_F100A         0x00             /* ESP FAS100A  */
-#define ESP_UID_F236          0x02             /* ESP FAS236   */
+/* ESP unique ID register read-only, found on fas236+fas100a+fsc only */
+#define ESP_UID_F100A         0x00             /* FAS100A  */
+#define ESP_UID_F236          0x02             /* FAS236   */
+#define ESP_UID_FSC           0xa2             /* NCR53CF9x-2  */
 #define ESP_UID_REV           0x07             /* ESP revision */
 #define ESP_UID_FAM           0xf8             /* ESP family   */
 
 /* ESP fifo flags register read-only */
 /* Note that the following implies a 16 byte FIFO on the ESP. */
 #define ESP_FF_FBYTES         0x1f             /* Num bytes in FIFO */
-#define ESP_FF_ONOTZERO       0x20             /* offset ctr not zero (esp100) */
+#define ESP_FF_ONOTZERO       0x20             /* offset ctr not zero (esp100,fsc) */
 #define ESP_FF_SSTEP          0xe0             /* Sequence step */
 
 /* ESP clock conversion factor register write-only */
@@ -583,14 +614,13 @@
 #define ESP_CCF_F6            0x06             /* 25.01MHz - 30MHz */
 #define ESP_CCF_F7            0x07             /* 30.01MHz - 35MHz */
 
-/* HME only... */
-#define ESP_BUSID_RESELID     0x10
-#define ESP_BUSID_CTR32BIT    0x40
-
 #define ESP_BUS_TIMEOUT        275             /* In milli-seconds */
 #define ESP_TIMEO_CONST       8192
+#define FSC_TIMEO_CONST       7668
 #define ESP_NEG_DEFP(mhz, cfact) \
         ((ESP_BUS_TIMEOUT * ((mhz) / 1000)) / (8192 * (cfact)))
+#define FSC_NEG_DEFP(mhz, cfact) \
+        ((ESP_BUS_TIMEOUT * ((mhz) / 1000)) / (7668 * (cfact)))
 #define ESP_MHZ_TO_CYCLE(mhertz)  ((1000000000) / ((mhertz) / 1000))
 #define ESP_TICK(ccf, cycle)  ((7682 * (ccf) * (cycle) / 1000))
 
@@ -609,6 +639,8 @@
 extern inline void esp_cmd(struct NCR_ESP *esp, struct ESP_regs *eregs,
 			   unchar cmd);
 extern struct NCR_ESP *esp_allocate(Scsi_Host_Template *, void *);
+extern void esp_deallocate(struct NCR_ESP *);
+extern void esp_release(void);
 extern void esp_initialize(struct NCR_ESP *);
 extern void esp_intr(int, void *, struct pt_regs *);
 #endif /* !(NCR53C9X_H) */
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/a2091.c linux/drivers/scsi/a2091.c
--- v2.3.13/linux/drivers/scsi/a2091.c	Sat Apr 11 11:13:25 1998
+++ linux/drivers/scsi/a2091.c	Wed Aug 18 10:00:52 1999
@@ -34,6 +34,7 @@
 
 static void a2091_intr (int irq, void *dummy, struct pt_regs *fp)
 {
+    unsigned long flags;
     unsigned int status;
     struct Scsi_Host *instance;
     for (instance = first_instance; instance &&
@@ -41,32 +42,20 @@
     {
 	status = DMA(instance)->ISTR;
 	if (!(status & (ISTR_INT_F|ISTR_INT_P)))
-	    continue;
+		continue;
 
-	if (status & ISTR_INTS)
-	{
-	    /* disable PORTS interrupt */
-	    custom.intena = IF_PORTS;
-	    wd33c93_intr (instance);
-	    /* enable PORTS interrupt */
-	    custom.intena = IF_SETCLR | IF_PORTS;
+	if (status & ISTR_INTS) {
+		spin_lock_irqsave(&io_request_lock, flags);
+		wd33c93_intr (instance);
+		spin_unlock_irqrestore(&io_request_lock, flags);
 	}
     }
 }
 
-static void do_a2091_intr (int irq, void *dummy, struct pt_regs *fp)
-{
-    unsigned long flags;
-
-    spin_lock_irqsave(&io_request_lock, flags);
-    a2091_intr(irq, dummy, fp);
-    spin_unlock_irqrestore(&io_request_lock, flags);
-}
-
 static int dma_setup (Scsi_Cmnd *cmd, int dir_in)
 {
     unsigned short cntr = CNTR_PDMD | CNTR_INTEN;
-    unsigned long addr = VTOP(cmd->SCp.ptr);
+    unsigned long addr = virt_to_bus(cmd->SCp.ptr);
     struct Scsi_Host *instance = cmd->host;
 
     /* don't allow DMA if the physical address is bad */
@@ -85,7 +74,7 @@
 	}
 
 	/* get the physical address of the bounce buffer */
-	addr = VTOP(HDATA(instance)->dma_bounce_buffer);
+	addr = virt_to_bus(HDATA(instance)->dma_bounce_buffer);
 
 	/* the bounce buffer may not be in the first 16M of physmem */
 	if (addr & A2091_XFER_MASK) {
@@ -200,7 +189,7 @@
 
 static int num_a2091 = 0;
 
-__initfunc(int a2091_detect(Scsi_Host_Template *tpnt))
+int __init a2091_detect(Scsi_Host_Template *tpnt)
 {
     static unsigned char called = 0;
     struct Scsi_Host *instance;
@@ -229,7 +218,8 @@
 	if (num_a2091++ == 0) {
 	    first_instance = instance;
 	    a2091_template = instance->hostt;
-	    request_irq(IRQ_AMIGA_PORTS, do_a2091_intr, 0, "A2091 SCSI", a2091_intr);
+	    request_irq(IRQ_AMIGA_PORTS, a2091_intr, SA_SHORQ, "A2091 SCSI",
+			a2091_intr);
 	}
 	DMA(instance)->CNTR = CNTR_PDMD | CNTR_INTEN;
 	zorro_config_board(key, 0);
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/a3000.c linux/drivers/scsi/a3000.c
--- v2.3.13/linux/drivers/scsi/a3000.c	Sat Apr 11 11:13:25 1998
+++ linux/drivers/scsi/a3000.c	Wed Aug 18 10:00:52 1999
@@ -32,34 +32,25 @@
 
 static void a3000_intr (int irq, void *dummy, struct pt_regs *fp)
 {
-    unsigned int status = DMA(a3000_host)->ISTR;
+	unsigned long flags;
+	unsigned int status = DMA(a3000_host)->ISTR;
 
-    if (!(status & ISTR_INT_P))
-	return;
-    if (status & ISTR_INTS)
-    {
-	/* disable PORTS interrupt */
-	custom.intena = IF_PORTS;
-	wd33c93_intr (a3000_host);
-	/* enable PORTS interrupt */
-	custom.intena = IF_SETCLR | IF_PORTS;
-    } else {
-      printk("Non-serviced A3000 SCSI-interrupt? ISTR = %02x\n", status);
-    }
+	if (!(status & ISTR_INT_P))
+		return;
+	if (status & ISTR_INTS)
+	{
+		spin_lock_irqsave(&io_request_lock, flags);
+		wd33c93_intr (a3000_host);
+		spin_unlock_irqrestore(&io_request_lock, flags);
+	} else
+		printk("Non-serviced A3000 SCSI-interrupt? ISTR = %02x\n",
+		       status);
 }
 
-static void do_a3000_intr (int irq, void *dummy, struct pt_regs *fp)
-{
-    unsigned long flags;
-
-    spin_lock_irqsave(&io_request_lock, flags);
-    a3000_intr(irq, dummy, fp);
-    spin_unlock_irqrestore(&io_request_lock, flags);
-}
 static int dma_setup (Scsi_Cmnd *cmd, int dir_in)
 {
     unsigned short cntr = CNTR_PDMD | CNTR_INTEN;
-    unsigned long addr = VTOP(cmd->SCp.ptr);
+    unsigned long addr = virt_to_bus(cmd->SCp.ptr);
 
     /*
      * if the physical address has the wrong alignment, or if
@@ -91,7 +82,7 @@
 			cmd->request_buffer, cmd->request_bufflen);
 	}
 
-	addr = VTOP(HDATA(a3000_host)->dma_bounce_buffer);
+	addr = virt_to_bus(HDATA(a3000_host)->dma_bounce_buffer);
     }
 
     /* setup dma direction */
@@ -175,7 +166,7 @@
     }
 }
 
-__initfunc(int a3000_detect(Scsi_Host_Template *tpnt))
+int __init a3000_detect(Scsi_Host_Template *tpnt)
 {
     static unsigned char called = 0;
 
@@ -194,7 +185,8 @@
     DMA(a3000_host)->DAWR = DAWR_A3000;
     wd33c93_init(a3000_host, (wd33c93_regs *)&(DMA(a3000_host)->SASR),
 		 dma_setup, dma_stop, WD33C93_FS_12_15);
-    request_irq(IRQ_AMIGA_PORTS, do_a3000_intr, 0, "A3000 SCSI", a3000_intr);
+    request_irq(IRQ_AMIGA_PORTS, a3000_intr, SA_SHIRQ, "A3000 SCSI",
+		a3000_intr);
     DMA(a3000_host)->CNTR = CNTR_PDMD | CNTR_INTEN;
     called = 1;
 
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/amiga7xx.c linux/drivers/scsi/amiga7xx.c
--- v2.3.13/linux/drivers/scsi/amiga7xx.c	Mon Oct  5 13:43:31 1998
+++ linux/drivers/scsi/amiga7xx.c	Wed Aug 18 10:00:52 1999
@@ -15,11 +15,14 @@
 #include <linux/config.h>
 #include <linux/zorro.h>
 
+#include <asm/setup.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/amigaints.h>
 #include <asm/amigahw.h>
+#include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/init.h>
 
 #include "scsi.h"
 #include "hosts.h"
@@ -33,11 +36,11 @@
     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);
+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);
 
-int amiga7xx_detect(Scsi_Host_Template *tpnt)
+int __init amiga7xx_detect(Scsi_Host_Template *tpnt)
 {
     static unsigned char called = 0;
     unsigned int key;
@@ -54,18 +57,13 @@
     if ((key = zorro_find(ZORRO_PROD_PHASE5_BLIZZARD_603E_PLUS, 0, 0)))
     {
 	cd = zorro_get_board(key);
-/*
-	unsigned long address;
-	address = (unsigned long)kernel_map((unsigned long)cd->cd_BoardAddr,
-		cd->cd_BoardSize, KERNELMAP_NOCACHE_SER, NULL);
-*/
+
 	options = OPTION_MEMORY_MAPPED|OPTION_DEBUG_TEST1|OPTION_INTFLY|OPTION_SYNCHRONOUS|OPTION_ALWAYS_SYNCHRONOUS|OPTION_DISCONNECT;
 
 	clock = 50000000;	/* 50MHz SCSI Clock */
 
-	ncr53c7xx_init(tpnt, 0, 710, (u32)(unsigned char *)(0x80f40000),
-			0, IRQ_AMIGA_PORTS, DMA_NONE, 
-			options, clock);
+	ncr53c7xx_init(tpnt, 0, 710, (u32)ZTWO_VADDR(0xf40000),	0,
+		       IRQ_AMIGA_PORTS, DMA_NONE, options, clock);
 
 	zorro_config_board(key, 0);
 	num++;
@@ -77,16 +75,15 @@
     {
 	unsigned long address;
 	cd = zorro_get_board(key);
-	address = (unsigned long)kernel_map((unsigned long)cd->cd_BoardAddr,
-		cd->cd_BoardSize, KERNELMAP_NOCACHE_SER, NULL);
+	address = (unsigned long)ioremap((unsigned long)cd->cd_BoardAddr,
+						cd->cd_BoardSize);
 
 	options = OPTION_MEMORY_MAPPED|OPTION_DEBUG_TEST1|OPTION_INTFLY|OPTION_SYNCHRONOUS|OPTION_ALWAYS_SYNCHRONOUS|OPTION_DISCONNECT;
 
 	clock = 50000000;	/* 50MHz SCSI Clock */
 
 	ncr53c7xx_init(tpnt, 0, 710, (u32)(unsigned char *)(address + 0x40000),
-			0, IRQ_AMIGA_PORTS, DMA_NONE, 
-			options, clock);
+		       0, IRQ_AMIGA_PORTS, DMA_NONE, options, clock);
 
 	zorro_config_board(key, 0);
 	num++;
@@ -100,9 +97,8 @@
 
 	clock = 50000000;	/* 50MHz SCSI Clock */
 
-    	ncr53c7xx_init(tpnt, 0, 710, (u32)(unsigned char *)ZTWO_VADDR(0xDD0040),
-			0, IRQ_AMIGA_PORTS, DMA_NONE,
-			options, clock);
+    	ncr53c7xx_init(tpnt, 0, 710, (u32)ZTWO_VADDR(0xDD0040), 0,
+		       IRQ_AMIGA_PORTS, DMA_NONE, options, clock);
     	num++;
     }
 #endif
@@ -113,8 +109,8 @@
     {
 	unsigned long address;
 	cd = zorro_get_board(key);
-	address = (unsigned long)kernel_map((unsigned long)cd->cd_BoardAddr,
-		cd->cd_BoardSize, KERNELMAP_NOCACHE_SER, NULL);
+	address = (unsigned long)ioremap((unsigned long)cd->cd_BoardAddr,
+						cd->cd_BoardSize);
 
     	options = OPTION_MEMORY_MAPPED|OPTION_DEBUG_TEST1|OPTION_INTFLY|OPTION_SYNCHRONOUS|OPTION_ALWAYS_SYNCHRONOUS|OPTION_DISCONNECT;
 
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/atari_NCR5380.c linux/drivers/scsi/atari_NCR5380.c
--- v2.3.13/linux/drivers/scsi/atari_NCR5380.c	Tue May 13 22:41:13 1997
+++ linux/drivers/scsi/atari_NCR5380.c	Wed Aug 18 10:00:52 1999
@@ -472,9 +472,9 @@
     int		  cnt = 1;
 #endif
 
-    for (endaddr = VTOP(cmd->SCp.ptr + cmd->SCp.this_residual - 1) + 1;
+    for (endaddr = virt_to_phys(cmd->SCp.ptr + cmd->SCp.this_residual - 1) + 1;
 	 cmd->SCp.buffers_residual &&
-	 VTOP(cmd->SCp.buffer[1].address) == endaddr; ) {
+	 virt_to_phys(cmd->SCp.buffer[1].address) == endaddr; ) {
 	
 	MER_PRINTK("VTOP(%p) == %08lx -> merging\n",
 		   cmd->SCp.buffer[1].address, endaddr);
@@ -1459,9 +1459,9 @@
       unsigned long timeout = jiffies + 2*NCR_TIMEOUT;
 
       while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS)
-	   && jiffies < timeout && !hostdata->connected)
+	   && time_before(jiffies, timeout) && !hostdata->connected)
 	;
-      if (jiffies >= timeout)
+      if (time_after_eq(jiffies, timeout))
       {
 	printk("scsi : arbitration timeout at %d\n", __LINE__);
 	NCR5380_write(MODE_REG, MR_BASE);
@@ -1616,7 +1616,7 @@
      * only wait for BSY... (Famous german words: Der Klügere gibt nach :-)
      */
 
-    while ((jiffies < timeout) && !(NCR5380_read(STATUS_REG) & 
+    while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) & 
 	(SR_BSY | SR_IO)));
 
     if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == 
@@ -1629,7 +1629,7 @@
 	    return -1;
     }
 #else
-    while ((jiffies < timeout) && !(NCR5380_read(STATUS_REG) & SR_BSY));
+    while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) & SR_BSY));
 #endif
 
     /* 
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/atari_scsi.c linux/drivers/scsi/atari_scsi.c
--- v2.3.13/linux/drivers/scsi/atari_scsi.c	Tue May 11 15:49:26 1999
+++ linux/drivers/scsi/atari_scsi.c	Wed Aug 18 10:00:52 1999
@@ -132,51 +132,51 @@
 	} while(0)
 
 #define	SCSI_DMA_READ_P(elt)					\
-	(((unsigned long)tt_scsi_dma.elt##_hi  << 24) |		\
-	 ((unsigned long)tt_scsi_dma.elt##_hmd << 16) |		\
-	 ((unsigned long)tt_scsi_dma.elt##_lmd << 8) |		\
-	  (unsigned long)tt_scsi_dma.elt##_lo)
-
-
-#define	SCSI_DMA_SETADR(adr)				\
-    do {						\
-	unsigned long __adr = (adr);			\
-	st_dma.dma_lo = (unsigned char)__adr;		\
-	MFPDELAY();					\
-	__adr >>= 8;					\
-	st_dma.dma_md = (unsigned char)__adr;		\
-	MFPDELAY();					\
-	__adr >>= 8;					\
-	st_dma.dma_hi = (unsigned char)__adr;		\
-	MFPDELAY();					\
-    } while(0)
-
-#define	SCSI_DMA_GETADR() ({				\
-    unsigned long	__adr;				\
-    __adr = st_dma.dma_lo;				\
-    MFPDELAY();						\
-    __adr |= (st_dma.dma_md & 0xff) << 8;		\
-    MFPDELAY();						\
-    __adr |= (st_dma.dma_hi & 0xff) << 16;		\
-    MFPDELAY();						\
-    __adr;						\
-})
-
-#define	ENABLE_IRQ()					\
-	do {						\
-		if (IS_A_TT())				\
-			atari_enable_irq( IRQ_TT_MFP_SCSI );	\
-		else					\
-			atari_enable_irq( IRQ_MFP_FSCSI );	\
-	} while(0)
-
-#define	DISABLE_IRQ()					\
-	do {						\
-		if (IS_A_TT())				\
-			atari_disable_irq( IRQ_TT_MFP_SCSI );	\
-		else					\
-			atari_disable_irq( IRQ_MFP_FSCSI );	\
-	} while(0)
+	(((((((unsigned long)tt_scsi_dma.elt##_hi << 8) |	\
+	     (unsigned long)tt_scsi_dma.elt##_hmd) << 8) |	\
+	   (unsigned long)tt_scsi_dma.elt##_lmd) << 8) |	\
+	 (unsigned long)tt_scsi_dma.elt##_lo)
+
+
+static inline void SCSI_DMA_SETADR(unsigned long adr)
+{
+	st_dma.dma_lo = (unsigned char)adr;
+	MFPDELAY();
+	adr >>= 8;
+	st_dma.dma_md = (unsigned char)adr;
+	MFPDELAY();
+	adr >>= 8;
+	st_dma.dma_hi = (unsigned char)adr;
+	MFPDELAY();
+}
+
+static inline unsigned long SCSI_DMA_GETADR(void)
+{
+	unsigned long adr;
+	adr = st_dma.dma_lo;
+	MFPDELAY();
+	adr |= (st_dma.dma_md & 0xff) << 8;
+	MFPDELAY();
+	adr |= (st_dma.dma_hi & 0xff) << 16;
+	MFPDELAY();
+	return adr;
+}
+
+static inline void ENABLE_IRQ(void)
+{
+	if (IS_A_TT())
+		atari_enable_irq(IRQ_TT_MFP_SCSI);
+	else
+		atari_enable_irq(IRQ_MFP_FSCSI);
+}
+
+static inline void DISABLE_IRQ(void)
+{
+	if (IS_A_TT())
+		atari_disable_irq(IRQ_TT_MFP_SCSI);
+	else
+		atari_disable_irq(IRQ_MFP_FSCSI);
+}
 
 
 #define HOSTDATA_DMALEN		(((struct NCR5380_hostdata *) \
@@ -461,8 +461,8 @@
 		/* If the dribble buffer was used on a read operation, copy the DMA-ed
 		 * data to the original destination address.
 		 */
-		memcpy( atari_dma_orig_addr, (void *)PTOV(atari_dma_startaddr),
-		       HOSTDATA_DMALEN - atari_dma_residual );
+		memcpy(atari_dma_orig_addr, phys_to_virt(atari_dma_startaddr),
+		       HOSTDATA_DMALEN - atari_dma_residual);
 		atari_dma_orig_addr = NULL;
 	}
 
@@ -476,20 +476,22 @@
 static void atari_scsi_fetch_restbytes( void )
 {
 	int nr;
-	char	*src, *dst;
+	char *src, *dst;
+	unsigned long phys_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 );
+	phys_dst = SCSI_DMA_READ_P(dma_addr);
+	nr = phys_dst & 3;
+	if (nr) {
+		/* there are 'nr' bytes left for the last long address
+		   before the DMA pointer */
+		phys_dst ^= nr;
 		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 *)&tt_scsi_dma.dma_restdata; nr > 0; --nr )
+			   nr, phys_dst);
+		/* The content of the DMA pointer is a physical address!  */
+		dst = phys_to_virt(phys_dst);
+		DMA_PRINTK(" = virt addr %p\n", dst);
+		for (src = (char *)&tt_scsi_dma.dma_restdata; nr != 0; --nr)
 			*dst++ = *src++;
 	}
 }
@@ -665,7 +667,7 @@
 					"double buffer\n" );
 			return( 0 );
 		}
-		atari_dma_phys_buffer = VTOP( atari_dma_buffer );
+		atari_dma_phys_buffer = virt_to_phys( atari_dma_buffer );
 		atari_dma_orig_addr = 0;
 	}
 #endif
@@ -764,7 +766,7 @@
 }
 #endif
 
-__initfunc(void atari_scsi_setup( char *str, int *ints ))
+void __init atari_scsi_setup(char *str, int *ints)
 {
 	/* Format of atascsi parameter is:
 	 *   atascsi=<can_queue>,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags>
@@ -772,23 +774,6 @@
 	 * Negative values mean don't change.
 	 */
 	
-	/* Grmbl... the standard parameter parsing can't handle negative numbers
-	 * :-( So let's do it ourselves!
-	 */
-
-	int i = ints[0]+1, fact;
-
-	while( str && (isdigit(*str) || *str == '-') && i <= 10) {
-		if (*str == '-')
-			fact = -1, ++str;
-		else
-			fact = 1;
-		ints[i++] = simple_strtoul( str, NULL, 0 ) * fact;
-		if ((str = strchr( str, ',' )) != NULL)
-			++str;
-	}
-	ints[0] = i-1;
-	
 	if (ints[0] < 1) {
 		printk( "atari_scsi_setup: no arguments!\n" );
 		return;
@@ -869,7 +854,7 @@
 
 	
 #ifdef CONFIG_ATARI_SCSI_RESET_BOOT
-__initfunc(static void atari_scsi_reset_boot( void ))
+static void __init atari_scsi_reset_boot(void)
 {
 	unsigned long end;
 	
@@ -892,7 +877,8 @@
 	NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
 	NCR5380_read( RESET_PARITY_INTERRUPT_REG );
 
-	for( end = jiffies + AFTER_RESET_DELAY; jiffies < end; )
+	end = jiffies + AFTER_RESET_DELAY;
+	while (time_before(jiffies, end))
 		barrier();
 
 	printk( " done\n" );
@@ -913,7 +899,7 @@
 unsigned long atari_scsi_dma_setup( struct Scsi_Host *instance, void *data,
 				   unsigned long count, int dir )
 {
-	unsigned long addr = VTOP( data );
+	unsigned long addr = virt_to_phys( data );
 
 	DMA_PRINTK("scsi%d: setting up dma, data = %p, phys = %lx, count = %ld, "
 		   "dir = %d\n", instance->host_no, data, addr, count, dir);
@@ -1097,7 +1083,7 @@
 	}
 	
 	/* Last step: apply the hard limit on DMA transfers */
-	limit = (atari_dma_buffer && !STRAM_ADDR( VTOP(cmd->SCp.ptr) )) ?
+	limit = (atari_dma_buffer && !STRAM_ADDR( virt_to_phys(cmd->SCp.ptr) )) ?
 		    STRAM_BUFFER_SIZE : 255*512;
 	if (possible_len > limit)
 		possible_len = limit;
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/blz1230.c linux/drivers/scsi/blz1230.c
--- v2.3.13/linux/drivers/scsi/blz1230.c	Wed Nov 11 11:50:00 1998
+++ linux/drivers/scsi/blz1230.c	Wed Aug 18 10:00:52 1999
@@ -14,6 +14,8 @@
  *    routines in this file used to be inline!
  */
 
+#include <linux/module.h>
+
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/types.h>
@@ -55,7 +57,7 @@
 				 */
 
 /***************************************************************** Detection */
-int blz1230_esp_detect(Scsi_Host_Template *tpnt)
+int __init blz1230_esp_detect(Scsi_Host_Template *tpnt)
 {
 	struct NCR_ESP *esp;
 	const struct ConfigDev *esp_dev;
@@ -80,12 +82,15 @@
 		eregs = (struct ESP_regs *)(address + BLZ1230II_ESP_ADDR);
 #endif
 
-		eregs->esp_cfg1 = (ESP_CONFIG1_PENABLE | 7);
+		esp = esp_allocate(tpnt, (void *) esp_dev);
+
+		esp_write(eregs->esp_cfg1, (ESP_CONFIG1_PENABLE | 7));
 		udelay(5);
-		if(eregs->esp_cfg1 != (ESP_CONFIG1_PENABLE | 7))
+		if(esp_read(eregs->esp_cfg1) != (ESP_CONFIG1_PENABLE | 7)){
+			esp_deallocate(esp);
+			scsi_unregister(esp->ehost);
 			return 0; /* Bail out if address did not hold data */
-
-		esp = esp_allocate(tpnt, (void *) esp_dev);
+		}
 
 		/* Do command transfer with programmed I/O */
 		esp->do_pio_cmds = 1;
@@ -131,24 +136,24 @@
 
 		/* Set the command buffer */
 		esp->esp_command = (volatile unsigned char*) cmd_buffer;
-		esp->esp_command_dvma = virt_to_bus((unsigned long) cmd_buffer);
+		esp->esp_command_dvma = virt_to_bus(cmd_buffer);
 
 		esp->irq = IRQ_AMIGA_PORTS;
-		request_irq(IRQ_AMIGA_PORTS, esp_intr, 0, 
+		esp->slot = key;
+		request_irq(IRQ_AMIGA_PORTS, esp_intr, SA_SHIRQ,
 			    "Blizzard 1230 SCSI IV", esp_intr);
 
 		/* Figure out our scsi ID on the bus */
 		esp->scsi_id = 7;
 		
-		/* Check for differential SCSI-bus */
-		/* What is this stuff? */
+		/* We don't have a differential SCSI-bus. */
 		esp->diff = 0;
 
 		esp_initialize(esp);
 
 		zorro_config_board(key, 0);
 
-		printk("\nESP: Total of %d ESP hosts found, %d actually in use.\n", nesps,esps_in_use);
+		printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps, esps_in_use);
 		esps_running = esps_in_use;
 		return esps_in_use;
 	}
@@ -249,7 +254,7 @@
 
 static int dma_irq_p(struct NCR_ESP *esp)
 {
-	return (esp->eregs->esp_status & ESP_STAT_INTR);
+	return (esp_read(esp->eregs->esp_status) & ESP_STAT_INTR);
 }
 
 static int dma_ports_p(struct NCR_ESP *esp)
@@ -267,4 +272,30 @@
 	} else {
 		dma_init_write(esp, addr, count);
 	}
+}
+
+#ifdef MODULE
+
+#define HOSTS_C
+
+#include "blz1230.h"
+
+Scsi_Host_Template driver_template = SCSI_BLZ1230;
+
+#include "scsi_module.c"
+
+#endif
+
+int blz1230_esp_release(struct Scsi_Host *instance)
+{
+#ifdef MODULE
+	unsigned int key;
+
+	key = ((struct NCR_ESP *)instance->hostdata)->slot;
+	esp_deallocate((struct NCR_ESP *)instance->hostdata);
+	esp_release();
+	zorro_unconfig_board(key, 0);
+	free_irq(IRQ_AMIGA_PORTS, esp_intr);
+#endif
+	return 1;
 }
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/blz1230.h linux/drivers/scsi/blz1230.h
--- v2.3.13/linux/drivers/scsi/blz1230.h	Tue Jun 22 14:43:06 1999
+++ linux/drivers/scsi/blz1230.h	Wed Aug 18 10:00:52 1999
@@ -48,6 +48,7 @@
 #define BLZ1230_DMA_WRITE 0x80000000
 
 extern int blz1230_esp_detect(struct SHT *);
+extern int blz1230_esp_release(struct Scsi_Host *);
 extern const char *esp_info(struct Scsi_Host *);
 extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 extern int esp_command(Scsi_Cmnd *);
@@ -57,9 +58,11 @@
 			 int hostno, int inout);
 
 #define SCSI_BLZ1230      { proc_dir:		&proc_scsi_esp, \
+			    proc_info:		esp_proc_info, \
 			    name:		"Blizzard1230 SCSI IV", \
 			    detect:		blz1230_esp_detect, \
-			    release:		NULL, \
+			    release:		blz1230_esp_release, \
+			    command:		esp_command, \
 			    queuecommand:	esp_queue, \
 			    abort:		esp_abort, \
 			    reset:		esp_reset, \
@@ -67,6 +70,6 @@
 			    this_id:		7, \
 			    sg_tablesize:	SG_ALL, \
 			    cmd_per_lun:	1, \
-			    use_clustering:	DISABLE_CLUSTERING }
+			    use_clustering:	ENABLE_CLUSTERING }
 
 #endif /* BLZ1230_H */
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/blz2060.c linux/drivers/scsi/blz2060.c
--- v2.3.13/linux/drivers/scsi/blz2060.c	Wed Nov 11 11:50:00 1998
+++ linux/drivers/scsi/blz2060.c	Wed Aug 18 10:00:52 1999
@@ -14,6 +14,8 @@
  *    routines in this file used to be inline!
  */
 
+#include <linux/module.h>
+
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/types.h>
@@ -55,7 +57,7 @@
 				 */
 
 /***************************************************************** Detection */
-int blz2060_esp_detect(Scsi_Host_Template *tpnt)
+int __init blz2060_esp_detect(Scsi_Host_Template *tpnt)
 {
 	struct NCR_ESP *esp;
 	const struct ConfigDev *esp_dev;
@@ -107,24 +109,24 @@
 		
 		/* Set the command buffer */
 		esp->esp_command = (volatile unsigned char*) cmd_buffer;
-		esp->esp_command_dvma = virt_to_bus((unsigned long) cmd_buffer);
+		esp->esp_command_dvma = virt_to_bus(cmd_buffer);
 
 		esp->irq = IRQ_AMIGA_PORTS;
-		request_irq(IRQ_AMIGA_PORTS, esp_intr, 0, 
+		esp->slot = key;
+		request_irq(IRQ_AMIGA_PORTS, esp_intr, SA_SHIRQ,
 			    "Blizzard 2060 SCSI", esp_intr);
 
 		/* Figure out our scsi ID on the bus */
 		esp->scsi_id = 7;
 		
-		/* Check for differential SCSI-bus */
-		/* What is this stuff? */
+		/* We don't have a differential SCSI-bus. */
 		esp->diff = 0;
 
 		esp_initialize(esp);
 
 		zorro_config_board(key, 0);
 
-		printk("\nESP: Total of %d ESP hosts found, %d actually in use.\n", nesps,esps_in_use);
+		printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps, esps_in_use);
 		esps_running = esps_in_use;
 		return esps_in_use;
 	}
@@ -201,7 +203,7 @@
 
 static int dma_irq_p(struct NCR_ESP *esp)
 {
-	return (esp->eregs->esp_status & ESP_STAT_INTR);
+	return (esp_read(esp->eregs->esp_status) & ESP_STAT_INTR);
 }
 
 static void dma_led_off(struct NCR_ESP *esp)
@@ -230,4 +232,30 @@
 	} else {
 		dma_init_write(esp, addr, count);
 	}
+}
+
+#ifdef MODULE
+
+#define HOSTS_C
+
+#include "blz2060.h"
+
+Scsi_Host_Template driver_template = SCSI_BLZ2060;
+
+#include "scsi_module.c"
+
+#endif
+
+int blz2060_esp_release(struct Scsi_Host *instance)
+{
+#ifdef MODULE
+	unsigned int key;
+
+	key = ((struct NCR_ESP *)instance->hostdata)->slot;
+	esp_deallocate((struct NCR_ESP *)instance->hostdata);
+	esp_release();
+	zorro_unconfig_board(key, 0);
+	free_irq(IRQ_AMIGA_PORTS, esp_intr);
+#endif
+	return 1;
 }
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/blz2060.h linux/drivers/scsi/blz2060.h
--- v2.3.13/linux/drivers/scsi/blz2060.h	Tue Jun 22 14:43:06 1999
+++ linux/drivers/scsi/blz2060.h	Wed Aug 18 10:00:52 1999
@@ -44,6 +44,7 @@
 #define BLZ2060_DMA_LED    0x02		/* HD led control 1 = off */
 
 extern int blz2060_esp_detect(struct SHT *);
+extern int blz2060_esp_release(struct Scsi_Host *);
 extern const char *esp_info(struct Scsi_Host *);
 extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 extern int esp_command(Scsi_Cmnd *);
@@ -53,9 +54,10 @@
 			 int hostno, int inout);
 
 #define SCSI_BLZ2060      { proc_dir:		&proc_scsi_esp, \
+			    proc_info:		esp_proc_info, \
 			    name:		"Blizzard2060 SCSI", \
 			    detect:		blz2060_esp_detect, \
-			    release:		NULL, \
+			    release:		blz2060_esp_release, \
 			    queuecommand:	esp_queue, \
 			    abort:		esp_abort, \
 			    reset:		esp_reset, \
@@ -63,6 +65,6 @@
 			    this_id:		7, \
 			    sg_tablesize:	SG_ALL, \
 			    cmd_per_lun:	1, \
-			    use_clustering:	DISABLE_CLUSTERING }
+			    use_clustering:	ENABLE_CLUSTERING }
 
 #endif /* BLZ2060_H */
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/cyberstorm.c linux/drivers/scsi/cyberstorm.c
--- v2.3.13/linux/drivers/scsi/cyberstorm.c	Wed Nov 11 11:50:00 1998
+++ linux/drivers/scsi/cyberstorm.c	Wed Aug 18 10:00:52 1999
@@ -17,6 +17,8 @@
  *    routines in this file used to be inline!
  */
 
+#include <linux/module.h>
+
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/types.h>
@@ -64,7 +66,7 @@
 				 */
 
 /***************************************************************** Detection */
-int cyber_esp_detect(Scsi_Host_Template *tpnt)
+int __init cyber_esp_detect(Scsi_Host_Template *tpnt)
 {
 	struct NCR_ESP *esp;
 	const struct ConfigDev *esp_dev;
@@ -127,10 +129,11 @@
 		
 		/* Set the command buffer */
 		esp->esp_command = (volatile unsigned char*) cmd_buffer;
-		esp->esp_command_dvma = virt_to_bus((unsigned long) cmd_buffer);
+		esp->esp_command_dvma = virt_to_bus(cmd_buffer);
 
 		esp->irq = IRQ_AMIGA_PORTS;
-		request_irq(IRQ_AMIGA_PORTS, esp_intr, 0, 
+		esp->slot = key;
+		request_irq(IRQ_AMIGA_PORTS, esp_intr, SA_SHIRQ,
 			    "CyberStorm SCSI", esp_intr);
 		/* Figure out our scsi ID on the bus */
 		/* The DMA cond flag contains a hardcoded jumper bit
@@ -140,15 +143,14 @@
 		 */
 		esp->scsi_id = 7;
 		
-		/* Check for differential SCSI-bus */
-		/* What is this stuff? */
+		/* We don't have a differential SCSI-bus. */
 		esp->diff = 0;
 
 		esp_initialize(esp);
 
 		zorro_config_board(key, 0);
 
-		printk("\nESP: Total of %d ESP hosts found, %d actually in use.\n", nesps,esps_in_use);
+		printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps, esps_in_use);
 		esps_running = esps_in_use;
 		return esps_in_use;
 	}
@@ -263,7 +265,7 @@
 static int dma_irq_p(struct NCR_ESP *esp)
 {
 	/* It's important to check the DMA IRQ bit in the correct way! */
-	return ((esp->eregs->esp_status & ESP_STAT_INTR) &&
+	return ((esp_read(esp->eregs->esp_status) & ESP_STAT_INTR) &&
 		((((struct cyber_dma_registers *)(esp->dregs))->cond_reg) &
 		 CYBER_DMA_HNDL_INTR));
 }
@@ -295,4 +297,30 @@
 	} else {
 		dma_init_write(esp, addr, count);
 	}
+}
+
+#ifdef MODULE
+
+#define HOSTS_C
+
+#include "cyberstorm.h"
+
+Scsi_Host_Template driver_template = SCSI_CYBERSTORM;
+
+#include "scsi_module.c"
+
+#endif
+
+int cyber_esp_release(struct Scsi_Host *instance)
+{
+#ifdef MODULE
+	unsigned int key;
+
+	key = ((struct NCR_ESP *)instance->hostdata)->slot;
+	esp_deallocate((struct NCR_ESP *)instance->hostdata);
+	esp_release();
+	zorro_unconfig_board(key, 0);
+	free_irq(IRQ_AMIGA_PORTS, esp_intr);
+#endif
+	return 1;
 }
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/cyberstorm.h linux/drivers/scsi/cyberstorm.h
--- v2.3.13/linux/drivers/scsi/cyberstorm.h	Tue Jun 22 14:43:06 1999
+++ linux/drivers/scsi/cyberstorm.h	Wed Aug 18 10:00:52 1999
@@ -46,6 +46,7 @@
 #define CYBER_SLOW_CABLE 0x08	/* If *not* set, assume SLOW_CABLE */
 
 extern int cyber_esp_detect(struct SHT *);
+extern int cyber_esp_release(struct Scsi_Host *);
 extern const char *esp_info(struct Scsi_Host *);
 extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 extern int esp_command(Scsi_Cmnd *);
@@ -56,9 +57,10 @@
 
 
 #define SCSI_CYBERSTORM   { proc_dir:		&proc_scsi_esp, \
+			    proc_info:		esp_proc_info, \
 			    name:		"CyberStorm SCSI", \
 			    detect:		cyber_esp_detect, \
-			    release:		NULL, \
+			    release:		cyber_esp_release, \
 			    queuecommand:	esp_queue, \
 			    abort:		esp_abort, \
 			    reset:		esp_reset, \
@@ -66,7 +68,6 @@
 			    this_id:		7, \
 			    sg_tablesize:	SG_ALL, \
 			    cmd_per_lun:	1, \
-			    use_clustering:	DISABLE_CLUSTERING }
+			    use_clustering:	ENABLE_CLUSTERING }
 
 #endif /* CYBER_ESP_H */
-
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/cyberstormII.c linux/drivers/scsi/cyberstormII.c
--- v2.3.13/linux/drivers/scsi/cyberstormII.c	Mon Oct  5 13:43:31 1998
+++ linux/drivers/scsi/cyberstormII.c	Wed Aug 18 10:00:52 1999
@@ -13,6 +13,8 @@
  *    routines in this file used to be inline!
  */
 
+#include <linux/module.h>
+
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/types.h>
@@ -54,7 +56,7 @@
 				 */
 
 /***************************************************************** Detection */
-int cyberII_esp_detect(Scsi_Host_Template *tpnt)
+int __init cyberII_esp_detect(Scsi_Host_Template *tpnt)
 {
 	struct NCR_ESP *esp;
 	const struct ConfigDev *esp_dev;
@@ -71,12 +73,15 @@
 		address = (unsigned long)ZTWO_VADDR(esp_dev->cd_BoardAddr);
 		eregs = (struct ESP_regs *)(address + CYBERII_ESP_ADDR);
 
-		eregs->esp_cfg1 = (ESP_CONFIG1_PENABLE | 7);
+		esp = esp_allocate(tpnt, (void *) esp_dev);
+
+		esp_write(eregs->esp_cfg1, (ESP_CONFIG1_PENABLE | 7));
 		udelay(5);
-		if(eregs->esp_cfg1 != (ESP_CONFIG1_PENABLE | 7))
+		if(esp_read(eregs->esp_cfg1) != (ESP_CONFIG1_PENABLE | 7)) {
+			esp_deallocate(esp);
+			scsi_unregister(esp->ehost);
 			return 0; /* Bail out if address did not hold data */
-
-		esp = esp_allocate(tpnt, (void *) esp_dev);
+		}
 
 		/* Do command transfer with programmed I/O */
 		esp->do_pio_cmds = 1;
@@ -118,24 +123,24 @@
 		
 		/* Set the command buffer */
 		esp->esp_command = (volatile unsigned char*) cmd_buffer;
-		esp->esp_command_dvma = virt_to_bus((unsigned long) cmd_buffer);
+		esp->esp_command_dvma = virt_to_bus(cmd_buffer);
 
 		esp->irq = IRQ_AMIGA_PORTS;
-		request_irq(IRQ_AMIGA_PORTS, esp_intr, 0, 
+		esp->slot = key;
+		request_irq(IRQ_AMIGA_PORTS, esp_intr, SA_SHIRQ,
 			    "CyberStorm SCSI Mk II", esp_intr);
 
 		/* Figure out our scsi ID on the bus */
 		esp->scsi_id = 7;
 		
-		/* Check for differential SCSI-bus */
-		/* What is this stuff? */
+		/* We don't have a differential SCSI-bus. */
 		esp->diff = 0;
 
 		esp_initialize(esp);
 
 		zorro_config_board(key, 0);
 
-		printk("\nESP: Total of %d ESP hosts found, %d actually in use.\n", nesps,esps_in_use);
+		printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps, esps_in_use);
 		esps_running = esps_in_use;
 		return esps_in_use;
 	}
@@ -214,7 +219,7 @@
 static int dma_irq_p(struct NCR_ESP *esp)
 {
 	/* It's important to check the DMA IRQ bit in the correct way! */
-	return (esp->eregs->esp_status & ESP_STAT_INTR);
+	return (esp_read(esp->eregs->esp_status) & ESP_STAT_INTR);
 }
 
 static void dma_led_off(struct NCR_ESP *esp)
@@ -242,4 +247,30 @@
 	} else {
 		dma_init_write(esp, addr, count);
 	}
+}
+
+#ifdef MODULE
+
+#define HOSTS_C
+
+#include "cyberstormII.h"
+
+Scsi_Host_Template driver_template = SCSI_CYBERSTORMII;
+
+#include "scsi_module.c"
+
+#endif
+
+int cyberII_esp_release(struct Scsi_Host *instance)
+{
+#ifdef MODULE
+	unsigned int key;
+
+	key = ((struct NCR_ESP *)instance->hostdata)->slot;
+	esp_deallocate((struct NCR_ESP *)instance->hostdata); 
+	esp_release();
+	zorro_unconfig_board(key, 0);
+	free_irq(IRQ_AMIGA_PORTS, esp_intr);
+#endif
+	return 1;
 }
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/cyberstormII.h linux/drivers/scsi/cyberstormII.h
--- v2.3.13/linux/drivers/scsi/cyberstormII.h	Tue Jun 22 14:43:06 1999
+++ linux/drivers/scsi/cyberstormII.h	Wed Aug 18 10:00:52 1999
@@ -34,6 +34,7 @@
 
 
 extern int cyberII_esp_detect(struct SHT *);
+extern int cyberII_esp_release(struct Scsi_Host *);
 extern const char *esp_info(struct Scsi_Host *);
 extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 extern int esp_command(Scsi_Cmnd *);
@@ -43,9 +44,10 @@
 			 int hostno, int inout);
 
 #define SCSI_CYBERSTORMII { proc_dir:		&proc_scsi_esp, \
+			    proc_info:		esp_proc_info, \
 			    name:		"CyberStorm Mk II SCSI", \
 			    detect:		cyberII_esp_detect, \
-			    release:		NULL, \
+			    release:		cyberII_esp_release, \
 			    queuecommand:	esp_queue, \
 			    abort:		esp_abort, \
 			    reset:		esp_reset, \
@@ -53,7 +55,6 @@
 			    this_id:		7, \
 			    sg_tablesize:	SG_ALL, \
 			    cmd_per_lun:	1, \
-			    use_clustering:	DISABLE_CLUSTERING }
+			    use_clustering:	ENABLE_CLUSTERING }
 
 #endif /* CYBERII_ESP_H */
-
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/fastlane.c linux/drivers/scsi/fastlane.c
--- v2.3.13/linux/drivers/scsi/fastlane.c	Wed Nov 11 11:50:00 1998
+++ linux/drivers/scsi/fastlane.c	Wed Aug 18 10:00:52 1999
@@ -22,6 +22,8 @@
  *    routines in this file used to be inline!
  */
 
+#include <linux/module.h>
+
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/types.h>
@@ -38,6 +40,7 @@
 
 #include <linux/zorro.h>
 #include <asm/irq.h>
+#include <asm/io.h>
 #include <asm/amigaints.h>
 #include <asm/amigahw.h>
 
@@ -77,7 +80,7 @@
 				 */
 
 /***************************************************************** Detection */
-int fastlane_esp_detect(Scsi_Host_Template *tpnt)
+int __init fastlane_esp_detect(Scsi_Host_Template *tpnt)
 {
 	struct NCR_ESP *esp;
 	const struct ConfigDev *esp_dev;
@@ -137,10 +140,8 @@
 
 		/* Map the physical address space into virtual kernel space */
 		address = (unsigned long)
-			kernel_map((unsigned long)esp_dev->cd_BoardAddr,
-				   esp_dev->cd_BoardSize,
-				   KERNELMAP_NOCACHE_SER,
-				   NULL);
+			ioremap_nocache((unsigned long)esp_dev->cd_BoardAddr,
+					esp_dev->cd_BoardSize);
 
 		if(!address){
 			printk("Could not remap Fastlane controller memory!");
@@ -163,17 +164,17 @@
 		
 		/* Set the command buffer */
 		esp->esp_command = (volatile unsigned char*) cmd_buffer;
-		esp->esp_command_dvma = virt_to_bus((unsigned long) cmd_buffer);
+		esp->esp_command_dvma = virt_to_bus(cmd_buffer);
 
 		esp->irq = IRQ_AMIGA_PORTS;
-		request_irq(IRQ_AMIGA_PORTS, esp_intr, 0, 
+		esp->slot = key;
+		request_irq(IRQ_AMIGA_PORTS, esp_intr, SA_SHIRQ,
 			    "Fastlane SCSI", esp_intr);
 
 		/* Controller ID */
 		esp->scsi_id = 7;
 		
-		/* Check for differential SCSI-bus */
-		/* What is this stuff? */
+		/* We don't have a differential SCSI-bus. */
 		esp->diff = 0;
 
 		dma_clear(esp);
@@ -181,7 +182,7 @@
 
 		zorro_config_board(key, 0);
 
-		printk("\nESP: Total of %d ESP hosts found, %d actually in use.\n", nesps,esps_in_use);
+		printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps, esps_in_use);
 		esps_running = esps_in_use;
 		return esps_in_use;
 	}
@@ -312,7 +313,7 @@
 	   (dma_status & FASTLANE_DMA_CREQ) &&
 #endif
 	   (!(dma_status & FASTLANE_DMA_MINT)) &&
-	   ((((struct ESP_regs *) (esp->eregs))->esp_status) & ESP_STAT_INTR));
+	   (esp_read(((struct ESP_regs *) (esp->eregs))->esp_status) & ESP_STAT_INTR));
 }
 
 static void dma_led_off(struct NCR_ESP *esp)
@@ -342,4 +343,30 @@
 	} else {
 		dma_init_write(esp, addr, count);
 	}
+}
+
+#ifdef MODULE
+
+#define HOSTS_C
+
+#include "fastlane.h"
+
+Scsi_Host_Template driver_template = SCSI_FASTLANE;
+
+#include "scsi_module.c"
+
+#endif
+
+int fastlane_esp_release(struct Scsi_Host *instance)
+{
+#ifdef MODULE
+	unsigned int key;
+
+	key = ((struct NCR_ESP *)instance->hostdata)->slot;
+	esp_deallocate((struct NCR_ESP *)instance->hostdata);
+	esp_release();
+	zorro_unconfig_board(key, 0);
+	free_irq(IRQ_AMIGA_PORTS, esp_intr);
+#endif
+	return 1;
 }
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/fastlane.h linux/drivers/scsi/fastlane.h
--- v2.3.13/linux/drivers/scsi/fastlane.h	Tue Jun 22 14:43:08 1999
+++ linux/drivers/scsi/fastlane.h	Wed Aug 18 10:00:52 1999
@@ -39,6 +39,7 @@
 #define FASTLANE_DMA_ESI   0x01	/* Enable SCSI IRQ */
 
 extern int fastlane_esp_detect(struct SHT *);
+extern int fastlane_esp_release(struct Scsi_Host *);
 extern const char *esp_info(struct Scsi_Host *);
 extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 extern int esp_command(Scsi_Cmnd *);
@@ -48,9 +49,10 @@
 			 int hostno, int inout);
 
 #define SCSI_FASTLANE     { proc_dir:		&proc_scsi_esp, \
+			    proc_info:		esp_proc_info, \
 			    name:		"Fastlane SCSI", \
 			    detect:		fastlane_esp_detect, \
-			    release:		NULL, \
+			    release:		fastlane_esp_release, \
 			    queuecommand:	esp_queue, \
 			    abort:		esp_abort, \
 			    reset:		esp_reset, \
@@ -58,6 +60,6 @@
 			    this_id:		7, \
 			    sg_tablesize:	SG_ALL, \
 			    cmd_per_lun:	1, \
-			    use_clustering:	DISABLE_CLUSTERING }
+			    use_clustering:	ENABLE_CLUSTERING }
 
 #endif /* FASTLANE_H */
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/gvp11.c linux/drivers/scsi/gvp11.c
--- v2.3.13/linux/drivers/scsi/gvp11.c	Sat Apr 11 11:13:25 1998
+++ linux/drivers/scsi/gvp11.c	Wed Aug 18 10:00:52 1999
@@ -34,6 +34,7 @@
 
 static void gvp11_intr (int irq, void *dummy, struct pt_regs *fp)
 {
+    unsigned long flags;
     unsigned int status;
     struct Scsi_Host *instance;
 
@@ -44,23 +45,12 @@
 	if (!(status & GVP11_DMAC_INT_PENDING))
 	    continue;
 
-	/* disable PORTS interrupt */
-	custom.intena = IF_PORTS;
+	spin_lock_irqsave(&io_request_lock, flags);
 	wd33c93_intr (instance);
-	/* enable PORTS interrupt */
-	custom.intena = IF_SETCLR | IF_PORTS;
+	spin_unlock_irqrestore(&io_request_lock, flags);
     }
 }
 
-static void do_gvp11_intr (int irq, void *dummy, struct pt_regs *fp)
-{
-    unsigned long flags;
-
-    spin_lock_irqsave(&io_request_lock, flags);
-    gvp11_intr(irq, dummy, fp);
-    spin_unlock_irqrestore(&io_request_lock, flags);
-}
-
 static int gvp11_xfer_mask = 0;
 
 void gvp11_setup (char *str, int *ints)
@@ -71,20 +61,24 @@
 static int dma_setup (Scsi_Cmnd *cmd, int dir_in)
 {
     unsigned short cntr = GVP11_DMAC_INT_ENABLE;
-    unsigned long addr = VTOP(cmd->SCp.ptr);
+    unsigned long addr = virt_to_bus(cmd->SCp.ptr);
     int bank_mask;
+    static int scsi_alloc_out_of_range = 0;
 
-    /* don't allow DMA if the physical address is bad */
+    /* use bounce buffer if the physical address is bad */
     if (addr & HDATA(cmd->host)->dma_xfer_mask ||
 	(!dir_in && mm_end_of_chunk (addr, cmd->SCp.this_residual)))
     {
 	HDATA(cmd->host)->dma_bounce_len = (cmd->SCp.this_residual + 511)
 	    & ~0x1ff;
-	HDATA(cmd->host)->dma_bounce_buffer =
-	    scsi_malloc (HDATA(cmd->host)->dma_bounce_len);
-	HDATA(cmd->host)->dma_buffer_pool = BUF_SCSI_ALLOCED;
-	
-	if (!HDATA(cmd->host)->dma_bounce_buffer) {
+
+ 	if( !scsi_alloc_out_of_range ) {
+	    HDATA(cmd->host)->dma_bounce_buffer =
+		scsi_malloc (HDATA(cmd->host)->dma_bounce_len);
+	    HDATA(cmd->host)->dma_buffer_pool = BUF_SCSI_ALLOCED;
+	}
+
+	if ( scsi_alloc_out_of_range || !HDATA(cmd->host)->dma_bounce_buffer) {
 	    HDATA(cmd->host)->dma_bounce_buffer =
 		amiga_chip_alloc(HDATA(cmd->host)->dma_bounce_len);
 
@@ -98,15 +92,17 @@
 	}
 
 	/* check if the address of the bounce buffer is OK */
-	addr = VTOP(HDATA(cmd->host)->dma_bounce_buffer);
+	addr = virt_to_bus(HDATA(cmd->host)->dma_bounce_buffer);
 
 	if (addr & HDATA(cmd->host)->dma_xfer_mask) {
 	    /* fall back to Chip RAM if address out of range */
-	    if( HDATA(cmd->host)->dma_buffer_pool == BUF_SCSI_ALLOCED)
+	    if( HDATA(cmd->host)->dma_buffer_pool == BUF_SCSI_ALLOCED) {
 		scsi_free (HDATA(cmd->host)->dma_bounce_buffer,
 			   HDATA(cmd->host)->dma_bounce_len);
-	    else
+		scsi_alloc_out_of_range = 1;
+	    } else {
 		amiga_chip_free (HDATA(cmd->host)->dma_bounce_buffer);
+            }
 		
 	    HDATA(cmd->host)->dma_bounce_buffer =
 		amiga_chip_alloc(HDATA(cmd->host)->dma_bounce_len);
@@ -117,18 +113,14 @@
 		return 1;
 	    }
 
-	    addr = VTOP(HDATA(cmd->host)->dma_bounce_buffer);
+	    addr = virt_to_bus(HDATA(cmd->host)->dma_bounce_buffer);
 	    HDATA(cmd->host)->dma_buffer_pool = BUF_CHIP_ALLOCED;
 	}
 	    
 	if (!dir_in) {
 	    /* copy to bounce buffer for a write */
-	    if (cmd->use_sg)
-		memcpy (HDATA(cmd->host)->dma_bounce_buffer,
-				cmd->SCp.ptr, cmd->SCp.this_residual);
-	    else
-		memcpy (HDATA(cmd->host)->dma_bounce_buffer,
-			cmd->request_buffer, cmd->request_bufflen);
+	    memcpy (HDATA(cmd->host)->dma_bounce_buffer,
+		    cmd->SCp.ptr, cmd->SCp.this_residual);
 	}
     }
 
@@ -169,41 +161,19 @@
 
     /* copy from a bounce buffer, if necessary */
     if (status && HDATA(instance)->dma_bounce_buffer) {
-	if (SCpnt && SCpnt->use_sg) {
-#if 0
-	    panic ("scsi%d: incomplete s/g support",
-		   instance->host_no);
-#else
-	    if( HDATA(instance)->dma_dir )
-		memcpy (SCpnt->SCp.ptr, 
-			HDATA(instance)->dma_bounce_buffer,
-			SCpnt->SCp.this_residual);
-
-	    if (HDATA(instance)->dma_buffer_pool == BUF_SCSI_ALLOCED)
-		scsi_free (HDATA(instance)->dma_bounce_buffer,
-			    HDATA(instance)->dma_bounce_len);
-	    else
-		amiga_chip_free(HDATA(instance)->dma_bounce_buffer);
-
-	    HDATA(instance)->dma_bounce_buffer = NULL;
-	    HDATA(instance)->dma_bounce_len = 0;
-	    
-#endif
-	} else {
-	    if (HDATA(instance)->dma_dir && SCpnt)
-		memcpy (SCpnt->request_buffer,
-			HDATA(instance)->dma_bounce_buffer,
-			SCpnt->request_bufflen);
-
-	    if (HDATA(instance)->dma_buffer_pool == BUF_SCSI_ALLOCED)
-		scsi_free (HDATA(instance)->dma_bounce_buffer,
-			    HDATA(instance)->dma_bounce_len);
-	    else
-		amiga_chip_free(HDATA(instance)->dma_bounce_buffer);
-
-	    HDATA(instance)->dma_bounce_buffer = NULL;
-	    HDATA(instance)->dma_bounce_len = 0;
-	}
+	if (HDATA(instance)->dma_dir && SCpnt)
+	    memcpy (SCpnt->SCp.ptr, 
+		    HDATA(instance)->dma_bounce_buffer,
+		    SCpnt->SCp.this_residual);
+	
+	if (HDATA(instance)->dma_buffer_pool == BUF_SCSI_ALLOCED)
+	    scsi_free (HDATA(instance)->dma_bounce_buffer,
+		       HDATA(instance)->dma_bounce_len);
+	else
+	    amiga_chip_free(HDATA(instance)->dma_bounce_buffer);
+	
+	HDATA(instance)->dma_bounce_buffer = NULL;
+	HDATA(instance)->dma_bounce_len = 0;
     }
 }
 
@@ -211,7 +181,7 @@
 
 #define CHECK_WD33C93
 
-__initfunc(int gvp11_detect(Scsi_Host_Template *tpnt))
+int __init gvp11_detect(Scsi_Host_Template *tpnt)
 {
     static unsigned char called = 0;
     struct Scsi_Host *instance;
@@ -371,7 +341,7 @@
 	if (num_gvp11++ == 0) {
 		first_instance = instance;
 		gvp11_template = instance->hostt;
-		request_irq(IRQ_AMIGA_PORTS, do_gvp11_intr, 0,
+		request_irq(IRQ_AMIGA_PORTS, gvp11_intr, SA_SHIRQ,
 			    "GVP11 SCSI", gvp11_intr);
 	}
 	DMA(instance)->CNTR = GVP11_DMAC_INT_ENABLE;
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c
--- v2.3.13/linux/drivers/scsi/hosts.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/scsi/hosts.c	Wed Aug 18 10:00:52 1999
@@ -47,7 +47,7 @@
     defined(CONFIG_WARPENGINE_SCSI) || \
     defined(CONFIG_A4091_SCSI) || \
     defined (CONFIG_GVP_TURBO_SCSI) || \
-    defined (CONFIG_BLZ603E)
+    defined (CONFIG_BLZ603EPLUS_SCSI)
 #define AMIGA7XXCONFIG
 #endif
 
@@ -95,6 +95,10 @@
 #include "fastlane.h"
 #endif
 
+#ifdef CONFIG_OKTAGON_SCSI
+#include "oktagon_esp.h"
+#endif
+
 #ifdef CONFIG_ATARI_SCSI
 #include "atari_scsi.h"
 #endif
@@ -327,6 +331,10 @@
 #include "jazz_esp.h"
 #endif
 
+#ifdef CONFIG_SUN3X_ESP
+#include "sun3x_esp.h"
+#endif
+
 /*
  * Moved ppa driver to the end of the probe list
  * since it is a removable host adapter.
@@ -402,6 +410,9 @@
 #ifdef CONFIG_FASTLANE_SCSI
 	SCSI_FASTLANE,
 #endif
+#ifdef CONFIG_OKTAGON_SCSI
+	SCSI_OKTAGON_ESP,
+#endif
 #endif
 
 #ifdef CONFIG_ATARI
@@ -596,6 +607,9 @@
 #ifdef CONFIG_SCSI_IMM
     IMM,
 #endif
+#ifdef CONFIG_SUN3X_ESP  
+    SCSI_SUN3X_ESP,
+#endif  
 #ifdef CONFIG_SCSI_DEBUG
     SCSI_DEBUG,
 #endif
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/jazz_esp.c linux/drivers/scsi/jazz_esp.c
--- v2.3.13/linux/drivers/scsi/jazz_esp.c	Tue Aug  4 16:56:37 1998
+++ linux/drivers/scsi/jazz_esp.c	Wed Aug 18 10:00:52 1999
@@ -196,7 +196,7 @@
 
 static int dma_irq_p(struct NCR_ESP *esp)
 {
-    return (esp->eregs->esp_status & ESP_STAT_INTR);
+    return (esp_read(esp->eregs->esp_status) & ESP_STAT_INTR);
 }
 
 static int dma_ports_p(struct NCR_ESP *esp)
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/mac_NCR5380.c linux/drivers/scsi/mac_NCR5380.c
--- v2.3.13/linux/drivers/scsi/mac_NCR5380.c	Fri Jan 15 14:41:04 1999
+++ linux/drivers/scsi/mac_NCR5380.c	Wed Aug 18 10:00:52 1999
@@ -490,9 +490,9 @@
     int		  cnt = 1;
 #endif
 
-    for (endaddr = VTOP(cmd->SCp.ptr + cmd->SCp.this_residual - 1) + 1;
+    for (endaddr = virt_to_phys(cmd->SCp.ptr + cmd->SCp.this_residual - 1) + 1;
 	 cmd->SCp.buffers_residual &&
-	 VTOP(cmd->SCp.buffer[1].address) == endaddr; ) {
+	 virt_to_phys(cmd->SCp.buffer[1].address) == endaddr; ) {
 	
 	MER_PRINTK("VTOP(%p) == %08lx -> merging\n",
 		   cmd->SCp.buffer[1].address, endaddr);
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/mac_esp.c linux/drivers/scsi/mac_esp.c
--- v2.3.13/linux/drivers/scsi/mac_esp.c	Fri Dec 18 10:12:25 1998
+++ linux/drivers/scsi/mac_esp.c	Wed Aug 18 10:00:52 1999
@@ -59,10 +59,15 @@
 static void dma_setup(struct NCR_ESP * esp, __u32 addr, int count, int write);
 static void dma_setup_quick(struct NCR_ESP * esp, __u32 addr, int count, int write);
 
-
 static int esp_dafb_dma_irq_p(struct NCR_ESP * espdev);
 static int esp_iosb_dma_irq_p(struct NCR_ESP * espdev);
 
+volatile unsigned char cmd_buffer[16];
+				/* This is where all commands are put
+				 * before they are transfered to the ESP chip
+				 * via PIO.
+				 */
+
 static int esp_initialized = 0;
 
 static int setup_num_esps = -1;
@@ -287,6 +292,9 @@
 	unsigned long timeout;
 #endif
 
+	if (esp_initialized > 0)
+		return -ENODEV;
+
 	/* what do we have in this machine... */
 	if (MACHW_PRESENT(MAC_SCSI_96)) {
 		chipspresent ++;
@@ -358,10 +366,13 @@
 
 		} /* chipnum == 0 */
 
-
 		/* use pio for command bytes; pio for message/data: TBI */
 		esp->do_pio_cmds = 1;
 
+		/* Set the command buffer */
+		esp->esp_command = (volatile unsigned char*) cmd_buffer;
+		esp->esp_command_dvma = (volatile unsigned char*) cmd_buffer;
+
 		/* various functions */
 		esp->dma_bytes_sent = &dma_bytes_sent;
 		esp->dma_can_transfer = &dma_can_transfer;
@@ -469,7 +480,7 @@
 static int esp_dafb_dma_irq_p(struct NCR_ESP * esp)
 {
 	unsigned int ret;
-	int sreg = esp->eregs->esp_status;
+	int sreg = esp_read(esp->eregs->esp_status);
 
 #ifdef DEBUG_MAC_ESP
 	printk("mac_esp: esp_dafb_dma_irq_p dafb %d irq %d\n", 
@@ -510,7 +521,7 @@
 static int esp_iosb_dma_irq_p(struct NCR_ESP * esp)
 {
 	int ret  = mac_irq_pending(IRQ_MAC_SCSI) || mac_irq_pending(IRQ_MAC_SCSIDRQ);
-	int sreg = esp->eregs->esp_status;
+	int sreg = esp_read(esp->eregs->esp_status);
 
 #ifdef DEBUG_MAC_ESP
 	printk("mac_esp: dma_irq_p drq %d irq %d sreg %x curr %p disc %p\n", 
@@ -614,7 +625,7 @@
 
 static int dma_irq_p(struct NCR_ESP * esp)
 {
-	int i = esp->eregs->esp_status;
+	int i = esp_read(esp->eregs->esp_status);
 
 #ifdef DEBUG_MAC_ESP
 	printk("mac_esp: dma_irq_p status %d\n", i);
@@ -629,7 +640,7 @@
 	 * Copied from iosb_dma_irq_p()
 	 */
 	int ret  = mac_irq_pending(IRQ_MAC_SCSI) || mac_irq_pending(IRQ_MAC_SCSIDRQ);
-	int sreg = esp->eregs->esp_status;
+	int sreg = esp_read(esp->eregs->esp_status);
 
 #ifdef DEBUG_MAC_ESP
 	printk("mac_esp: dma_irq_p drq %d irq %d sreg %x curr %p disc %p\n", 
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/mac_scsi.c linux/drivers/scsi/mac_scsi.c
--- v2.3.13/linux/drivers/scsi/mac_scsi.c	Fri Jan 15 14:41:04 1999
+++ linux/drivers/scsi/mac_scsi.c	Wed Aug 18 10:00:52 1999
@@ -685,7 +685,7 @@
 unsigned long mac_scsi_dma_setup( struct Scsi_Host *instance, void *data,
 				   unsigned long count, int dir )
 {
-	unsigned long addr = VTOP( data );
+	unsigned long addr = virt_to_phys( data );
 
 	DMA_PRINTK("scsi%d: setting up dma, data = %p, phys = %lx, count = %ld, "
 		   "dir = %d\n", instance->host_no, data, addr, count, dir);
@@ -846,7 +846,7 @@
 	}
 
 	/* Last step: apply the hard limit on DMA transfers */
-	limit = (atari_dma_buffer && !STRAM_ADDR( VTOP(cmd->SCp.ptr) )) ?
+	limit = (atari_dma_buffer && !STRAM_ADDR( virt_to_phys(cmd->SCp.ptr) )) ?
 		    STRAM_BUFFER_SIZE : 255*512;
 	if (possible_len > limit)
 		possible_len = limit;
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/mca_53c9x.c linux/drivers/scsi/mca_53c9x.c
--- v2.3.13/linux/drivers/scsi/mca_53c9x.c	Fri Dec 18 10:12:25 1998
+++ linux/drivers/scsi/mca_53c9x.c	Wed Aug 18 10:00:52 1999
@@ -156,6 +156,8 @@
 			 "NCR 53c9x SCSI", esp_intr))
 			{
 				printk("Unable to request IRQ %d.\n", esp->irq);
+				esp_deallocate(esp);
+				unregister_scsi(esp->ehost);
 				return 0;
 			}
 
@@ -163,6 +165,8 @@
 				printk("Unable to request DMA channel %d.\n",
 				 esp->dma);
 				free_irq(esp->irq, esp_intr);
+				esp_deallocate(esp);
+				unregister_scsi(esp->ehost);
 				return 0;
 			}
 
@@ -259,7 +263,7 @@
 	struct NCR_ESP *esp = (struct NCR_ESP *)host->hostdata;
 	unsigned char tmp_byte;
 
-
+	esp_deallocate(esp);
 	/*
 	 * Tell the 86C01 to stop sending interrupts
 	 */
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/ncr53c8xx.c linux/drivers/scsi/ncr53c8xx.c
--- v2.3.13/linux/drivers/scsi/ncr53c8xx.c	Thu Jul  8 15:42:21 1999
+++ linux/drivers/scsi/ncr53c8xx.c	Mon Aug 16 10:33:58 1999
@@ -588,9 +588,7 @@
 #endif
 
 #if defined(__i386__) || !defined(NCR_IOMAPPED)
-__initfunc(
-static vm_offset_t remap_pci_mem(u_long base, u_long size)
-)
+static vm_offset_t __init remap_pci_mem(u_long base, u_long size)
 {
 	u_long page_base	= ((u_long) base) & PAGE_MASK;
 	u_long page_offs	= ((u_long) base) - page_base;
@@ -599,9 +597,7 @@
 	return (vm_offset_t) (page_remapped? (page_remapped + page_offs) : 0UL);
 }
 
-__initfunc(
-static void unmap_pci_mem(vm_offset_t vaddr, u_long size)
-)
+static void __init unmap_pci_mem(vm_offset_t vaddr, u_long size)
 {
 	if (vaddr)
 		iounmap((void *) (vaddr & PAGE_MASK));
@@ -3701,9 +3697,7 @@
 **==========================================================
 */
 
-__initfunc(
-void ncr_script_fill (struct script * scr, struct scripth * scrh)
-)
+void __init ncr_script_fill (struct script * scr, struct scripth * scrh)
 {
 	int	i;
 	ncrcmd	*p;
@@ -3778,9 +3772,7 @@
 **==========================================================
 */
 
-__initfunc(
-static void ncr_script_copy_and_bind (ncb_p np, ncrcmd *src, ncrcmd *dst, int len)
-)
+static void __init ncr_script_copy_and_bind (ncb_p np, ncrcmd *src, ncrcmd *dst, int len)
 {
 	ncrcmd  opcode, new, old, tmp1, tmp2;
 	ncrcmd	*start, *end;
@@ -4036,10 +4028,8 @@
 **	Get target set-up from Symbios format NVRAM.
 */
 
-__initfunc(
-static void
-	ncr_Symbios_setup_target(ncb_p np, int target, Symbios_nvram *nvram)
-)
+static void __init 
+ncr_Symbios_setup_target(ncb_p np, int target, Symbios_nvram *nvram)
 {
 	tcb_p tp = &np->target[target];
 	Symbios_target *tn = &nvram->target[target];
@@ -4059,10 +4049,8 @@
 **	Get target set-up from Tekram format NVRAM.
 */
 
-__initfunc(
-static void
-	ncr_Tekram_setup_target(ncb_p np, int target, Tekram_nvram *nvram)
-)
+static void __init 
+ncr_Tekram_setup_target(ncb_p np, int target, Tekram_nvram *nvram)
 {
 	tcb_p tp = &np->target[target];
 	struct Tekram_target *tn = &nvram->target[target];
@@ -4088,9 +4076,7 @@
 }
 #endif /* SCSI_NCR_NVRAM_SUPPORT */
 
-__initfunc(
-static int ncr_prepare_setting(ncb_p np, ncr_nvram *nvram)
-)
+static int __init ncr_prepare_setting(ncb_p np, ncr_nvram *nvram)
 {
 	u_char	burst_max;
 	u_long	period;
@@ -4372,9 +4358,7 @@
 
 #ifdef SCSI_NCR_DEBUG_NVRAM
 
-__initfunc(
-void ncr_display_Symbios_nvram(ncb_p np, Symbios_nvram *nvram)
-)
+void __init ncr_display_Symbios_nvram(ncb_p np, Symbios_nvram *nvram)
 {
 	int i;
 
@@ -4404,9 +4388,7 @@
 
 static u_char Tekram_boot_delay[7] __initdata = {3, 5, 10, 20, 30, 60, 120};
 
-__initfunc(
-void ncr_display_Tekram_nvram(ncb_p np, Tekram_nvram *nvram)
-)
+void __init ncr_display_Tekram_nvram(ncb_p np, Tekram_nvram *nvram)
 {
 	int i, tags, boot_delay;
 	char *rem;
@@ -4465,9 +4447,8 @@
 **	start the timer daemon.
 */
 
-__initfunc(
-static int ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device)
-)
+static int __init 
+ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device)
 {
         struct host_data *host_data;
 	ncb_p np;
@@ -8807,9 +8788,7 @@
 */
 
 #ifndef NCR_IOMAPPED
-__initfunc(
-static int ncr_regtest (struct ncb* np)
-)
+static int __init ncr_regtest (struct ncb* np)
 {
 	register volatile u_int32 data;
 	/*
@@ -8833,9 +8812,7 @@
 }
 #endif
 
-__initfunc(
-static int ncr_snooptest (struct ncb* np)
-)
+static int __init ncr_snooptest (struct ncb* np)
 {
 	u_int32	ncr_rd, ncr_wr, ncr_bk, host_rd, host_wr, pc;
 	int	i, err=0;
@@ -9098,9 +9075,7 @@
 /*
  *	calculate NCR SCSI clock frequency (in KHz)
  */
-__initfunc(
-static unsigned ncrgetfreq (ncb_p np, int gen)
-)
+static unsigned __init ncrgetfreq (ncb_p np, int gen)
 {
 	unsigned ms = 0;
 
@@ -9148,9 +9123,7 @@
 /*
  *	Get/probe NCR SCSI clock frequency
  */
-__initfunc(
-static void ncr_getclock (ncb_p np, int mult)
-)
+static void __init ncr_getclock (ncb_p np, int mult)
 {
 	unsigned char scntl3 = INB(nc_scntl3);
 	unsigned char stest1 = INB(nc_stest1);
@@ -9238,9 +9211,8 @@
 #define	ARG_SEP	','
 #endif
 
-__initfunc(
-void ncr53c8xx_setup(char *str, int *ints)
-)
+
+void __init ncr53c8xx_setup(char *str, int *ints)
 {
 #ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
 	char *cur = str;
@@ -9351,9 +9323,7 @@
 **   Returns the number of boards successfully attached.
 */
 
-__initfunc(
-static void ncr_print_driver_setup(void)
-)
+static void __init ncr_print_driver_setup(void)
 {
 #define YesNo(y)	y ? 'y' : 'n'
 	printk ("ncr53c8xx: setup=disc:%c,specf:%d,ultra:%d,tags:%d,sync:%d,"
@@ -9392,10 +9362,8 @@
 static ushort	ncr_chip_ids[]   __initdata	= SCSI_NCR_CHIP_IDS;
 
 #ifdef SCSI_NCR_NVRAM_SUPPORT
-__initfunc(
-static int
+static int __init 
 ncr_attach_using_nvram(Scsi_Host_Template *tpnt, int nvram_index, int count, ncr_device device[])
-)
 {
 	int i, j;
 	int attach_count = 0;
@@ -9476,9 +9444,7 @@
 }
 #endif /* SCSI_NCR_NVRAM_SUPPORT */
 
-__initfunc(
-int ncr53c8xx_detect(Scsi_Host_Template *tpnt)
-)
+int __init ncr53c8xx_detect(Scsi_Host_Template *tpnt)
 {
 	int i, j;
 	int chips;
@@ -9605,44 +9571,16 @@
 **   Return the offset immediately after the base address that has 
 **   been read. Btw, we blindly assume that the high 32 bits of 64 bit 
 **   base addresses are set to zero on 32 bit architectures.
+**   (the pci generic code now does this for us)
 **
 */
-#if LINUX_VERSION_CODE <= LinuxVersionCode(2,1,92)
-__initfunc(
-static int 
-pci_read_base_address(u_char bus, u_char device_fn, int offset, u_long *base)
-)
-{
-	u_int32 tmp;
-
-	pcibios_read_config_dword(bus, device_fn, offset, &tmp);
-	*base = tmp;
-	offset += sizeof(u_int32);
-	if ((tmp & 0x7) == 0x4) {
-#if BITS_PER_LONG > 32
-		pcibios_read_config_dword(bus, device_fn, offset, &tmp);
-		*base |= (((u_long)tmp) << 32);
-#endif
-		offset += sizeof(u_int32);
-	}
-	return offset;
-}
-#else	/* LINUX_VERSION_CODE > LinuxVersionCode(2,1,92) */
-__initfunc(
-static int 
+
+static int __init 
 pci_get_base_address(struct pci_dev *pdev, int index, u_long *base)
-)
 {
-	*base = pdev->base_address[index++];
-	if ((*base & 0x7) == 0x4) {
-#if BITS_PER_LONG > 32
-		*base |= (((u_long)pdev->base_address[index]) << 32);
-#endif
-		++index;
-	}
+	*base = pdev->resource[++index].start;
 	return index;
 }
-#endif
 
 /*
 **   Read and check the PCI configuration for any detected NCR 
@@ -9650,10 +9588,9 @@
 **   been detected.
 */
 
-__initfunc(
-static int ncr53c8xx_pci_init(Scsi_Host_Template *tpnt,
+
+static int __init ncr53c8xx_pci_init(Scsi_Host_Template *tpnt,
 			      uchar bus, uchar device_fn, ncr_device *device)
-)
 {
 	ushort vendor_id, device_id, command;
 	uchar cache_line_size, latency_timer;
@@ -10907,9 +10844,7 @@
 static void nvram_stop(ncr_slot *np, u_char *gpreg);
 static void nvram_setBit(ncr_slot *np, u_char write_bit, u_char *gpreg, int bit_mode);
 
-__initfunc(
-static int ncr_get_Symbios_nvram (ncr_slot *np, Symbios_nvram *nvram)
-)
+static int __init ncr_get_Symbios_nvram (ncr_slot *np, Symbios_nvram *nvram)
 {
 	static u_char Symbios_trailer[6] = {0xfe, 0xfe, 0, 0, 0, 0};
 	u_char	gpcntl, gpreg;
@@ -10998,9 +10933,8 @@
 /*
  * Read Symbios NvRAM data and compute checksum.
  */
-__initfunc(
-static u_short nvram_read_data(ncr_slot *np, u_char *data, int len, u_char *gpreg, u_char *gpcntl)
-)
+static u_short __init nvram_read_data(ncr_slot *np, u_char *data, int len,
+				      u_char *gpreg, u_char *gpcntl)
 {
 	int	x;
 	u_short	csum;
@@ -11017,9 +10951,7 @@
 /*
  * Send START condition to NVRAM to wake it up.
  */
-__initfunc(
-static void nvram_start(ncr_slot *np, u_char *gpreg)
-)
+static void __init nvram_start(ncr_slot *np, u_char *gpreg)
 {
 	nvram_setBit(np, 1, gpreg, SET_BIT);
 	nvram_setBit(np, 0, gpreg, SET_CLK);
@@ -11031,9 +10963,9 @@
  * WRITE a byte to the NVRAM and then get an ACK to see it was accepted OK,
  * GPIO0 must already be set as an output
  */
-__initfunc(
-static void nvram_write_byte(ncr_slot *np, u_char *ack_data, u_char write_data, u_char *gpreg, u_char *gpcntl)
-)
+static void __init nvram_write_byte(ncr_slot *np, u_char *ack_data,
+				    u_char write_data, u_char *gpreg,
+				    u_char *gpcntl)
 {
 	int x;
 	
@@ -11047,9 +10979,9 @@
  * READ a byte from the NVRAM and then send an ACK to say we have got it,
  * GPIO0 must already be set as an input
  */
-__initfunc(
-static void nvram_read_byte(ncr_slot *np, u_char *read_data, u_char ack_data, u_char *gpreg, u_char *gpcntl)
-)
+static void __init nvram_read_byte(ncr_slot *np, u_char *read_data,
+				   u_char ack_data, u_char *gpreg,
+				   u_char *gpcntl)
 {
 	int x;
 	u_char read_bit;
@@ -11067,9 +10999,8 @@
  * Output an ACK to the NVRAM after reading,
  * change GPIO0 to output and when done back to an input
  */
-__initfunc(
-static void nvram_writeAck(ncr_slot *np, u_char write_bit, u_char *gpreg, u_char *gpcntl)
-)
+static void __init nvram_writeAck(ncr_slot *np, u_char write_bit,
+				  u_char *gpreg, u_char *gpcntl)
 {
 	OUTB (nc_gpcntl, *gpcntl & 0xfe);
 	nvram_doBit(np, 0, write_bit, gpreg);
@@ -11080,9 +11011,8 @@
  * Input an ACK from NVRAM after writing,
  * change GPIO0 to input and when done back to an output
  */
-__initfunc(
-static void nvram_readAck(ncr_slot *np, u_char *read_bit, u_char *gpreg, u_char *gpcntl)
-)
+static void __init nvram_readAck(ncr_slot *np, u_char *read_bit,
+				 u_char *gpreg, u_char *gpcntl)
 {
 	OUTB (nc_gpcntl, *gpcntl | 0x01);
 	nvram_doBit(np, read_bit, 1, gpreg);
@@ -11093,9 +11023,8 @@
  * Read or write a bit to the NVRAM,
  * read if GPIO0 input else write if GPIO0 output
  */
-__initfunc(
-static void nvram_doBit(ncr_slot *np, u_char *read_bit, u_char write_bit, u_char *gpreg)
-)
+static void __init nvram_doBit(ncr_slot *np, u_char *read_bit,
+			       u_char write_bit, u_char *gpreg)
 {
 	nvram_setBit(np, write_bit, gpreg, SET_BIT);
 	nvram_setBit(np, 0, gpreg, SET_CLK);
@@ -11108,9 +11037,7 @@
 /*
  * Send STOP condition to NVRAM - puts NVRAM to sleep... ZZzzzz!!
  */
-__initfunc(
-static void nvram_stop(ncr_slot *np, u_char *gpreg)
-)
+static void __init nvram_stop(ncr_slot *np, u_char *gpreg)
 {
 	nvram_setBit(np, 0, gpreg, SET_CLK);
 	nvram_setBit(np, 1, gpreg, SET_BIT);
@@ -11119,9 +11046,8 @@
 /*
  * Set/clear data/clock bit in GPIO0
  */
-__initfunc(
-static void nvram_setBit(ncr_slot *np, u_char write_bit, u_char *gpreg, int bit_mode)
-)
+static void __init nvram_setBit(ncr_slot *np, u_char write_bit,
+				u_char *gpreg, int bit_mode)
 {
 	UDELAY (5);
 	switch (bit_mode){
@@ -11172,9 +11098,7 @@
 static void Tnvram_Stop(ncr_slot *np, u_char *gpreg);
 static void Tnvram_Clk(ncr_slot *np, u_char *gpreg);
 
-__initfunc(
-static int ncr_get_Tekram_nvram (ncr_slot *np, Tekram_nvram *nvram)
-)
+static int __init ncr_get_Tekram_nvram (ncr_slot *np, Tekram_nvram *nvram)
 {
 	u_char gpcntl, gpreg;
 	u_char old_gpcntl, old_gpreg;
@@ -11209,9 +11133,8 @@
 /*
  * Read Tekram NvRAM data and compute checksum.
  */
-__initfunc(
-static u_short Tnvram_read_data(ncr_slot *np, u_short *data, int len, u_char *gpreg)
-)
+static u_short __init Tnvram_read_data(ncr_slot *np, u_short *data, int len,
+				       u_char *gpreg)
 {
 	u_char	read_bit;
 	u_short	csum;
@@ -11236,9 +11159,8 @@
 /*
  * Send read command and address to NVRAM
  */
-__initfunc(
-static void Tnvram_Send_Command(ncr_slot *np, u_short write_data, u_char *read_bit, u_char *gpreg)
-)
+static void __init Tnvram_Send_Command(ncr_slot *np, u_short write_data,
+				       u_char *read_bit, u_char *gpreg)
 {
 	int x;
 
@@ -11252,9 +11174,8 @@
 /*
  * READ a byte from the NVRAM
  */
-__initfunc(
-static void Tnvram_Read_Word(ncr_slot *np, u_short *nvram_data, u_char *gpreg)
-)
+static void __init Tnvram_Read_Word(ncr_slot *np, u_short *nvram_data, 
+				    u_char *gpreg)
 {
 	int x;
 	u_char read_bit;
@@ -11273,9 +11194,8 @@
 /* 
  * Read bit from NVRAM
  */
-__initfunc(
-static void Tnvram_Read_Bit(ncr_slot *np, u_char *read_bit, u_char *gpreg)
-)
+static void __init Tnvram_Read_Bit(ncr_slot *np, u_char *read_bit,
+				   u_char *gpreg)
 {
 	UDELAY (2);
 	Tnvram_Clk(np, gpreg);
@@ -11285,9 +11205,8 @@
 /*
  * Write bit to GPIO0
  */
-__initfunc(
-static void Tnvram_Write_Bit(ncr_slot *np, u_char write_bit, u_char *gpreg)
-)
+static void __init Tnvram_Write_Bit(ncr_slot *np, u_char write_bit,
+				    u_char *gpreg)
 {
 	if (write_bit & 0x01)
 		*gpreg |= 0x02;
@@ -11305,9 +11224,7 @@
 /*
  * Send STOP condition to NVRAM - puts NVRAM to sleep... ZZZzzz!!
  */
-__initfunc(
-static void Tnvram_Stop(ncr_slot *np, u_char *gpreg)
-)
+static void __init Tnvram_Stop(ncr_slot *np, u_char *gpreg)
 {
 	*gpreg &= 0xef;
 	OUTB (nc_gpreg, *gpreg);
@@ -11319,9 +11236,7 @@
 /*
  * Pulse clock bit in GPIO0
  */
-__initfunc(
-static void Tnvram_Clk(ncr_slot *np, u_char *gpreg)
-)
+static void __init Tnvram_Clk(ncr_slot *np, u_char *gpreg)
 {
 	OUTB (nc_gpreg, *gpreg | 0x04);
 	UDELAY (2);
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/oktagon_esp.c linux/drivers/scsi/oktagon_esp.c
--- v2.3.13/linux/drivers/scsi/oktagon_esp.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/oktagon_esp.c	Sun Aug 15 11:49:08 1999
@@ -0,0 +1,597 @@
+/*
+ * Oktagon_esp.c -- Driver for bsc Oktagon
+ *
+ * Written by Carsten Pluntke 1998
+ *
+ * Based on cyber_esp.c
+ */
+
+#include <linux/config.h>
+
+#if defined(CONFIG_AMIGA) || defined(CONFIG_APUS)
+#define USE_BOTTOM_HALF
+#endif
+
+#define __KERNEL_SYSCALLS__
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/malloc.h>
+#include <linux/blk.h>
+#include <linux/proc_fs.h>
+#include <linux/stat.h>
+#include <linux/reboot.h>
+#include <asm/system.h>
+#include <asm/ptrace.h>
+#include <asm/pgtable.h>
+#include <asm/io.h>
+
+#include "scsi.h"
+#include "hosts.h"
+#include "NCR53C9x.h"
+#include "oktagon_esp.h"
+
+#include <linux/zorro.h>
+#include <asm/irq.h>
+#include <asm/amigaints.h>
+#include <asm/amigahw.h>
+
+#ifdef USE_BOTTOM_HALF
+#include <linux/tqueue.h>
+#include <linux/interrupt.h>
+#endif
+
+#include <linux/unistd.h>
+
+static int  dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
+static int  dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp);
+static void dma_dump_state(struct NCR_ESP *esp);
+static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length);
+static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length);
+static void dma_ints_off(struct NCR_ESP *esp);
+static void dma_ints_on(struct NCR_ESP *esp);
+static int  dma_irq_p(struct NCR_ESP *esp);
+static void dma_led_off(struct NCR_ESP *esp);
+static void dma_led_on(struct NCR_ESP *esp);
+static int  dma_ports_p(struct NCR_ESP *esp);
+static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
+
+static void dma_irq_exit(struct NCR_ESP *esp);
+static void dma_invalidate(struct NCR_ESP *esp);
+
+static void dma_mmu_get_scsi_one(struct NCR_ESP *,Scsi_Cmnd *);
+static void dma_mmu_get_scsi_sgl(struct NCR_ESP *,Scsi_Cmnd *);
+static void dma_mmu_release_scsi_one(struct NCR_ESP *,Scsi_Cmnd *);
+static void dma_mmu_release_scsi_sgl(struct NCR_ESP *,Scsi_Cmnd *);
+static void dma_advance_sg(Scsi_Cmnd *);
+static int  oktagon_notify_reboot(struct notifier_block *this, unsigned long code, void *x);
+
+void esp_bootup_reset(struct NCR_ESP *esp,struct ESP_regs *eregs);
+
+#ifdef USE_BOTTOM_HALF
+static void dma_commit(void *opaque);
+
+long oktag_to_io(long *paddr, long *addr, long len);
+long oktag_from_io(long *addr, long *paddr, long len);
+
+static struct tq_struct tq_fake_dma = { NULL, 0, dma_commit, NULL };
+
+#define DMA_MAXTRANSFER 0x8000
+
+#else
+
+/*
+ * No bottom half. Use transfer directly from IRQ. Find a narrow path
+ * between too much IRQ overhead and clogging the IRQ for too long.
+ */
+
+#define DMA_MAXTRANSFER 0x1000
+
+#endif
+
+static struct notifier_block oktagon_notifier = { 
+	oktagon_notify_reboot,
+	NULL,
+	0
+};
+
+static long *paddress;
+static long *address;
+static long len;
+static long dma_on;
+static int direction;
+static struct NCR_ESP *current_esp;
+
+
+volatile unsigned char cmd_buffer[16];
+				/* This is where all commands are put
+				 * before they are trasfered to the ESP chip
+				 * via PIO.
+				 */
+
+/***************************************************************** Detection */
+int oktagon_esp_detect(Scsi_Host_Template *tpnt)
+{
+	struct NCR_ESP *esp;
+	const struct ConfigDev *esp_dev;
+	int key;
+	unsigned long address;
+	struct ESP_regs *eregs;
+
+	if((key = zorro_find(ZORRO_PROD_BSC_OKTAGON_2008, 0, 0))){
+		esp_dev = zorro_get_board(key);
+
+		/*
+		 * It is a SCSI controller.
+		 * Hardwire Host adapter to SCSI ID 7
+		 */
+		
+		address = (unsigned long)ZTWO_VADDR(esp_dev->cd_BoardAddr);
+		eregs = (struct ESP_regs *)(address + OKTAGON_ESP_ADDR);
+
+		/* This line was 5 lines lower */
+		esp = esp_allocate(tpnt, (void *) esp_dev);
+
+		/* we have to shift the registers only one bit for oktagon */
+		esp->shift = 1;
+
+		esp_write(eregs->esp_cfg1, (ESP_CONFIG1_PENABLE | 7));
+		udelay(5);
+		if (esp_read(eregs->esp_cfg1) != (ESP_CONFIG1_PENABLE | 7))
+			return 0; /* Bail out if address did not hold data */
+
+		/* Do command transfer with programmed I/O */
+		esp->do_pio_cmds = 1;
+
+		/* Required functions */
+		esp->dma_bytes_sent = &dma_bytes_sent;
+		esp->dma_can_transfer = &dma_can_transfer;
+		esp->dma_dump_state = &dma_dump_state;
+		esp->dma_init_read = &dma_init_read;
+		esp->dma_init_write = &dma_init_write;
+		esp->dma_ints_off = &dma_ints_off;
+		esp->dma_ints_on = &dma_ints_on;
+		esp->dma_irq_p = &dma_irq_p;
+		esp->dma_ports_p = &dma_ports_p;
+		esp->dma_setup = &dma_setup;
+
+		/* Optional functions */
+		esp->dma_barrier = 0;
+		esp->dma_drain = 0;
+		esp->dma_invalidate = &dma_invalidate;
+		esp->dma_irq_entry = 0;
+		esp->dma_irq_exit = &dma_irq_exit;
+		esp->dma_led_on = &dma_led_on;
+		esp->dma_led_off = &dma_led_off;
+		esp->dma_poll = 0;
+		esp->dma_reset = 0;
+
+		esp->dma_mmu_get_scsi_one = &dma_mmu_get_scsi_one;
+		esp->dma_mmu_get_scsi_sgl = &dma_mmu_get_scsi_sgl;
+		esp->dma_mmu_release_scsi_one = &dma_mmu_release_scsi_one;
+		esp->dma_mmu_release_scsi_sgl = &dma_mmu_release_scsi_sgl;
+		esp->dma_advance_sg = &dma_advance_sg;
+
+		/* SCSI chip speed */
+		/* Looking at the quartz of the SCSI board... */
+		esp->cfreq = 25000000;
+
+		/* The DMA registers on the CyberStorm are mapped
+		 * relative to the device (i.e. in the same Zorro
+		 * I/O block).
+		 */
+		esp->dregs = (void *)(address + OKTAGON_DMA_ADDR);
+
+		paddress = (long *) esp->dregs;
+
+		/* ESP register base */
+		esp->eregs = eregs;
+		
+		/* Set the command buffer */
+		esp->esp_command = (volatile unsigned char*) cmd_buffer;
+
+		/* Yes, the virtual address. See below. */
+		esp->esp_command_dvma = (__u32) cmd_buffer;
+
+		esp->irq = IRQ_AMIGA_PORTS;
+		esp->slot = key;
+		request_irq(IRQ_AMIGA_PORTS, esp_intr, SA_SHIRQ,
+			    "BSC Oktagon SCSI", esp_intr);
+
+		/* Figure out our scsi ID on the bus */
+		esp->scsi_id = 7;
+		
+		/* We don't have a differential SCSI-bus. */
+		esp->diff = 0;
+
+		esp_initialize(esp);
+
+		zorro_config_board(key, 0);
+		printk("ESP_Oktagon Driver 1.1"
+#ifdef USE_BOTTOM_HALF
+		       " [BOTTOM_HALF]"
+#else
+		       " [IRQ]"
+#endif
+		       " registered.\n");
+		printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps,esps_in_use);
+		esps_running = esps_in_use;
+		current_esp = esp;
+		register_reboot_notifier(&oktagon_notifier);
+		return esps_in_use;
+	}
+	return 0;
+}
+
+
+/*
+ * On certain configurations the SCSI equipment gets confused on reboot,
+ * so we have to reset it then.
+ */
+
+static int
+oktagon_notify_reboot(struct notifier_block *this, unsigned long code, void *x)
+{
+  struct NCR_ESP *esp;
+  
+  if((code == SYS_DOWN || code == SYS_HALT) && (esp = current_esp))
+   {
+    esp_bootup_reset(esp,esp->eregs);
+    udelay(500); /* Settle time. Maybe unneccessary. */
+   }
+  return NOTIFY_DONE;
+}
+    
+
+	
+#ifdef USE_BOTTOM_HALF
+
+
+/*
+ * The bsc Oktagon controller has no real DMA, so we have to do the 'DMA
+ * transfer' in the interrupt (Yikes!) or use a bottom half to not to clutter
+ * IRQ's for longer-than-good.
+ *
+ * FIXME
+ * BIG PROBLEM: 'len' is usually the buffer length, not the expected length
+ * of the data. So DMA may finish prematurely, further reads lead to
+ * 'machine check' on APUS systems (don't know about m68k systems, AmigaOS
+ * deliberately ignores the bus faults) and a normal copy-loop can't
+ * be exited prematurely just at the right moment by the dma_invalidate IRQ.
+ * So do it the hard way, write an own copier in assembler and
+ * catch the exception.
+ *                                     -- Carsten
+ */
+ 
+ 
+static void dma_commit(void *opaque)
+{
+    long wait,len2,pos;
+    struct NCR_ESP *esp;
+
+    ESPDATA(("Transfer: %ld bytes, Address 0x%08lX, Direction: %d\n",
+         len,(long) address,direction));
+    dma_ints_off(current_esp);
+
+    pos = 0;
+    wait = 1;
+    if(direction) /* write? (memory to device) */
+     {
+      while(len > 0)
+       {
+        len2 = oktag_to_io(paddress, address+pos, len);
+	if(!len2)
+	 {
+	  if(wait > 1000)
+	   {
+	    printk("Expedited DMA exit (writing) %ld\n",len);
+	    break;
+	   }
+	  mdelay(wait);
+	  wait *= 2;
+	 }
+	pos += len2;
+	len -= len2*sizeof(long);
+       }
+     } else {
+      while(len > 0)
+       {
+        len2 = oktag_from_io(address+pos, paddress, len);
+	if(!len2)
+	 {
+	  if(wait > 1000)
+	   {
+	    printk("Expedited DMA exit (reading) %ld\n",len);
+	    break;
+	   }
+	  mdelay(wait);
+	  wait *= 2;
+	 }
+	pos += len2;
+	len -= len2*sizeof(long);
+       }
+     }
+
+    /* to make esp->shift work */
+    esp=current_esp;
+
+#if 0
+    len2 = (esp_read(current_esp->eregs->esp_tclow) & 0xff) |
+           ((esp_read(current_esp->eregs->esp_tcmed) & 0xff) << 8);
+
+    /*
+     * Uh uh. If you see this, len and transfer count registers were out of
+     * sync. That means really serious trouble.
+     */
+
+    if(len2)
+      printk("Eeeek!! Transfer count still %ld!\n",len2);
+#endif
+
+    /*
+     * Normally we just need to exit and wait for the interrupt to come.
+     * But at least one device (my Microtek ScanMaker 630) regularly mis-
+     * calculates the bytes it should send which is really ugly because
+     * it locks up the SCSI bus if not accounted for.
+     */
+
+    if(!(esp_read(current_esp->eregs->esp_status) & ESP_STAT_INTR))
+     {
+      long len = 100;
+      long trash[10];
+
+      /*
+       * Interrupt bit was not set. Either the device is just plain lazy
+       * so we give it a 10 ms chance or...
+       */
+      while(len-- && (!(esp_read(current_esp->eregs->esp_status) & ESP_STAT_INTR)))
+        udelay(100);
+
+
+      if(!(esp_read(current_esp->eregs->esp_status) & ESP_STAT_INTR))
+       {
+        /*
+	 * So we think that the transfer count is out of sync. Since we
+	 * have all we want we are happy and can ditch the trash.
+	 */
+	 
+        len = DMA_MAXTRANSFER;
+
+        while(len-- && (!(esp_read(current_esp->eregs->esp_status) & ESP_STAT_INTR)))
+          oktag_from_io(trash,paddress,2);
+
+        if(!(esp_read(current_esp->eregs->esp_status) & ESP_STAT_INTR))
+         {
+          /*
+           * Things really have gone wrong. If we leave the system in that
+           * state, the SCSI bus is locked forever. I hope that this will
+           * turn the system in a more or less running state.
+           */
+          printk("Device is bolixed, trying bus reset...\n");
+	  esp_bootup_reset(current_esp,current_esp->eregs);
+         }
+       }
+     }
+
+    ESPDATA(("Transfer_finale: do_data_finale should come\n"));
+
+    len = 0;
+    dma_on = 0;
+    dma_ints_on(current_esp);
+}
+
+#endif
+
+/************************************************************* DMA Functions */
+static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
+{
+	/* Since the CyberStorm DMA is fully dedicated to the ESP chip,
+	 * the number of bytes sent (to the ESP chip) equals the number
+	 * of bytes in the FIFO - there is no buffering in the DMA controller.
+	 * XXXX Do I read this right? It is from host to ESP, right?
+	 */
+	return fifo_count;
+}
+
+static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp)
+{
+	unsigned long sz = sp->SCp.this_residual;
+	if(sz > DMA_MAXTRANSFER)
+		sz = DMA_MAXTRANSFER;
+	return sz;
+}
+
+static void dma_dump_state(struct NCR_ESP *esp)
+{
+}
+
+/*
+ * What the f$@& is this?
+ *
+ * Some SCSI devices (like my Microtek ScanMaker 630 scanner) want to transfer
+ * more data than requested. How much? Dunno. So ditch the bogus data into
+ * the sink, hoping the device will advance to the next phase sooner or later.
+ *
+ *                         -- Carsten
+ */
+
+static long oktag_eva_buffer[16]; /* The data sink */
+
+static void oktag_check_dma(void)
+{
+  struct NCR_ESP *esp;
+
+  esp=current_esp;
+  if(!len)
+   {
+    address = oktag_eva_buffer;
+    len = 2;
+    /* esp_do_data sets them to zero like len */
+    esp_write(current_esp->eregs->esp_tclow,2);
+    esp_write(current_esp->eregs->esp_tcmed,0);
+   }
+}
+
+static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length)
+{
+	/* Zorro is noncached, everything else done using processor. */
+	/* cache_clear(addr, length); */
+	
+	if(dma_on)
+	  panic("dma_init_read while dma process is initialized/running!\n");
+	direction = 0;
+	address = (long *) vaddress;
+	current_esp = esp;
+	len = length;
+	oktag_check_dma();
+        dma_on = 1;
+}
+
+static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length)
+{
+	/* cache_push(addr, length); */
+
+	if(dma_on)
+	  panic("dma_init_write while dma process is initialized/running!\n");
+	direction = 1;
+	address = (long *) vaddress;
+	current_esp = esp;
+	len = length;
+	oktag_check_dma();
+	dma_on = 1;
+}
+
+static void dma_ints_off(struct NCR_ESP *esp)
+{
+	disable_irq(esp->irq);
+}
+
+static void dma_ints_on(struct NCR_ESP *esp)
+{
+	enable_irq(esp->irq);
+}
+
+static int dma_irq_p(struct NCR_ESP *esp)
+{
+	/* It's important to check the DMA IRQ bit in the correct way! */
+	return (esp_read(esp->eregs->esp_status) & ESP_STAT_INTR);
+}
+
+static void dma_led_off(struct NCR_ESP *esp)
+{
+}
+
+static void dma_led_on(struct NCR_ESP *esp)
+{
+}
+
+static int dma_ports_p(struct NCR_ESP *esp)
+{
+	return ((custom.intenar) & IF_PORTS);
+}
+
+static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
+{
+	/* On the Sparc, DMA_ST_WRITE means "move data from device to memory"
+	 * so when (write) is true, it actually means READ!
+	 */
+	if(write){
+		dma_init_read(esp, addr, count);
+	} else {
+		dma_init_write(esp, addr, count);
+	}
+}
+
+/*
+ * IRQ entry when DMA transfer is ready to be started
+ */
+
+static void dma_irq_exit(struct NCR_ESP *esp)
+{
+#ifdef USE_BOTTOM_HALF
+	if(dma_on)
+	 {
+	  tq_fake_dma.sync = 0;
+	  queue_task(&tq_fake_dma,&tq_immediate);
+	  mark_bh(IMMEDIATE_BH);
+	 }
+#else
+	while(len && !dma_irq_p(esp))
+	 {
+	  if(direction)
+	    *paddress = *address++;
+	   else
+	    *address++ = *paddress;
+	  len -= (sizeof(long));
+	 }
+	len = 0;
+        dma_on = 0;
+#endif
+}
+
+/*
+ * IRQ entry when DMA has just finished
+ */
+
+static void dma_invalidate(struct NCR_ESP *esp)
+{
+}
+
+/*
+ * Since the processor does the data transfer we have to use the custom
+ * mmu interface to pass the virtual address, not the physical.
+ */
+
+void dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd *sp)
+{
+        sp->SCp.have_data_in = (int) sp->SCp.ptr =
+                sp->request_buffer;
+}
+
+void dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd *sp)
+{
+        sp->SCp.ptr = 
+                sp->SCp.buffer->address;
+}
+
+void dma_mmu_release_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd *sp)
+{
+}
+
+void dma_mmu_release_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd *sp)
+{
+}
+
+void dma_advance_sg(Scsi_Cmnd *sp)
+{
+  sp->SCp.ptr = sp->SCp.buffer->address;
+}
+
+#ifdef MODULE
+
+#define HOSTS_C
+
+#include "oktagon_esp.h"
+
+Scsi_Host_Template driver_template = SCSI_OKTAGON_ESP;
+
+#include "scsi_module.c"
+
+#endif
+
+int oktagon_esp_release(struct Scsi_Host *instance)
+{
+#ifdef MODULE
+	unsigned int key;
+
+	key = ((struct NCR_ESP *)instance->hostdata)->slot;
+	esp_release();
+	zorro_unconfig_board(key, 0);
+	free_irq(IRQ_AMIGA_PORTS, esp_intr);
+	unregister_reboot_notifier(&oktagon_notifier);
+#endif
+	return 1;
+}
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/oktagon_esp.h linux/drivers/scsi/oktagon_esp.h
--- v2.3.13/linux/drivers/scsi/oktagon_esp.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/oktagon_esp.h	Thu Aug 12 10:28:34 1999
@@ -0,0 +1,57 @@
+/* oktagon_esp.h: Defines and structures for the CyberStorm SCSI Mk II driver.
+ *
+ * Copyright (C) 1996 Jesper Skov (jskov@cs.auc.dk)
+ */
+
+#include "NCR53C9x.h"
+
+#ifndef OKTAGON_ESP_H
+#define OKTAGON_ESP_H
+
+/* The controller registers can be found in the Z2 config area at these
+ * offsets:
+ */
+#define OKTAGON_ESP_ADDR 0x03000
+#define OKTAGON_DMA_ADDR 0x01000
+
+
+/* The CyberStorm II DMA interface */
+struct oktagon_dma_registers {
+	volatile unsigned char cond_reg;        /* DMA cond    (ro)  [0x000] */
+#define ctrl_reg  cond_reg			/* DMA control (wo)  [0x000] */
+	unsigned char dmapad4[0x3f];
+	volatile unsigned char dma_addr0;	/* DMA address (MSB) [0x040] */
+	unsigned char dmapad1[3];
+	volatile unsigned char dma_addr1;	/* DMA address       [0x044] */
+	unsigned char dmapad2[3];
+	volatile unsigned char dma_addr2;	/* DMA address       [0x048] */
+	unsigned char dmapad3[3];
+	volatile unsigned char dma_addr3;	/* DMA address (LSB) [0x04c] */
+};
+
+extern int oktagon_esp_detect(struct SHT *);
+extern int oktagon_esp_release(struct Scsi_Host *);
+extern const char *esp_info(struct Scsi_Host *);
+extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+extern int esp_command(Scsi_Cmnd *);
+extern int esp_abort(Scsi_Cmnd *);
+extern int esp_reset(Scsi_Cmnd *, unsigned int);
+extern int esp_proc_info(char *buffer, char **start, off_t offset, int length,
+			int hostno, int inout);
+
+#define SCSI_OKTAGON_ESP {                       \
+   proc_dir:            &proc_scsi_esp,          \
+   proc_info:           &esp_proc_info,          \
+   name:                "BSC Oktagon SCSI",      \
+   detect:              oktagon_esp_detect,      \
+   release:             oktagon_esp_release,     \
+   queuecommand:        esp_queue,               \
+   abort:               esp_abort,               \
+   reset:               esp_reset,               \
+   can_queue:           7,                       \
+   this_id:             7,                       \
+   sg_tablesize:        SG_ALL,                  \
+   cmd_per_lun:         1,                       \
+   use_clustering:      ENABLE_CLUSTERING }
+
+#endif /* OKTAGON_ESP_H */
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/oktagon_io.S linux/drivers/scsi/oktagon_io.S
--- v2.3.13/linux/drivers/scsi/oktagon_io.S	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/oktagon_io.S	Thu Aug 12 10:28:34 1999
@@ -0,0 +1,195 @@
+/* -*- mode: asm -*-
+ * Due to problems while transferring data I've put these routines as assembly
+ * code.
+ * Since I'm no PPC assembler guru, the code is just the assembler version of
+
+int oktag_to_io(long *paddr,long *addr,long len)
+{
+  long *addr2 = addr;
+  for(len=(len+sizeof(long)-1)/sizeof(long);len--;)
+    *paddr = *addr2++;
+  return addr2 - addr;
+}
+
+int oktag_from_io(long *addr,long *paddr,long len)
+{
+  long *addr2 = addr;
+  for(len=(len+sizeof(long)-1)/sizeof(long);len--;)
+    *addr2++ = *paddr;
+  return addr2 - addr;
+}
+
+ * assembled using gcc -O2 -S, with two exception catch points where data
+ * is moved to/from the IO register.
+ */
+
+#include <linux/config.h>
+
+#ifdef CONFIG_APUS
+
+	.file	"oktagon_io.c"
+
+gcc2_compiled.:
+/*
+	.section ".text"
+*/
+	.align 2
+	.globl oktag_to_io
+	.type	 oktag_to_io,@function
+oktag_to_io:
+	addi 5,5,3
+	srwi 5,5,2
+	cmpwi 1,5,0
+	mr 9,3
+	mr 3,4
+	addi 5,5,-1
+	bc 12,6,.L3
+.L5:
+	cmpwi 1,5,0
+	lwz 0,0(3)
+	addi 3,3,4
+	addi 5,5,-1
+exp1:	stw 0,0(9)
+	bc 4,6,.L5
+.L3:
+ret1:	subf 3,4,3
+	srawi 3,3,2
+	blr
+.Lfe1:
+	.size	 oktag_to_io,.Lfe1-oktag_to_io
+	.align 2
+	.globl oktag_from_io
+	.type	 oktag_from_io,@function
+oktag_from_io:
+	addi 5,5,3
+	srwi 5,5,2
+	cmpwi 1,5,0
+	mr 9,3
+	addi 5,5,-1
+	bc 12,6,.L9
+.L11:
+	cmpwi 1,5,0
+exp2:	lwz 0,0(4)
+	addi 5,5,-1
+	stw 0,0(3)
+	addi 3,3,4
+	bc 4,6,.L11
+.L9:
+ret2:	subf 3,9,3
+	srawi 3,3,2
+	blr
+.Lfe2:
+	.size	 oktag_from_io,.Lfe2-oktag_from_io
+	.ident	"GCC: (GNU) egcs-2.90.29 980515 (egcs-1.0.3 release)"
+
+/*
+ * Exception table.
+ * Second longword shows where to jump when an exception at the addr the first
+ * longword is pointing to is caught.
+ */
+
+.section __ex_table,"a"
+	.align	2
+oktagon_except:
+	.long	exp1,ret1
+	.long	exp2,ret2
+
+#else
+
+/*
+The code which follows is for 680x0 based assembler and is meant for
+Linux/m68k. It was created by cross compiling the code using the
+instructions given above. I then added the four labels used in the
+exception handler table at the bottom of this file.
+- Kevin <kcozens@interlog.com>
+*/
+
+#ifdef CONFIG_AMIGA
+
+	.file	"oktagon_io.c"
+	.version	"01.01"
+gcc2_compiled.:
+.text
+	.align 	2
+.globl oktag_to_io
+	.type	 oktag_to_io,@function
+oktag_to_io:
+	link.w %a6,#0
+	move.l %d2,-(%sp)
+	move.l 8(%a6),%a1
+	move.l 12(%a6),%d1
+	move.l %d1,%a0
+	move.l 16(%a6),%d0
+	addq.l #3,%d0
+	lsr.l #2,%d0
+	subq.l #1,%d0
+	moveq.l #-1,%d2
+	cmp.l %d0,%d2
+	jbeq .L3
+.L5:
+exp1:
+	move.l (%a0)+,(%a1)
+	dbra %d0,.L5
+	clr.w %d0
+	subq.l #1,%d0
+	jbcc .L5
+.L3:
+ret1:
+	move.l %a0,%d0
+	sub.l %d1,%d0
+	asr.l #2,%d0
+	move.l -4(%a6),%d2
+	unlk %a6
+	rts
+
+.Lfe1:
+	.size	 oktag_to_io,.Lfe1-oktag_to_io
+	.align 	2
+.globl oktag_from_io
+	.type	 oktag_from_io,@function
+oktag_from_io:
+	link.w %a6,#0
+	move.l %d2,-(%sp)
+	move.l 8(%a6),%d1
+	move.l 12(%a6),%a1
+	move.l %d1,%a0
+	move.l 16(%a6),%d0
+	addq.l #3,%d0
+	lsr.l #2,%d0
+	subq.l #1,%d0
+	moveq.l #-1,%d2
+	cmp.l %d0,%d2
+	jbeq .L9
+.L11:
+exp2:
+	move.l (%a1),(%a0)+
+	dbra %d0,.L11
+	clr.w %d0
+	subq.l #1,%d0
+	jbcc .L11
+.L9:
+ret2:
+	move.l %a0,%d0
+	sub.l %d1,%d0
+	asr.l #2,%d0
+	move.l -4(%a6),%d2
+	unlk %a6
+	rts
+.Lfe2:
+	.size	 oktag_from_io,.Lfe2-oktag_from_io
+	.ident	"GCC: (GNU) 2.7.2.1"
+
+/*
+ * Exception table.
+ * Second longword shows where to jump when an exception at the addr the first
+ * longword is pointing to is caught.
+ */
+
+.section __ex_table,"a"
+	.align	2
+oktagon_except:
+	.long	exp1,ret1
+	.long	exp2,ret2
+
+#endif
+#endif
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/pas16.c linux/drivers/scsi/pas16.c
--- v2.3.13/linux/drivers/scsi/pas16.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/scsi/pas16.c	Thu Aug 12 11:10:58 1999
@@ -73,7 +73,6 @@
  *     software after reset using the default_irq for the
  *     current board number.
  *
- *
  * 2.  With command line overrides - pas16=port,irq may be 
  *     used on the LILO command line to override the defaults.
  *
@@ -83,6 +82,11 @@
  *     -DPAS16_OVERRIDE={{0x388, 10}}
  *     NOTE:  Untested.
  *	
+ * 4.  When included as a module, with arguments passed on the command line:
+ *         pas16_irq=xx		the interrupt
+ *         pas16_addr=xx	the port
+ *     e.g. "modprobe pas16 pas16_addr=0x388 pas16_irq=5"
+ *
  *     Note that if the override methods are used, place holders must
  *     be specified for other boards in the system.
  *
@@ -99,7 +103,11 @@
  *   interrupts.  Ie, for a board at the default 0x388 base port,
  *   boot: linux pas16=0x388,255
  *
- *     (255 is the IRQ_NONE constant in NCR5380.h)
+ *   IRQ_NONE (255) should be specified for no interrupt,
+ *   IRQ_AUTO (254) to autoprobe for an IRQ line if overridden
+ *   on the command line.
+ *
+ *   (IRQ_AUTO == 254, IRQ_NONE == 255 in NCR5380.h)
  */
  
 #ifdef MODULE
@@ -129,6 +137,8 @@
 };
 static int pas_maxi = 0;
 static int pas_wmaxi = 0;
+static unsigned short pas16_addr = 0;
+static int pas16_irq = 0;
  
 
 int scsi_irq_translate[] =
@@ -385,6 +395,22 @@
     tpnt->proc_dir = &proc_scsi_pas16;
     tpnt->proc_info = &pas16_proc_info;
 
+    if (pas16_addr != 0) {
+	overrides[0].io_port = pas16_addr;
+	/*
+	*  This is how we avoid seeing more than
+	*  one host adapter at the same I/O port.
+	*  Cribbed shamelessly from pas16_setup().
+	*/
+	for (count = 0; count < NO_BASES; ++count)
+	    if (bases[count].io_port == pas16_addr) {
+ 		    bases[count].noauto = 1;
+		    break;
+	}
+    }
+    if (pas16_irq != 0)
+	overrides[0].irq = pas16_irq;
+
     for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
 	io_port = 0;
 
@@ -580,4 +606,7 @@
 Scsi_Host_Template driver_template = MV_PAS16;
 
 #include "scsi_module.c"
+
+MODULE_PARM(pas16_addr, "h");
+MODULE_PARM(pas16_irq, "i");
 #endif
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v2.3.13/linux/drivers/scsi/scsi.c	Mon Aug  9 14:59:22 1999
+++ linux/drivers/scsi/scsi.c	Mon Aug  9 19:21:33 1999
@@ -406,6 +406,11 @@
 	up(SCpnt->request.sem);
 }
 
+MODULE_PARM(scsi_logging_level, "i");
+MODULE_PARM_DESC(scsi_logging_level, "SCSI logging level; should be zero or nonzero");
+
+#ifndef MODULE
+
 static int __init scsi_logging_setup (char *str)
 {
 	int tmp;
@@ -422,12 +427,19 @@
 
 __setup("scsi_logging=", scsi_logging_setup);
 
+#endif
+
 #ifdef CONFIG_SCSI_MULTI_LUN
 static int max_scsi_luns = 8;
 #else
 static int max_scsi_luns = 1;
 #endif
 
+MODULE_PARM(max_scsi_luns, "i");
+MODULE_PARM_DESC(max_scsi_luns, "last scsi LUN (should be between 1 and 8)");
+
+#ifndef MODULE
+
 static int __init scsi_luns_setup (char *str)
 {
 	int tmp;
@@ -443,6 +455,9 @@
 }
 
 __setup("max_scsi_luns=", scsi_luns_setup);
+
+#endif
+
 /*
  *  Detecting SCSI devices :
  *  We scan all present host adapter's busses,  from ID 0 to ID (max_id).
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/scsi_error.c linux/drivers/scsi/scsi_error.c
--- v2.3.13/linux/drivers/scsi/scsi_error.c	Wed Jun 16 19:26:27 1999
+++ linux/drivers/scsi/scsi_error.c	Sun Aug 15 11:49:53 1999
@@ -35,7 +35,11 @@
 #include "hosts.h"
 #include "constants.h"
 
-#define SHUTDOWN_SIGS	(sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM))
+#ifdef MODULE
+	#define SHUTDOWN_SIGS	(sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM))
+#else
+	#define SHUTDOWN_SIGS	(0UL)
+#endif
 
 #ifdef DEBUG
     #define SENSE_TIMEOUT SCSI_TIMEOUT
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/sun3x_esp.c linux/drivers/scsi/sun3x_esp.c
--- v2.3.13/linux/drivers/scsi/sun3x_esp.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/sun3x_esp.c	Thu Aug 12 10:28:34 1999
@@ -0,0 +1,290 @@
+/* sun3x_esp.c:  EnhancedScsiProcessor Sun3x SCSI driver code.
+ *
+ * (C) 1999 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
+ *
+ * Based on David S. Miller's esp driver
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/malloc.h>
+#include <linux/blk.h>
+#include <linux/proc_fs.h>
+#include <linux/stat.h>
+
+#include "scsi.h"
+#include "hosts.h"
+#include "NCR53C9x.h"
+
+#include "sun3x_esp.h"
+#include <asm/sun3x.h>
+#include <asm/dvma.h>
+
+extern struct NCR_ESP *espchain;
+
+static void dma_barrier(struct NCR_ESP *esp);
+static int  dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
+static int  dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp);
+static void dma_drain(struct NCR_ESP *esp);
+static void dma_dump_state(struct NCR_ESP *esp);
+static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length);
+static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length);
+static void dma_ints_off(struct NCR_ESP *esp);
+static void dma_ints_on(struct NCR_ESP *esp);
+static int  dma_irq_p(struct NCR_ESP *esp);
+static void dma_poll(struct NCR_ESP *esp, unsigned char *vaddr);
+static int  dma_ports_p(struct NCR_ESP *esp);
+static void dma_reset(struct NCR_ESP *esp);
+static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
+static void dma_mmu_get_scsi_one (struct NCR_ESP *esp, Scsi_Cmnd *sp);
+static void dma_mmu_get_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp);
+static void dma_mmu_release_scsi_one (struct NCR_ESP *esp, Scsi_Cmnd *sp);
+static void dma_mmu_release_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp);
+static void dma_advance_sg (Scsi_Cmnd *sp);
+
+volatile unsigned char cmd_buffer[16];
+                                /* This is where all commands are put
+                                 * before they are trasfered to the ESP chip
+                                 * via PIO.
+                                 */
+
+/* Detecting ESP chips on the machine.  This is the simple and easy
+ * version.
+ */
+int sun3x_esp_detect(Scsi_Host_Template *tpnt)
+{
+	struct NCR_ESP *esp;
+	struct ConfigDev *esp_dev;
+
+	esp_dev = 0;
+	esp = esp_allocate(tpnt, (void *) esp_dev);
+
+	/* Do command transfer with DMA */
+	esp->do_pio_cmds = 0;
+
+	/* Required functions */
+	esp->dma_bytes_sent = &dma_bytes_sent;
+	esp->dma_can_transfer = &dma_can_transfer;
+	esp->dma_dump_state = &dma_dump_state;
+	esp->dma_init_read = &dma_init_read;
+	esp->dma_init_write = &dma_init_write;
+	esp->dma_ints_off = &dma_ints_off;
+	esp->dma_ints_on = &dma_ints_on;
+	esp->dma_irq_p = &dma_irq_p;
+	esp->dma_ports_p = &dma_ports_p;
+	esp->dma_setup = &dma_setup;
+
+	/* Optional functions */
+	esp->dma_barrier = &dma_barrier;
+	esp->dma_drain = &dma_drain;
+	esp->dma_irq_entry = &dma_ints_off;
+	esp->dma_irq_exit = &dma_ints_on;
+	esp->dma_led_on = 0;
+	esp->dma_led_off = 0;
+	esp->dma_poll = &dma_poll;
+	esp->dma_reset = &dma_reset;
+
+        /* virtual DMA functions */
+        esp->dma_mmu_get_scsi_one = &dma_mmu_get_scsi_one;
+        esp->dma_mmu_get_scsi_sgl = &dma_mmu_get_scsi_sgl;
+        esp->dma_mmu_release_scsi_one = &dma_mmu_release_scsi_one;
+        esp->dma_mmu_release_scsi_sgl = &dma_mmu_release_scsi_sgl;
+        esp->dma_advance_sg = &dma_advance_sg;
+	    
+	/* SCSI chip speed */
+	esp->cfreq = 20000000;
+	esp->eregs = (struct ESP_regs *)(SUN3X_ESP_BASE);
+	esp->dregs = (void *)SUN3X_ESP_DMA;
+
+	esp->esp_command = (volatile unsigned char *)cmd_buffer;
+	esp->esp_command_dvma = dvma_alloc(virt_to_phys(cmd_buffer), 
+					   sizeof (cmd_buffer));
+
+	esp->irq = 2;
+	request_irq(esp->irq, esp_intr, SA_INTERRUPT, "SUN3X SCSI", NULL);
+
+	esp->scsi_id = 7;
+	esp->diff = 0;
+
+	esp_initialize(esp);
+
+	printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps,
+	       esps_in_use);
+	esps_running = esps_in_use;
+	return esps_in_use;
+}
+
+static void dma_barrier(struct NCR_ESP *esp)
+{
+	struct sparc_dma_registers *dregs =
+		(struct sparc_dma_registers *) esp->dregs;
+
+	while(dregs->cond_reg & DMA_PEND_READ)
+		udelay(1);
+	dregs->cond_reg &= ~(DMA_ENABLE);
+}
+
+/* This uses various DMA csr fields and the fifo flags count value to
+ * determine how many bytes were successfully sent/received by the ESP.
+ */
+static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
+{
+	struct sparc_dma_registers *dregs = 
+		(struct sparc_dma_registers *) esp->dregs;
+
+	int rval = dregs->st_addr - esp->esp_command_dvma;
+
+	return rval - fifo_count;
+}
+
+static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp)
+{
+	__u32 base, end, sz;
+
+	base = ((__u32)sp->SCp.ptr);
+	base &= (0x1000000 - 1);
+	end = (base + sp->SCp.this_residual);
+	if(end > 0x1000000)
+		end = 0x1000000;
+	sz = (end - base);
+	return sz;
+}
+
+static void dma_drain(struct NCR_ESP *esp)
+{
+	struct sparc_dma_registers *dregs =
+		(struct sparc_dma_registers *) esp->dregs;
+
+	if(dregs->cond_reg & DMA_FIFO_ISDRAIN) {
+		dregs->cond_reg |= DMA_FIFO_STDRAIN;
+		while(dregs->cond_reg & DMA_FIFO_ISDRAIN)
+			udelay(1);
+	}
+}
+
+static void dma_dump_state(struct NCR_ESP *esp)
+{
+	struct sparc_dma_registers *dregs =
+		(struct sparc_dma_registers *) esp->dregs;
+
+	ESPLOG(("esp%d: dma -- cond_reg<%08lx> addr<%p>\n",
+		esp->esp_id, dregs->cond_reg, dregs->st_addr));
+}
+
+static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length)
+{
+	struct sparc_dma_registers *dregs = 
+		(struct sparc_dma_registers *) esp->dregs;
+
+	dregs->cond_reg |= (DMA_ST_WRITE | DMA_ENABLE);
+	dregs->st_addr = vaddress;
+}
+
+static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length)
+{
+	struct sparc_dma_registers *dregs = 
+		(struct sparc_dma_registers *) esp->dregs;
+
+	/* Set up the DMA counters */
+	dregs->cond_reg = ((dregs->cond_reg & ~(DMA_ST_WRITE)) | DMA_ENABLE);
+	dregs->st_addr = vaddress;
+}
+
+static void dma_ints_off(struct NCR_ESP *esp)
+{
+	DMA_INTSOFF((struct sparc_dma_registers *) esp->dregs);
+}
+
+static void dma_ints_on(struct NCR_ESP *esp)
+{
+	DMA_INTSON((struct sparc_dma_registers *) esp->dregs);
+}
+
+static int dma_irq_p(struct NCR_ESP *esp)
+{
+	return DMA_IRQ_P((struct sparc_dma_registers *) esp->dregs);
+}
+
+static void dma_poll(struct NCR_ESP *esp, unsigned char *vaddr)
+{
+	dma_drain(esp);
+
+	/* Wait till the first bits settle. */
+	while(vaddr[0] == 0xff)
+		udelay(1);
+}	
+
+static int dma_ports_p(struct NCR_ESP *esp)
+{
+	return (((struct sparc_dma_registers *) esp->dregs)->cond_reg 
+			& DMA_INT_ENAB);
+}
+
+/* Resetting various pieces of the ESP scsi driver chipset/buses. */
+static void dma_reset(struct NCR_ESP *esp)
+{
+	struct sparc_dma_registers *dregs =
+		(struct sparc_dma_registers *)esp->dregs;
+
+	/* Punt the DVMA into a known state. */
+	dregs->cond_reg |= DMA_RST_SCSI;
+	dregs->cond_reg &= ~(DMA_RST_SCSI);
+	DMA_INTSON(dregs);
+}
+
+static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
+{
+	struct sparc_dma_registers *dregs = 
+		(struct sparc_dma_registers *) esp->dregs;
+	unsigned long nreg = dregs->cond_reg;
+
+	if(write)
+		nreg |= DMA_ST_WRITE;
+	else
+		nreg &= ~(DMA_ST_WRITE);
+	nreg |= DMA_ENABLE;
+	dregs->cond_reg = nreg;
+	dregs->st_addr = addr;
+}
+
+static void dma_mmu_get_scsi_one (struct NCR_ESP *esp, Scsi_Cmnd *sp)
+{
+    sp->SCp.have_data_in = dvma_alloc(virt_to_phys(sp->SCp.buffer),
+				       sp->SCp.this_residual);
+    sp->SCp.ptr = (char *)((unsigned long)sp->SCp.have_data_in);
+}
+
+static void dma_mmu_get_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp)
+{
+    int sz = sp->SCp.buffers_residual;
+    struct mmu_sglist *sg = (struct mmu_sglist *) sp->SCp.buffer;
+
+    while (sz >= 0) {
+        sg[sz].dvma_addr = dvma_alloc(virt_to_phys(sg[sz].addr), sg[sz].len);
+        sz--;
+    }
+    sp->SCp.ptr=(char *)((unsigned long)sp->SCp.buffer->dvma_address);
+}
+
+static void dma_mmu_release_scsi_one (struct NCR_ESP *esp, Scsi_Cmnd *sp)
+{
+    dvma_free(sp->SCp.have_data_in, sp->request_bufflen);
+}
+
+static void dma_mmu_release_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp)
+{
+    int sz = sp->use_sg - 1;
+    struct mmu_sglist *sg = (struct mmu_sglist *)sp->buffer;
+                        
+    while(sz >= 0) {
+        dvma_free(sg[sz].dvma_addr,sg[sz].len);
+        sz--;
+    }
+}
+
+static void dma_advance_sg (Scsi_Cmnd *sp)
+{
+    sp->SCp.ptr = (char *)((unsigned long)sp->SCp.buffer->dvma_address);
+}
diff -u --recursive --new-file v2.3.13/linux/drivers/scsi/sun3x_esp.h linux/drivers/scsi/sun3x_esp.h
--- v2.3.13/linux/drivers/scsi/sun3x_esp.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/sun3x_esp.h	Thu Aug 12 10:28:34 1999
@@ -0,0 +1,41 @@
+/* sun3x_esp.h: Defines and structures for the Sun3x ESP
+ *
+ * (C) 1995 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
+ */
+
+#ifndef _SUN3X_ESP_H
+#define _SUN3X_ESP_H
+
+/* For dvma controller register definitions. */
+#include <asm/dvma.h>
+
+extern int sun3x_esp_detect(struct SHT *);
+extern const char *esp_info(struct Scsi_Host *);
+extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+extern int esp_command(Scsi_Cmnd *);
+extern int esp_abort(Scsi_Cmnd *);
+extern int esp_reset(Scsi_Cmnd *, unsigned int);
+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_info:      &esp_proc_info,			\
+		name:           "Sun ESP 100/100a/200",		\
+		detect:         sun3x_esp_detect,		\
+		info:           esp_info,			\
+		command:        esp_command,			\
+		queuecommand:   esp_queue,			\
+		abort:          esp_abort,			\
+		reset:          esp_reset,			\
+		can_queue:      7,				\
+		this_id:        7,				\
+		sg_tablesize:   SG_ALL,				\
+		cmd_per_lun:    1,				\
+		use_clustering: DISABLE_CLUSTERING, }
+
+#endif /* !(_SUN3X_ESP_H) */
diff -u --recursive --new-file v2.3.13/linux/drivers/sound/Makefile linux/drivers/sound/Makefile
--- v2.3.13/linux/drivers/sound/Makefile	Mon Aug  9 14:59:23 1999
+++ linux/drivers/sound/Makefile	Thu Aug 12 12:18:32 1999
@@ -141,19 +141,19 @@
 
 # Translate to Rules.make lists.
 
-L_TARGET	:= sound.a
+O_TARGET	:= sounddrivers.o
 # This is a nice idea but needs depmod altering
 #MOD_LIST_NAME	:= SOUND_MODULES
 
-L_OBJS		:= $(sort $(filter-out $(export-objs), $(obj-y)))
-LX_OBJS		:= $(sort $(filter     $(export-objs), $(obj-y)))
+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)))
 MI_OBJS		:= $(sort $(filter-out $(export-objs), $(int-m)))
 MIX_OBJS	:= $(sort $(filter     $(export-objs), $(int-m)))
 
 ifeq ($(CONFIG_LOWLEVEL_SOUND),y)
-    L_OBJS	+= lowlevel/lowlevel.o
+    O_OBJS	+= lowlevel/lowlevel.o
 endif
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.13/linux/drivers/sound/dmasound.c linux/drivers/sound/dmasound.c
--- v2.3.13/linux/drivers/sound/dmasound.c	Wed Jul 21 15:46:48 1999
+++ linux/drivers/sound/dmasound.c	Wed Aug 18 10:01:36 1999
@@ -131,7 +131,9 @@
 static int irq_installed = 0;
 #endif /* MODULE */
 static char **sound_buffers = NULL;
+#ifdef CONFIG_PPC
 static char **sound_read_buffers = NULL;
+#endif
 
 #ifdef CONFIG_ATARI
 extern void atari_microwire_cmd(int cmd);
@@ -282,7 +284,9 @@
 
 static int catchRadius = 0;
 static int numBufs = 4, bufSize = 32;
+#ifdef CONFIG_PPC
 static int numReadBufs = 4, readbufSize = 32;
+#endif
 
 MODULE_PARM(catchRadius, "i");
 MODULE_PARM(numBufs, "i");
@@ -796,10 +800,12 @@
 				    size_t userCount,
 				    u_char frame[], ssize_t *frameUsed,
 				    ssize_t frameLeft);
+#ifdef CONFIG_PPC
 static ssize_t sound_copy_translate_read(const u_char *userPtr,
 				    size_t userCount,
 				    u_char frame[], ssize_t *frameUsed,
 				    ssize_t frameLeft);
+#endif
 
 
 /*
@@ -846,7 +852,9 @@
 };
 
 static struct sound_queue sq;
+#ifdef CONFIG_PPC
 static struct sound_queue read_sq;
+#endif
 
 #define sq_block_address(i)	(sq.buffers[i])
 #define SIGNAL_RECEIVED	(signal_pending(current))
@@ -877,7 +885,7 @@
 	if (value < 0)
 		return(value);
 
-	return put_user(value, addr)? -EFAULT: 0;
+	return put_user(value, addr);
 }
 
 
@@ -2728,8 +2736,8 @@
 	start = sq_block_address(sq.front);
 	end = start+((sq.count == index) ? sq.rear_size : sq.block_size);
 	/* end might not be a legal virtual address. */
-	DMASNDSetEnd(VTOP(end - 1) + 1);
-	DMASNDSetBase(VTOP(start));
+	DMASNDSetEnd(virt_to_phys(end - 1) + 1);
+	DMASNDSetBase(virt_to_phys(start));
 	/* Since only an even number of samples per frame can
 	   be played, we might lose one byte here. (TO DO) */
 	sq.front = (sq.front+1) % sq.max_count;
@@ -4031,6 +4039,7 @@
 		return 0;
 }
 
+#ifdef CONFIG_PPC
 static ssize_t sound_copy_translate_read(const u_char *userPtr,
 				    size_t userCount,
 				    u_char frame[], ssize_t *frameUsed,
@@ -4069,6 +4078,7 @@
 	else
 		return 0;
 }
+#endif
 
 
 /*
@@ -4644,6 +4654,7 @@
 }
 
 
+#ifdef CONFIG_PPC
 static int sq_allocate_read_buffers(void)
 {
 	int i;
@@ -4680,15 +4691,12 @@
 	
 
 	if (sound_read_buffers) {
-
-#if CONFIG_PPC
 		cp = awacs_rx_cmds;
 		for (i = 0; i < numReadBufs; i++,cp++) {
 			st_le16(&cp->command, DBDMA_STOP);
 		}
 		/* We should probably wait for the thing to stop before we
 		   release the memory */
-#endif
 		for (i = 0; i < numBufs; i++)
 			sound.mach.dma_free (sound_read_buffers[i],
 					     bufSize << 10);
@@ -4696,6 +4704,7 @@
 		sound_read_buffers = 0;
 	}
 }
+#endif
 
 
 static void sq_setup(int numBufs, int bufSize, char **write_buffers)
@@ -4735,12 +4744,11 @@
 #endif /* CONFIG_PPC */
 }
 
+#ifdef CONFIG_PPC
 static void read_sq_setup(int numBufs, int bufSize, char **read_buffers)
 {
-#ifdef CONFIG_PPC
 	int i;
 	volatile struct dbdma_cmd *cp;
-#endif /* CONFIG_PPC */
 
 	read_sq.max_count = numBufs;
 	read_sq.max_active = numBufs;
@@ -4753,14 +4761,6 @@
 	read_sq.syncing = 0;
 	read_sq.active = 0;
 
-#ifdef CONFIG_ATARI
-	read_sq.ignore_int = 0;
-#endif /* CONFIG_ATARI */
-#ifdef CONFIG_AMIGA
-	read_sq.block_size_half = read_sq.block_size>>1;
-	read_sq.block_size_quarter = read_sq.block_size_half>>1;
-#endif /* CONFIG_AMIGA */
-#ifdef CONFIG_PPC
 	cp = awacs_rx_cmds;
 	memset((void *) cp, 0, (numBufs + 1) * sizeof(struct dbdma_cmd));
 
@@ -4784,8 +4784,8 @@
 	out_le32(&awacs_rxdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16);
 	out_le32(&awacs_rxdma->cmdptr, virt_to_bus(awacs_rx_cmds));
 
-#endif /* CONFIG_PPC */
 }
+#endif /* CONFIG_PPC */
 
 
 static void sq_play(void)
@@ -4868,6 +4868,8 @@
 
 /***********/
 
+#ifdef CONFIG_PPC
+
 /* Here is how the values are used for reading.
  * The value 'active' simply indicates the DMA is running.  This is
  * done so the driver semantics are DMA starts when the first read is
@@ -4930,6 +4932,7 @@
 	}
 	return uRead;
 }
+#endif
 
 static int sq_open(struct inode *inode, struct file *file)
 {
@@ -4957,6 +4960,7 @@
 	}
 
 
+#ifdef CONFIG_PCC
 	if (file->f_mode & FMODE_READ) {
 		if (read_sq.busy) {
 			rc = -EBUSY;
@@ -4976,6 +4980,7 @@
 		read_sq_setup(numReadBufs,readbufSize<<10, sound_read_buffers);
 		read_sq.open_mode = file->f_mode;
 	}                                                                      
+#endif
 
 #ifdef CONFIG_ATARI
 	sq.ignore_int = 1;
@@ -5004,10 +5009,12 @@
 		sq.busy = 0;
 		WAKE_UP(sq.open_queue);
 	}
+#ifdef CONFIG_PCC
 	if (file->f_mode & FMODE_READ) {
 		read_sq.busy = 0;
 		WAKE_UP(read_sq.open_queue);
 	}
+#endif
 err_out:
 	MOD_DEC_USE_COUNT;
 	return rc;
@@ -5056,16 +5063,20 @@
 	sound.hard = sound.dsp;
 	sound_silence();
 
+#ifdef CONFIG_PPC
 	sq_release_read_buffers();
+#endif
 	sq_release_buffers();
 	MOD_DEC_USE_COUNT;
 
 	/* There is probably a DOS atack here. They change the mode flag. */
 	/* XXX add check here */
+#ifdef CONFIG_PPC
 	if (file->f_mode & FMODE_READ) {
 		read_sq.busy = 0;
 		WAKE_UP(read_sq.open_queue);
 	}
+#endif
 
 	if (file->f_mode & FMODE_WRITE) {
 		sq.busy = 0;
@@ -5173,7 +5184,11 @@
 static struct file_operations sq_fops =
 {
 	sound_lseek,
+#ifdef CONFIG_PPC
 	sq_read,			/* sq_read */
+#else
+	NULL,			/* sq_read */
+#endif
 	sq_write,
 	NULL,			/* sq_readdir */
 	NULL,			/* sq_poll */
@@ -5198,12 +5213,16 @@
 	init_waitqueue_head(&sq.open_queue);
 	init_waitqueue_head(&sq.sync_queue);
 
+#ifdef CONFIG_PPC
 	init_waitqueue_head(&read_sq.action_queue);
 	init_waitqueue_head(&read_sq.open_queue);
 	init_waitqueue_head(&read_sq.sync_queue);
+#endif
 
 	sq.busy = 0;
+#ifdef CONFIG_PPC
 	read_sq.busy = 0;
+#endif
 
 	/* whatever you like as startup mode for /dev/dsp,
 	 * (/dev/audio hasn't got a startup mode). note that
@@ -5251,7 +5270,10 @@
 
 static int state_open(struct inode *inode, struct file *file)
 {
-	char *buffer = state.buf, *mach = "", awacs_buf[50];
+	char *buffer = state.buf, *mach = "";
+#ifdef CONFIG_PPC
+	char awacs_buf[50];
+#endif
 	int len = 0;
 
 	if (state.busy)
diff -u --recursive --new-file v2.3.13/linux/drivers/sound/es1370.c linux/drivers/sound/es1370.c
--- v2.3.13/linux/drivers/sound/es1370.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/sound/es1370.c	Thu Aug 12 12:21:47 1999
@@ -106,6 +106,7 @@
  *    03.08.99   0.26  adapt to Linus' new __setup/__initcall
  *                     added kernel command line option "es1370=joystick[,lineout[,micbias]]"
  *                     removed CONFIG_SOUND_ES1370_JOYPORT_BOOT kludge
+ *    12.08.99   0.27  module_init/__setup fixes
  *
  * some important things missing in Ensoniq documentation:
  *
@@ -1067,9 +1068,10 @@
                         current->state = TASK_RUNNING;
                         return -EBUSY;
                 }
-		tmo = (count * HZ) / dac1_samplerate[(s->ctrl & CTRL_WTSRSEL) >> CTRL_SH_WTSRSEL];
+		tmo = 3 * HZ * (count + s->dma_dac1.fragsize) / 2
+			/ dac1_samplerate[(s->ctrl & CTRL_WTSRSEL) >> CTRL_SH_WTSRSEL];
 		tmo >>= sample_shift[(s->sctrl & SCTRL_P1FMT) >> SCTRL_SH_P1FMT];
-		if (!schedule_timeout(tmo ? : 1) && tmo)
+		if (!schedule_timeout(tmo + 1))
 			DBG(printk(KERN_DEBUG "es1370: dma timed out??\n");)
         }
         remove_wait_queue(&s->dma_dac1.wait, &wait);
@@ -1102,9 +1104,10 @@
                         current->state = TASK_RUNNING;
                         return -EBUSY;
                 }
-		tmo = (count * HZ) / DAC2_DIVTOSR((s->ctrl & CTRL_PCLKDIV) >> CTRL_SH_PCLKDIV);
+		tmo = 3 * HZ * (count + s->dma_dac2.fragsize) / 2
+			/ DAC2_DIVTOSR((s->ctrl & CTRL_PCLKDIV) >> CTRL_SH_PCLKDIV);
 		tmo >>= sample_shift[(s->sctrl & SCTRL_P2FMT) >> SCTRL_SH_P2FMT];
-		if (!schedule_timeout(tmo ? : 1) && tmo)
+		if (!schedule_timeout(tmo + 1))
 			DBG(printk(KERN_DEBUG "es1370: dma timed out??\n");)
         }
         remove_wait_queue(&s->dma_dac2.wait, &wait);
@@ -2300,6 +2303,16 @@
 static int lineout[NR_DEVICE] = { 0, };
 static int micbias[NR_DEVICE] = { 0, };
 
+MODULE_PARM(joystick, "1-" __MODULE_STRING(NR_DEVICE) "i");
+MODULE_PARM_DESC(joystick, "if 1 enables joystick interface (still need separate driver)");
+MODULE_PARM(lineout, "1-" __MODULE_STRING(NR_DEVICE) "i");
+MODULE_PARM_DESC(lineout, "if 1 the LINE input is converted to LINE out");
+MODULE_PARM(micbias, "1-" __MODULE_STRING(NR_DEVICE) "i");
+MODULE_PARM_DESC(micbias, "sets the +5V bias for an electret microphone");
+
+MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
+MODULE_DESCRIPTION("ES1370 AudioPCI Driver");
+
 /* --------------------------------------------------------------------- */
 
 static struct initvol {
@@ -2318,10 +2331,7 @@
 	{ SOUND_MIXER_WRITE_OGAIN, 0x4040 }
 };
 
-#ifndef MODULE
-static
-#endif
-int __init init_module(void)
+static int __init init_es1370(void)
 {
 	struct es1370_state *s;
 	struct pci_dev *pcidev = NULL;
@@ -2330,7 +2340,7 @@
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "es1370: version v0.26 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "es1370: version v0.27 time " __TIME__ " " __DATE__ "\n");
 	while (index < NR_DEVICE && 
 	       (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, pcidev))) {
 		if (pcidev->resource[0].flags == 0 || 
@@ -2438,21 +2448,7 @@
 	return 0;
 }
 
-/* --------------------------------------------------------------------- */
-
-#ifdef MODULE
-
-MODULE_PARM(joystick, "1-" __MODULE_STRING(NR_DEVICE) "i");
-MODULE_PARM_DESC(joystick, "if 1 enables joystick interface (still need separate driver)");
-MODULE_PARM(lineout, "1-" __MODULE_STRING(NR_DEVICE) "i");
-MODULE_PARM_DESC(lineout, "if 1 the LINE input is converted to LINE out");
-MODULE_PARM(micbias, "1-" __MODULE_STRING(NR_DEVICE) "i");
-MODULE_PARM_DESC(micbias, "sets the +5V bias for an electret microphone");
-
-MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
-MODULE_DESCRIPTION("ES1370 AudioPCI Driver");
-
-void cleanup_module(void)
+static void __exit cleanup_es1370(void)
 {
 	struct es1370_state *s;
 
@@ -2472,7 +2468,12 @@
 	printk(KERN_INFO "es1370: unloading\n");
 }
 
-#else /* MODULE */
+module_init(init_es1370);
+module_exit(cleanup_es1370);
+
+/* --------------------------------------------------------------------- */
+
+#ifndef MODULE
 
 /* format is: es1370=[joystick[,lineout[,micbias]]] */
 
@@ -2493,6 +2494,5 @@
 }
 
 __setup("es1370=", es1370_setup);
-__initcall(init_module);
 
 #endif /* MODULE */
diff -u --recursive --new-file v2.3.13/linux/drivers/sound/es1371.c linux/drivers/sound/es1371.c
--- v2.3.13/linux/drivers/sound/es1371.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/sound/es1371.c	Thu Aug 12 12:21:48 1999
@@ -3,7 +3,7 @@
 /*
  *      es1371.c  --  Creative Ensoniq ES1371.
  *
- *      Copyright (C) 1998  Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *      Copyright (C) 1998-1999  Thomas Sailer (sailer@ife.ee.ethz.ch)
  *
  *      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
@@ -71,6 +71,9 @@
  *    03.08.99   0.14  adapt to Linus' new __setup/__initcall
  *                     added kernel command line option "es1371=joystickaddr"
  *                     removed CONFIG_SOUND_ES1371_JOYPORT_BOOT kludge
+ *    10.08.99   0.15  (Re)added S/PDIF module option for cards revision >= 4.
+ *                     Initial version by Dave Platt <dplatt@snulbug.mtview.ca.us>.
+ *                     module_init/__setup fixes
  *
  */
 
@@ -145,6 +148,7 @@
 static const unsigned sample_size[] = { 1, 2, 2, 4 };
 static const unsigned sample_shift[] = { 0, 1, 1, 2 };
 
+#define CTRL_SPDIFEN_B  0x04000000
 #define CTRL_JOY_SHIFT  24
 #define CTRL_JOY_MASK   3
 #define CTRL_JOY_200    0x00000000  /* joystick base address */
@@ -180,6 +184,9 @@
 
 
 #define STAT_INTR       0x80000000  /* wired or of all interrupt bits */
+#define STAT_EN_SPDIF   0x00040000  /* enable S/PDIF circuitry */
+#define STAT_TS_SPDIF   0x00020000  /* test S/PDIF circuitry */
+#define STAT_TESTMODE   0x00010000  /* test ASIC */
 #define STAT_SYNC_ERR   0x00000100  /* 1 = codec sync error */
 #define STAT_VC         0x000000c0  /* CCB int source, 0=DAC1, 1=DAC2, 2=ADC, 3=undef */
 #define STAT_SH_VC      6
@@ -1481,9 +1488,9 @@
                         current->state = TASK_RUNNING;
                         return -EBUSY;
                 }
-		tmo = (count * HZ) / s->dac1rate;
+		tmo = 3 * HZ * (count + s->dma_dac1.fragsize) / 2 / s->dac1rate;
 		tmo >>= sample_shift[(s->sctrl & SCTRL_P1FMT) >> SCTRL_SH_P1FMT];
-		if (!schedule_timeout(tmo ? : 1) && tmo)
+		if (!schedule_timeout(tmo + 1))
 			printk(KERN_DEBUG "es1371: dma timed out??\n");
         }
         remove_wait_queue(&s->dma_dac1.wait, &wait);
@@ -1516,9 +1523,9 @@
                         current->state = TASK_RUNNING;
                         return -EBUSY;
                 }
-		tmo = (count * HZ) / s->dac2rate;
+		tmo = 3 * HZ * (count + s->dma_dac2.fragsize) / 2 / s->dac2rate;
 		tmo >>= sample_shift[(s->sctrl & SCTRL_P2FMT) >> SCTRL_SH_P2FMT];
-		if (!schedule_timeout(tmo ? : 1) && tmo)
+		if (!schedule_timeout(tmo + 1))
 			printk(KERN_DEBUG "es1371: dma timed out??\n");
         }
         remove_wait_queue(&s->dma_dac2.wait, &wait);
@@ -2697,6 +2704,15 @@
 #define NR_DEVICE 5
 
 static int joystick[NR_DEVICE] = { 0, };
+static int spdif[NR_DEVICE] = { 0, };
+
+MODULE_PARM(joystick, "1-" __MODULE_STRING(NR_DEVICE) "i");
+MODULE_PARM_DESC(joystick, "sets address and enables joystick interface (still need separate driver)");
+MODULE_PARM(spdif, "1-" __MODULE_STRING(NR_DEVICE) "i");
+MODULE_PARM_DESC(spdif, "if 1 the output is in S/PDIF digital mode");
+
+MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
+MODULE_DESCRIPTION("ES1371 AudioPCI97 Driver");
 
 /* --------------------------------------------------------------------- */
 
@@ -2719,19 +2735,18 @@
 	{ SOUND_MIXER_WRITE_IGAIN, 0x4040 }
 };
 
-#ifndef MODULE
-static
-#endif
-int __init init_module(void)
+static int __init init_es1371(void)
 {
 	struct es1371_state *s;
 	struct pci_dev *pcidev = NULL;
 	mm_segment_t fs;
 	int i, val, val2, index = 0;
+	u8 revision;
+	unsigned cssr;
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "es1371: version v0.14 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "es1371: version v0.15 time " __TIME__ " " __DATE__ "\n");
 	while (index < NR_DEVICE && 
 	       (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1371, pcidev))) {
 		if (pcidev->resource[0].flags == 0 || 
@@ -2784,6 +2799,18 @@
 			}
 		}
 		s->sctrl = 0;
+		cssr = 0;
+		/* check to see if s/pdif mode is being requested */
+		pci_read_config_byte(pcidev, PCI_REVISION_ID, &revision);
+		if (spdif[index]) {
+			if (revision >= 4) {
+				printk(KERN_INFO "es1371: enabling S/PDIF output\n");
+				cssr |= STAT_EN_SPDIF;
+				s->ctrl |= CTRL_SPDIFEN_B;
+			} else {
+				printk(KERN_ERR "es1371: revision %d does not support S/PDIF\n", revision);
+			}
+		}
 		/* initialize the chips */
 		outl(s->ctrl, s->io+ES1371_REG_CONTROL);
 		outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
@@ -2858,6 +2885,8 @@
 			mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
 		}
 		set_fs(fs);
+		/* turn on S/PDIF output driver if requested */
+		outl(cssr, s->io+ES1371_REG_STATUS);
 		/* queue it for later freeing */
 		s->next = devs;
 		devs = s;
@@ -2883,17 +2912,7 @@
 	return 0;
 }
 
-/* --------------------------------------------------------------------- */
-
-#ifdef MODULE
-
-MODULE_PARM(joystick, "1-" __MODULE_STRING(NR_DEVICE) "i");
-MODULE_PARM_DESC(joystick, "sets address and enables joystick interface (still need separate driver)");
-
-MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
-MODULE_DESCRIPTION("ES1371 AudioPCI97 Driver");
-
-void cleanup_module(void)
+static void __exit cleanup_es1371(void)
 {
 	struct es1371_state *s;
 
@@ -2913,23 +2932,27 @@
 	printk(KERN_INFO "es1371: unloading\n");
 }
 
-#else /* MODULE */
+module_init(init_es1371);
+module_exit(cleanup_es1371);
+
+/* --------------------------------------------------------------------- */
+
+#ifndef MODULE
 
 /* format is: es1371=[joystick] */
 
 static int __init es1371_setup(char *str)
 {
 	static unsigned __initdata nr_dev = 0;
-        int ints[11];
 
 	if (nr_dev >= NR_DEVICE)
 		return 0;
-	get_option(&str, &joystick[nr_dev]);
+	if (get_option(&str, &joystick[nr_dev]) == 2)
+		get_option(&str, &spdif[nr_dev]);
 	nr_dev++;
 	return 1;
 }
 
 __setup("es1371=", es1371_setup);
-__initcall(init_module);
 
 #endif /* MODULE */
diff -u --recursive --new-file v2.3.13/linux/drivers/sound/esssolo1.c linux/drivers/sound/esssolo1.c
--- v2.3.13/linux/drivers/sound/esssolo1.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/sound/esssolo1.c	Thu Aug 12 12:21:48 1999
@@ -39,13 +39,26 @@
  *    15.06.99   0.4   Fix bad allocation bug.
  *                     Thanks to Deti Fliegl <fliegl@in.tum.de>
  *    28.06.99   0.5   Add pci_set_master
- *
+ *    12.08.99   0.6   Fix MIDI UART crashing the driver
+ *                     Changed mixer semantics from OSS documented
+ *                     behaviour to OSS "code behaviour".
+ *                     Recording might actually work now.
+ *                     The real DDMA controller address register is at PCI config
+ *                     0x60, while the register at 0x18 is used as a placeholder
+ *                     register for BIOS address allocation. This register
+ *                     is supposed to be copied into 0x60, according
+ *                     to the Solo1 datasheet. When I do that, I can access
+ *                     the DDMA registers except the mask bit, which
+ *                     is stuck at 1. When I copy the contents of 0x18 +0x10
+ *                     to the DDMA base register, everything seems to work.
+ *                     The fun part is that the Windows Solo1 driver doesn't
+ *                     seem to do these tricks.
+ *                     Bugs remaining: plops and clicks when starting/stopping playback
  *
  */
 
 /*****************************************************************************/
       
-#include <linux/config.h>
 #include <linux/version.h>
 #include <linux/module.h>
 #include <linux/string.h>
@@ -69,6 +82,10 @@
 
 /* --------------------------------------------------------------------- */
 
+#undef OSS_DOCUMENTED_MIXER_SEMANTICS
+
+/* --------------------------------------------------------------------- */
+
 #ifndef PCI_VENDOR_ID_ESS
 #define PCI_VENDOR_ID_ESS         0x125d
 #endif
@@ -78,9 +95,12 @@
 
 #define SOLO1_MAGIC  ((PCI_VENDOR_ID_ESS<<16)|PCI_DEVICE_ID_ESS_SOLO1)
 
+#define DDMABASE_OFFSET           0x10    /* chip bug workaround kludge */
+#define DDMABASE_EXTENT           16
+
 #define IOBASE_EXTENT             16
 #define SBBASE_EXTENT             16
-#define VCBASE_EXTENT             16
+#define VCBASE_EXTENT             (DDMABASE_EXTENT+DDMABASE_OFFSET)
 #define MPUBASE_EXTENT            4
 #define GPBASE_EXTENT             4
 
@@ -98,16 +118,15 @@
 
 /* --------------------------------------------------------------------- */
 
-#define DEBUGREC
-
-/* --------------------------------------------------------------------- */
-
 struct solo1_state {
 	/* magic */
 	unsigned int magic;
 
-	/* we keep sb cards in a linked list */
+	/* we keep the cards in a linked list */
 	struct solo1_state *next;
+	
+	/* pcidev is needed to turn off the DDMA controller at driver shutdown */
+	struct pci_dev *pcidev;
 
 	/* soundcore stuff */
 	int dev_audio;
@@ -116,10 +135,10 @@
 	int dev_dmfm;
 
 	/* hardware resources */
-	unsigned long iobase, sbbase, vcbase, mpubase, gpbase; /* long for SPARC */
+	unsigned long iobase, sbbase, vcbase, ddmabase, mpubase, gpbase; /* long for SPARC */
 	unsigned int irq;
 
-	/* mixer registers; there is no HW readback */
+	/* mixer registers */
 	struct {
 		unsigned short vol[10];
 		unsigned int recsrc;
@@ -302,6 +321,8 @@
 	spin_lock_irqsave(&s->lock, flags);
 	if (!(s->ena & FMODE_WRITE) && (s->dma_dac.mapped || s->dma_dac.count > 0) && s->dma_dac.ready) {
 		s->ena |= FMODE_WRITE;
+		write_mixer(s, 0x78, 0x12);
+		udelay(10);
 		write_mixer(s, 0x78, 0x13);
 	}
 	spin_unlock_irqrestore(&s->lock, flags);
@@ -326,47 +347,24 @@
 	    && s->dma_adc.ready) {
 		s->ena |= FMODE_READ;
 		write_ctrl(s, 0xb8, 0xf);
-#ifdef DEBUGREC
+#if 0
 		printk(KERN_DEBUG "solo1: DMAbuffer: 0x%08lx\n", (long)s->dma_adc.rawbuf);
 		printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x\n", 
-		       inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
-#endif
-                outb(0, s->vcbase+0xd); /* master reset */
-#ifdef DEBUGREC
-		printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x (a. clr)\n", 
-		       inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
-#endif
-		outb(1, s->vcbase+0xf);  /* mask */
-#ifdef DEBUGREC
-		printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x (a. mask)\n", 
-		       inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
-#endif
-		outb(0x54/*0x14*/, s->vcbase+0xb);  /* DMA_MODE_READ | DMA_MODE_AUTOINIT */
-#ifdef DEBUGREC
-		printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x (a. wrmode)\n", 
-		       inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
-#endif
-		outl(virt_to_bus(s->dma_adc.rawbuf), s->vcbase);
-#ifdef DEBUGREC
-		printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x (a. wrbase)\n", 
-		       inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
-#endif
-		outw(s->dma_adc.dmasize-1, s->vcbase+4);
-#ifdef DEBUGREC
-		printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x (a. wrcnt)\n", 
-		       inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
-#endif
-		outb(0, s->vcbase+0xf);
-#ifdef DEBUGREC
-		printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x (a. clrmask)\n", 
-		       inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
+		       inb(s->ddmabase+0xf), inw(s->ddmabase+4), inl(s->ddmabase), inb(s->ddmabase+8));
 #endif
+                outb(0, s->ddmabase+0xd); /* master reset */
+		outb(1, s->ddmabase+0xf);  /* mask */
+		outb(0x54/*0x14*/, s->ddmabase+0xb);  /* DMA_MODE_READ | DMA_MODE_AUTOINIT */
+		outl(virt_to_bus(s->dma_adc.rawbuf), s->ddmabase);
+		outw(s->dma_adc.dmasize-1, s->ddmabase+4);
+		outb(0, s->ddmabase+0xf);
 	}
 	spin_unlock_irqrestore(&s->lock, flags);
-#ifdef DEBUGREC
-	printk(KERN_DEBUG "solo1: start DMA: reg B8: 0x%02x  DMAstat: 0x%02x  DMAcnt: 0x%04x  DMAmask: 0x%02x  SBstat: 0x%02x\n", 
-	       read_ctrl(s, 0xb8), inb(s->vcbase+8), inw(s->vcbase+4), inb(s->vcbase+0xf), inb(s->sbbase+0xc));
-
+#if 0
+	printk(KERN_DEBUG "solo1: start DMA: reg B8: 0x%02x  SBstat: 0x%02x\n"
+	       KERN_DEBUG "solo1: DMA: stat: 0x%02x  cnt: 0x%04x  mask: 0x%02x\n", 
+	       read_ctrl(s, 0xb8), inb(s->sbbase+0xc), 
+	       inb(s->ddmabase+8), inw(s->ddmabase+4), inb(s->ddmabase+0xf));
 	printk(KERN_DEBUG "solo1: A1: 0x%02x  A2: 0x%02x  A4: 0x%02x  A5: 0x%02x  A8: 0x%02x\n"  
 	       KERN_DEBUG "solo1: B1: 0x%02x  B2: 0x%02x  B4: 0x%02x  B7: 0x%02x  B8: 0x%02x  B9: 0x%02x\n",
 	       read_ctrl(s, 0xa1), read_ctrl(s, 0xa2), read_ctrl(s, 0xa4), read_ctrl(s, 0xa5), read_ctrl(s, 0xa8), 
@@ -456,16 +454,16 @@
 	va = virt_to_bus(s->dma_adc.rawbuf);
 	if ((va & ~((1<<24)-1)))
 		panic("solo1: buffer above 16M boundary");
-	outb(0, s->vcbase+0xd);  /* clear */
-	outb(1, s->vcbase+0xf); /* mask */
-	//outb(0, s->vcbase+8);  /* enable (enable is active low!) */
-	outb(0x54, s->vcbase+0xb);  /* DMA_MODE_READ | DMA_MODE_AUTOINIT */
-	outl(va, s->vcbase);
-	outw(s->dma_adc.dmasize-1, s->vcbase+4);
+	outb(0, s->ddmabase+0xd);  /* clear */
+	outb(1, s->ddmabase+0xf); /* mask */
+	/*outb(0, s->ddmabase+8);*/  /* enable (enable is active low!) */
+	outb(0x54, s->ddmabase+0xb);  /* DMA_MODE_READ | DMA_MODE_AUTOINIT */
+	outl(va, s->ddmabase);
+	outw(s->dma_adc.dmasize-1, s->ddmabase+4);
 	c = - s->dma_adc.fragsamples;
 	write_ctrl(s, 0xa4, c);
 	write_ctrl(s, 0xa5, c >> 8);
-	outb(0, s->vcbase+0xf);
+	outb(0, s->ddmabase+0xf);
 	s->dma_adc.ready = 1;
 	return 0;
 }
@@ -513,12 +511,12 @@
 
 	/* update ADC pointer */
 	if (s->ena & FMODE_READ) {
-		hwptr = (s->dma_adc.dmasize - 1 - inw(s->vcbase+4)) % s->dma_adc.dmasize;
+		hwptr = (s->dma_adc.dmasize - 1 - inw(s->ddmabase+4)) % s->dma_adc.dmasize;
                 diff = (s->dma_adc.dmasize + hwptr - s->dma_adc.hwptr) % s->dma_adc.dmasize;
                 s->dma_adc.hwptr = hwptr;
 		s->dma_adc.total_bytes += diff;
 		s->dma_adc.count += diff;
-#ifdef DEBUGREC
+#if 0
 		printk(KERN_DEBUG "solo1: rd: hwptr %u swptr %u dmasize %u count %u\n",
 		       s->dma_adc.hwptr, s->dma_adc.swptr, s->dma_adc.dmasize, s->dma_adc.count);
 #endif
@@ -633,16 +631,28 @@
 		SOUND_MASK_MIC, SOUND_MASK_MIC, SOUND_MASK_CD, SOUND_MASK_VOLUME,
 		SOUND_MASK_MIC, 0, SOUND_MASK_LINE, 0
 	};
-	static const unsigned char mixtable[SOUND_MIXER_NRDEVICES] = {
-		[SOUND_MIXER_PCM]    = 0x7c,   /* voice */
-		[SOUND_MIXER_SYNTH]  = 0x36,   /* FM */
-		[SOUND_MIXER_CD]     = 0x38,   /* CD */
-		[SOUND_MIXER_LINE]   = 0x3e,   /* Line */
-		[SOUND_MIXER_LINE1]  = 0x3a,   /* AUX */
-		[SOUND_MIXER_MIC]    = 0x1a,   /* Mic */
-		[SOUND_MIXER_LINE2]  = 0x6d    /* Mono in */
+	static const unsigned char mixtable1[SOUND_MIXER_NRDEVICES] = {
+		[SOUND_MIXER_PCM]     = 1,   /* voice */
+		[SOUND_MIXER_SYNTH]   = 2,   /* FM */
+		[SOUND_MIXER_CD]      = 3,   /* CD */
+		[SOUND_MIXER_LINE]    = 4,   /* Line */
+		[SOUND_MIXER_LINE1]   = 5,   /* AUX */
+		[SOUND_MIXER_MIC]     = 6,   /* Mic */
+		[SOUND_MIXER_LINE2]   = 7,   /* Mono in */
+		[SOUND_MIXER_SPEAKER] = 8,   /* Speaker */
+		[SOUND_MIXER_RECLEV]  = 9,   /* Recording level */
+		[SOUND_MIXER_VOLUME]  = 10   /* Master Volume */
 	};
-	unsigned char l, r, rl, rr;
+	static const unsigned char mixreg[] = {
+		0x7c,   /* voice */
+		0x36,   /* FM */
+		0x38,   /* CD */
+		0x3e,   /* Line */
+		0x3a,   /* AUX */
+		0x1a,   /* Mic */
+		0x6d    /* Mono in */
+	};
+	unsigned char l, r, rl, rr, vidx;
 	int i, val;
 
 	VALIDATE_STATE(s);
@@ -657,16 +667,6 @@
 		val = (read_mixer(s, 0x7d) & 0x08) ? 1 : 0;
 		return put_user(val, (int *)arg);
 	}
-	if (cmd == SOUND_MIXER_PRIVATE1) {
-		/* enable/disable/query mixer preamp */
-		get_user_ret(val, (int *)arg, -EFAULT);
-		if (val != -1) {
-			val = val ? 0xff : 0xf7;
-			write_mixer(s, 0x7d, (read_mixer(s, 0x7d) | 0x08) & val);
-		}
-		val = (read_mixer(s, 0x7d) & 0x08) ? 1 : 0;
-		return put_user(val, (int *)arg);
-	}
 	if (cmd == SOUND_MIXER_PRIVATE2) {
 		/* enable/disable/query spatializer */
 		get_user_ret(val, (int *)arg, -EFAULT);
@@ -720,36 +720,11 @@
                 case SOUND_MIXER_CAPS:
 			return put_user(SOUND_CAP_EXCL_INPUT, (int *)arg);
 
-		case SOUND_MIXER_VOLUME:
-			rl = read_mixer(s, 0x60);
-			rr = read_mixer(s, 0x62);
-			l = (rl * 3 + 11) / 2;
-			if (rl & 0x40)
-				l = 0;
-			r = (rr * 3 + 11) / 2;
-			if (rr & 0x40)
-				r = 0;
-			return put_user((((unsigned int)r) << 8) | l, (int *)arg);
-
-		case SOUND_MIXER_SPEAKER:
-			rl = read_mixer(s, 0x3c);
-			l = (rl & 7) * 14 + 2;
-			return put_user(l * 0x101, (int *)arg);
-
-		case SOUND_MIXER_RECLEV:
-			rl = read_ctrl(s, 0xb4);
-			r = ((rl & 0xf) * 13 + 5) / 2;
-			l = (((rl >> 4) & 0xf) * 13 + 5) / 2;
-			return put_user((((unsigned int)r) << 8) | l, (int *)arg);
-
 		default:
 			i = _IOC_NR(cmd);
-                        if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i])
+                        if (i >= SOUND_MIXER_NRDEVICES || !(vidx = mixtable1[i]))
                                 return -EINVAL;
-			rl = read_mixer(s, mixtable[i]);
-			r = ((rl & 0xf) * 13 + 5) / 2;
-			l = (((rl >> 4) & 0xf) * 13 + 5) / 2;
-			return put_user((((unsigned int)r) << 8) | l, (int *)arg);
+			return put_user(s->mix.vol[vidx-1], (int *)arg);
 		}
 	}
         if (_IOC_DIR(cmd) != (_IOC_READ|_IOC_WRITE)) 
@@ -757,21 +732,21 @@
 	s->mix.modcnt++;
 	switch (_IOC_NR(cmd)) {
 	case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
-
-	{
-		static const unsigned char regs[] = {
-			0x1c, 0x1a, 0x36, 0x38, 0x3a, 0x3c, 0x3e, 0x60, 0x62, 0x6d, 0x7c
-		};
-		int i;
-
-		for (i = 0; i < sizeof(regs); i++)
-			printk(KERN_DEBUG "solo1: mixer reg 0x%02x: 0x%02x\n",
-			       regs[i], read_mixer(s, regs[i]));
-		printk(KERN_DEBUG "solo1: ctrl reg 0x%02x: 0x%02x\n",
-		       0xb4, read_ctrl(s, 0xb4));
-	} 
-
-		get_user_ret(val, (int *)arg, -EFAULT);
+#if 0
+	        {
+			static const unsigned char regs[] = {
+				0x1c, 0x1a, 0x36, 0x38, 0x3a, 0x3c, 0x3e, 0x60, 0x62, 0x6d, 0x7c
+			};
+			int i;
+			
+			for (i = 0; i < sizeof(regs); i++)
+				printk(KERN_DEBUG "solo1: mixer reg 0x%02x: 0x%02x\n",
+				       regs[i], read_mixer(s, regs[i]));
+			printk(KERN_DEBUG "solo1: ctrl reg 0x%02x: 0x%02x\n",
+			       0xb4, read_ctrl(s, 0xb4));
+		}
+#endif
+	        get_user_ret(val, (int *)arg, -EFAULT);
                 i = hweight32(val);
                 if (i == 0)
                         return 0;
@@ -810,7 +785,12 @@
 		}
 		write_mixer(s, 0x60, rl);
 		write_mixer(s, 0x62, rr);
-		return put_user((((unsigned int)r) << 8) | l, (int *)arg);
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
+                s->mix.vol[9] = ((unsigned int)r << 8) | l;
+#else
+                s->mix.vol[9] = val;
+#endif
+		return put_user(s->mix.vol[9], (int *)arg);
 
 	case SOUND_MIXER_SPEAKER:
 		get_user_ret(val, (int *)arg, -EFAULT);
@@ -822,7 +802,12 @@
 		rl = (l - 2) / 14;
 		l = rl * 14 + 2;
 		write_mixer(s, 0x3c, rl);
-		return put_user(l * 0x101, (int *)arg);
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
+                s->mix.vol[7] = l * 0x101;
+#else
+                s->mix.vol[7] = val;
+#endif
+		return put_user(s->mix.vol[7], (int *)arg);
 
 	case SOUND_MIXER_RECLEV:
 		get_user_ret(val, (int *)arg, -EFAULT);
@@ -841,11 +826,16 @@
 		r = (rl * 13 + 5) / 2;
 		l = (rr * 13 + 5) / 2;
 		write_ctrl(s, 0xb4, (rl << 4) | rr);
-		return put_user((((unsigned int)r) << 8) | l, (int *)arg);
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
+                s->mix.vol[8] = ((unsigned int)r << 8) | l;
+#else
+                s->mix.vol[8] = val;
+#endif
+		return put_user(s->mix.vol[8], (int *)arg);
 
 	default:
 		i = _IOC_NR(cmd);
-		if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i])
+		if (i >= SOUND_MIXER_NRDEVICES || !(vidx = mixtable1[i]))
 			return -EINVAL;
 		get_user_ret(val, (int *)arg, -EFAULT);
 		l = (val << 1) & 0x1fe;
@@ -862,8 +852,13 @@
 		rr = (r - 5) / 13;
 		r = (rl * 13 + 5) / 2;
 		l = (rr * 13 + 5) / 2;
-		write_mixer(s, mixtable[i], (rl << 4) | rr);
-		return put_user((((unsigned int)r) << 8) | l, (int *)arg);
+		write_mixer(s, mixreg[vidx-1], (rl << 4) | rr);
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
+                s->mix.vol[vidx-1] = ((unsigned int)r << 8) | l;
+#else
+                s->mix.vol[vidx-1] = val;
+#endif
+		return put_user(s->mix.vol[vidx-1], (int *)arg);
 	}
 }
 
@@ -919,10 +914,8 @@
 	NULL,  /* fsync */
 	NULL,  /* fasync */
 	NULL,  /* check_media_change */
-#if 0
 	NULL,  /* revalidate */
 	NULL,  /* lock */
-#endif
 };
 
 /* --------------------------------------------------------------------- */
@@ -931,7 +924,8 @@
 {
 	DECLARE_WAITQUEUE(wait, current);
 	unsigned long flags;
-	int count, tmo;
+	int count;
+	unsigned tmo;
 	
 	if (s->dma_dac.mapped)
 		return 0;
@@ -950,12 +944,12 @@
                         current->state = TASK_RUNNING;
                         return -EBUSY;
                 }
-		tmo = (count * HZ) / s->rate;
+		tmo = 3 * HZ * (count + s->dma_dac.fragsize) / 2 / s->rate;
 		if (s->fmt & (AFMT_S16_LE | AFMT_U16_LE))
 			tmo >>= 1;
 		if (s->channels > 1)
 			tmo >>= 1;
-                if (!schedule_timeout(tmo ? : 1) && tmo)
+                if (!schedule_timeout(tmo + 1))
                         printk(KERN_DEBUG "solo1: dma timed out??\n");
         }
         remove_wait_queue(&s->dma_dac.wait, &wait);
@@ -996,7 +990,7 @@
 			cnt = count;
 #ifdef DEBUGREC
 		printk(KERN_DEBUG "solo1_read: reg B8: 0x%02x  DMAstat: 0x%02x  DMAcnt: 0x%04x  SBstat: 0x%02x  cnt: %u\n", 
-		       read_ctrl(s, 0xb8), inb(s->vcbase+8), inw(s->vcbase+4), inb(s->sbbase+0xc), cnt);
+		       read_ctrl(s, 0xb8), inb(s->ddmabase+8), inw(s->ddmabase+4), inb(s->sbbase+0xc), cnt);
 #endif
 		if (cnt <= 0) {
 			start_adc(s);
@@ -1007,12 +1001,10 @@
 			       KERN_DEBUG "solo1_read: SBstat: 0x%02x  cnt: %u\n",
 			       read_ctrl(s, 0xa1), read_ctrl(s, 0xa2), read_ctrl(s, 0xa4), read_ctrl(s, 0xa5), read_ctrl(s, 0xa8), 
 			       read_ctrl(s, 0xb1), read_ctrl(s, 0xb2), read_ctrl(s, 0xb7), read_ctrl(s, 0xb8), read_ctrl(s, 0xb9), 
-			       inl(s->vcbase), inw(s->vcbase+4), inb(s->vcbase+8), inb(s->vcbase+15), inb(s->sbbase+0xc), cnt);
+			       inl(s->ddmabase), inw(s->ddmabase+4), inb(s->ddmabase+8), inb(s->ddmabase+15), inb(s->sbbase+0xc), cnt);
 #endif
-			if (inb(s->vcbase+15) & 1) {
+			if (inb(s->ddmabase+15) & 1)
 				printk(KERN_ERR "solo1: cannot start recording, DDMA mask bit stuck at 1\n");
-				return -EIO;
-			}
 			if (file->f_flags & O_NONBLOCK)
 				return ret ? ret : -EAGAIN;
 			interruptible_sleep_on(&s->dma_adc.wait);
@@ -1023,7 +1015,7 @@
 			       KERN_DEBUG "solo1_read: SBstat: 0x%02x  cnt: %u\n",
 			       read_ctrl(s, 0xa1), read_ctrl(s, 0xa2), read_ctrl(s, 0xa4), read_ctrl(s, 0xa5), read_ctrl(s, 0xa8), 
 			       read_ctrl(s, 0xb1), read_ctrl(s, 0xb2), read_ctrl(s, 0xb7), read_ctrl(s, 0xb8), read_ctrl(s, 0xb9), 
-			       inl(s->vcbase), inw(s->vcbase+4), inb(s->vcbase+8), inb(s->vcbase+15), inb(s->sbbase+0xc), cnt);
+			       inl(s->ddmabase), inw(s->ddmabase+4), inb(s->ddmabase+8), inb(s->ddmabase+15), inb(s->sbbase+0xc), cnt);
 #endif
 			if (signal_pending(current))
 				return ret ? ret : -ERESTARTSYS;
@@ -1042,7 +1034,7 @@
 		start_adc(s);
 #ifdef DEBUGREC
 		printk(KERN_DEBUG "solo1_read: reg B8: 0x%02x  DMAstat: 0x%02x  DMAcnt: 0x%04x  SBstat: 0x%02x\n", 
-		       read_ctrl(s, 0xb8), inb(s->vcbase+8), inw(s->vcbase+4), inb(s->sbbase+0xc));
+		       read_ctrl(s, 0xb8), inb(s->ddmabase+8), inw(s->ddmabase+4), inb(s->sbbase+0xc));
 #endif
 	}
 	return ret;
@@ -1304,7 +1296,7 @@
 				if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
 					return ret;
 				start_adc(s);
-				if (inb(s->vcbase+15) & 1)
+				if (inb(s->ddmabase+15) & 1)
 					printk(KERN_ERR "solo1: cannot start recording, DDMA mask bit stuck at 1\n");
 			} else
 				stop_adc(s);
@@ -1466,8 +1458,8 @@
 	}
 	if (file->f_mode & FMODE_READ) {
 		stop_adc(s);
-		outb(1, s->vcbase+0xf); /* mask DMA channel */
-		//outb(0, s->vcbase+0xd); /* DMA master clear */
+		outb(1, s->ddmabase+0xf); /* mask DMA channel */
+		outb(0, s->ddmabase+0xd); /* DMA master clear */
 		dealloc_dmabuf(&s->dma_adc);
 	}
 	s->open_mode &= ~(FMODE_READ | FMODE_WRITE);
@@ -1533,10 +1525,8 @@
 	NULL,  /* fsync */
 	NULL,  /* fasync */
 	NULL,  /* check_media_change */
-#if 0
 	NULL,  /* revalidate */
 	NULL,  /* lock */
-#endif
 };
 
 /* --------------------------------------------------------------------- */
@@ -1550,7 +1540,7 @@
 	if (!(s->mpubase))
 		return;
 	wake = 0;
-	while (inb(s->mpubase+1) & 0x80) {
+	while (!(inb(s->mpubase+1) & 0x80)) {
 		ch = inb(s->mpubase);
 		if (s->midi.icnt < MIDIINBUF) {
 			s->midi.ibuf[s->midi.iwr] = ch;
@@ -1562,7 +1552,7 @@
 	if (wake)
 		wake_up(&s->midi.iwait);
 	wake = 0;
-	while ((inb(s->mpubase+1) & 0x40) && s->midi.ocnt > 0) {
+	while (!(inb(s->mpubase+1) & 0x40) && s->midi.ocnt > 0) {
 		outb(s->midi.obuf[s->midi.ord], s->mpubase);
 		s->midi.ord = (s->midi.ord + 1) % MIDIOUTBUF;
 		s->midi.ocnt--;
@@ -1577,22 +1567,12 @@
 {
         struct solo1_state *s = (struct solo1_state *)dev_id;
 	unsigned int intsrc;
-
-	static unsigned lim = 0;
 	
 	/* fastpath out, to ease interrupt sharing */
 	intsrc = inb(s->iobase+7); /* get interrupt source(s) */
 	if (!intsrc)
 		return;
 	(void)inb(s->sbbase+0xe);  /* clear interrupt */
-#ifdef DEBUGREC
-	if (intsrc & 0x10 && lim < 20) {
-		lim++;
-		printk(KERN_DEBUG "solo1: audio1int reg B8: 0x%02x  DMAstat: 0x%02x  DMAcnt: 0x%04x  SBstat: 0x%02x\n", 
-		       read_ctrl(s, 0xb8), inb(s->vcbase+8), inw(s->vcbase+4), inb(s->sbbase+0xc));
-	}
-	//printk(KERN_DEBUG "solo1: interrupt 0x%02x\n", intsrc);
-#endif
 	spin_lock(&s->lock);
 	/* clear audio interrupts first */
 	if (intsrc & 0x20)
@@ -1849,10 +1829,8 @@
 	NULL,  /* fsync */
 	NULL,  /* fasync */
 	NULL,  /* check_media_change */
-#if 0
 	NULL,  /* revalidate */
 	NULL,  /* lock */
-#endif
 };
 
 /* --------------------------------------------------------------------- */
@@ -2025,10 +2003,8 @@
 	NULL,  /* fsync */
 	NULL,  /* fasync */
 	NULL,  /* check_media_change */
-#if 0
 	NULL,  /* revalidate */
 	NULL,  /* lock */
-#endif
 };
 
 /* --------------------------------------------------------------------- */
@@ -2060,11 +2036,10 @@
 	struct pci_dev *pcidev = NULL;
 	mm_segment_t fs;
 	int i, val, index = 0;
-	u16 ddmabase;
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "solo1: version v0.5 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "solo1: version v0.6 time " __TIME__ " " __DATE__ "\n");
 	while (index < NR_DEVICE && 
 	       (pcidev = pci_find_device(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_SOLO1, pcidev))) {
 		if (pcidev->resource[0].start == 0 ||
@@ -2090,35 +2065,32 @@
 		init_waitqueue_head(&s->midi.owait);
 		init_MUTEX(&s->open_sem);
 		s->magic = SOLO1_MAGIC;
+		s->pcidev = pcidev;
 		s->iobase = pcidev->resource[0].start;
 		s->sbbase = pcidev->resource[1].start;
 		s->vcbase = pcidev->resource[2].start;
+		s->ddmabase = s->vcbase + DDMABASE_OFFSET;
 		s->mpubase = pcidev->resource[3].start;
 		s->gpbase = pcidev->resource[4].start;
 		s->irq = pcidev->irq;
 		if (check_region(s->iobase, IOBASE_EXTENT) ||
 		    check_region(s->sbbase, SBBASE_EXTENT) ||
-		    check_region(s->vcbase, VCBASE_EXTENT) ||
+		    check_region(s->ddmabase, DDMABASE_EXTENT) ||
 		    check_region(s->mpubase, MPUBASE_EXTENT)) {
 			printk(KERN_ERR "solo1: io ports in use\n");
 			goto err_region;
 		}
 		request_region(s->iobase, IOBASE_EXTENT, "ESS Solo1");
 		request_region(s->sbbase, SBBASE_EXTENT, "ESS Solo1");
-		request_region(s->vcbase, VCBASE_EXTENT, "ESS Solo1");
+		request_region(s->ddmabase, DDMABASE_EXTENT, "ESS Solo1");
 		request_region(s->mpubase, MPUBASE_EXTENT, "ESS Solo1");
 		if (request_irq(s->irq, solo1_interrupt, SA_SHIRQ, "ESS Solo1", s)) {
 			printk(KERN_ERR "solo1: irq %u in use\n", s->irq);
 			goto err_irq;
 		}
 		/* initialize DDMA base address */
-		/* use PCI config reg, and not vcbase, we need the bus view */
-		pci_read_config_word(pcidev, 0x18, &ddmabase);
-		pci_write_config_word(pcidev, 0x60, (ddmabase & (~0xf)) | 1);
-#ifdef DEBUGREC
-		printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x\n", 
-		       inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
-#endif
+		printk(KERN_DEBUG "solo1: ddma base address: 0x%lx\n", s->ddmabase);
+		pci_write_config_word(pcidev, 0x60, (s->ddmabase & (~0xf)) | 1);
 		/* set DMA policy to DDMA, IRQ emulation off (CLKRUN disabled for now) */
 		pci_write_config_dword(pcidev, 0x50, 0);
 		/* disable legacy audio address decode */
@@ -2147,21 +2119,9 @@
 		write_mixer(s, 0x52, 0);
 		write_mixer(s, 0x14, 0);  /* DAC1 minimum volume */
 		write_mixer(s, 0x71, 0x20); /* enable new 0xA1 reg format */
-#ifdef DEBUGREC
-		printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x\n", 
-		       inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
-#endif
-		outb(0, s->vcbase+0xd); /* DMA master clear */
-#ifdef DEBUGREC
-		printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x\n", 
-		       inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
-#endif
-		outb(1, s->vcbase+0xf); /* mask channel */
-#ifdef DEBUGREC
-		printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x\n", 
-		       inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
-#endif
-		//outb(0, s->vcbase+0x8); /* enable controller (enable is low active!!) */
+		outb(0, s->ddmabase+0xd); /* DMA master clear */
+		outb(1, s->ddmabase+0xf); /* mask channel */
+		/*outb(0, s->ddmabase+0x8);*/ /* enable controller (enable is low active!!) */
 
 		pci_set_master(pcidev);  /* enable bus mastering */
 		
@@ -2173,6 +2133,8 @@
 			val = initvol[i].vol;
 			mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
 		}
+		val = 1; /* enable mic preamp */
+		mixer_ioctl(s, SOUND_MIXER_PRIVATE1, (unsigned long)&val);
 		set_fs(fs);
 		/* queue it for later freeing */
 		s->next = devs;
@@ -2192,7 +2154,7 @@
 	err_irq:
 		release_region(s->iobase, IOBASE_EXTENT);
 		release_region(s->sbbase, SBBASE_EXTENT);
-		release_region(s->vcbase, VCBASE_EXTENT);
+		release_region(s->ddmabase, DDMABASE_EXTENT);
 		release_region(s->mpubase, MPUBASE_EXTENT);
 	err_region:
 		kfree_s(s, sizeof(struct solo1_state));
@@ -2215,13 +2177,14 @@
 		devs = devs->next;
 		/* stop DMA controller */
 		outb(0, s->iobase+6);
-		outb(0, s->vcbase+0xd); /* DMA master clear */
+		outb(0, s->ddmabase+0xd); /* DMA master clear */
 		outb(3, s->sbbase+6); /* reset sequencer and FIFO */
 		synchronize_irq();
+		pci_write_config_word(s->pcidev, 0x60, 0); /* turn off DDMA controller address space */
 		free_irq(s->irq, s);
 		release_region(s->iobase, IOBASE_EXTENT);
 		release_region(s->sbbase, SBBASE_EXTENT);
-		release_region(s->vcbase, VCBASE_EXTENT);
+		release_region(s->ddmabase, DDMABASE_EXTENT);
 		release_region(s->mpubase, MPUBASE_EXTENT);
 		unregister_sound_dsp(s->dev_audio);
 		unregister_sound_mixer(s->dev_mixer);
diff -u --recursive --new-file v2.3.13/linux/drivers/sound/lowlevel/awe_compat-fbsd.h linux/drivers/sound/lowlevel/awe_compat-fbsd.h
--- v2.3.13/linux/drivers/sound/lowlevel/awe_compat-fbsd.h	Mon Aug  9 14:59:23 1999
+++ linux/drivers/sound/lowlevel/awe_compat-fbsd.h	Wed Dec 31 16:00:00 1969
@@ -1,173 +0,0 @@
-/*
- * sound/awe_compat.h
- *
- * Compat defines for the AWE32/SB32/AWE64 wave table synth driver.
- *   version 0.4.3; Nov. 1, 1998
- *
- * Copyright (C) 1996-1998 Takashi Iwai
- *
- * 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 AWE_COMPAT_H_DEF
-#define AWE_COMPAT_H_DEF
-
-/*================================================================
- * version check
- *================================================================*/
-
-/* FreeBSD version check */
-#include <i386/isa/sound/awe_config.h>
-
-#define AWE_OBSOLETE_VOXWARE
-#if __FreeBSD__ >= 2
-#  include <osreldate.h>
-#  if __FreeBSD_version >= 300000
-#    undef AWE_OBSOLETE_VOXWARE
-#  endif
-#endif
-#ifdef __linux__
-#  include <linux/config.h>
-#endif
-
-
-/*================================================================
- * INCLUDE OTHER HEADER FILES
- *================================================================*/
-
-/* reading configuration of sound driver */
-
-#ifdef AWE_OBSOLETE_VOXWARE
-
-#include <i386/isa/sound/sound_config.h>
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_AWE32)
-#define CONFIG_AWE32_SYNTH
-#endif
-
-#else /* AWE_OBSOLETE_VOXWARE */
-
-#ifdef HAS_LOWLEVEL_H
-#include "lowlevel.h"
-#endif
-
-#include <i386/isa/sound/sound_config.h>
-#if defined(CONFIGURE_SOUNDCARD) && defined(CONFIG_AWE32)
-#  define CONFIG_AWE32_SYNTH
-#endif
-
-#endif /* AWE_OBSOLETE_VOXWARE */
-
-
-/*================================================================
- * include AWE header files
- *================================================================*/
-
-#if defined(CONFIG_AWE32_SYNTH) || defined(CONFIG_AWE32_SYNTH_MODULE)
-
-#include <i386/isa/sound/awe_hw.h>
-#include <i386/isa/sound/awe_version.h>
-#include <i386/isa/sound/awe_voice.h>
-
-#ifdef AWE_HAS_GUS_COMPATIBILITY
-/* include finetune table */
-#ifdef AWE_OBSOLETE_VOXWARE
-#  define SEQUENCER_C
-#endif
-#include <i386/isa/sound/tuning.h>
-#include <machine/ultrasound.h>
-#endif /* AWE_HAS_GUS_COMPATIBILITY */
-
-
-/*----------------------------------------------------------------
- * compatibility macros for AWE32 driver
- *----------------------------------------------------------------*/
-
-/* redefine following macros */
-#undef IOCTL_IN
-#undef IOCTL_OUT
-#undef OUTW
-#undef COPY_FROM_USER
-#undef COPY_TO_USER
-#undef GET_BYTE_FROM_USER
-#undef GET_SHORT_FROM_USER
-#undef IOCTL_TO_USER
-  
-/* inline is not checked yet.. maybe it'll work */
-#define INLINE	/*inline*/
-
-#define KERN_WARNING /**/
-
-/*----------------------------------------------------------------
- * memory management for freebsd
- *----------------------------------------------------------------*/
-
-/* i/o requests; nothing */
-#define awe_check_port()	0	/* always false */
-#define awe_request_region()	/* nothing */
-#define awe_release_region()	/* nothing */
-
-#define AWE_DYNAMIC_BUFFER
-
-#define my_malloc_init(ptr)	/* nothing */
-#define my_malloc_memptr()	0
-#define my_malloc(size)		malloc(size, M_TEMP, M_WAITOK)
-#define my_free(ptr)		if (ptr) {free(ptr, M_TEMP);}
-
-#define INIT_TABLE(buffer,index,nums,type) {buffer=NULL; index=0;}
-
-/*----------------------------------------------------------------
- * i/o interfaces for freebsd
- *----------------------------------------------------------------*/
-
-/* according to linux rule; the arguments are swapped */
-#define OUTW(data,addr)		outw(addr, data)
-
-#define COPY_FROM_USER(target,source,offs,count) \
-	uiomove(((caddr_t)(target)),(count),((struct uio *)(source)))
-#define COPY_TO_USER(target,source,offs,count) \
-	uiomove(((caddr_t)(source)),(count),((struct uio *)(target)))
-#define GET_BYTE_FROM_USER(target,addr,offs) \
-	uiomove(((char*)&(target)), 1, ((struct uio *)(addr)))
-#define GET_SHORT_FROM_USER(target,addr,offs) \
-	uiomove(((char*)&(target)), 2, ((struct uio *)(addr)))
-#define IOCTL_TO_USER(target,offs,source,count) \
-	memcpy(&((target)[offs]), (source), (count))
-#define IO_WRITE_CHECK(cmd)	(cmd & IOC_IN)
-#define IOCTL_IN(arg)		(*(int*)(arg))
-#define IOCTL_OUT(arg,val)	(*(int*)(arg) = (val))
-#define BZERO(target,len)	bzero((caddr_t)target, len)
-#define MEMCPY(dst,src,len)	bcopy((caddr_t)src, (caddr_t)dst, len)
-
-#ifndef AWE_OBSOLETE_VOXWARE
-#  define printk printf
-#  define RET_ERROR(err)		-err
-#endif
-
-
-/* old style device tables (not modulized) */
-#define sound_alloc_synthdev() \
-	(num_synths >= MAX_SYNTH_DEV ? -1 : num_synths++)
-#define sound_alloc_mixerdev() \
-	(num_mixers >= MAX_MIXER_DEV ? -1 : num_mixers++)
-#define sound_alloc_mididev() \
-	(num_midis >= MAX_MIXER_DEV ? -1 : num_midis++)
-#define sound_unload_synthdev(dev)	/**/
-#define sound_unload_mixerdev(dev)	/**/
-#define sound_unload_mididev(dev)	/**/
-
-
-#endif /* CONFIG_AWE32_SYNTH */
-
-#endif /* AWE_COMPAT_H_DEF */
diff -u --recursive --new-file v2.3.13/linux/drivers/sound/lowlevel/awe_compat-linux.h linux/drivers/sound/lowlevel/awe_compat-linux.h
--- v2.3.13/linux/drivers/sound/lowlevel/awe_compat-linux.h	Wed Dec 16 12:52:01 1998
+++ linux/drivers/sound/lowlevel/awe_compat-linux.h	Wed Dec 31 16:00:00 1969
@@ -1,248 +0,0 @@
-/*
- * sound/awe_compat.h
- *
- * Compat defines for the AWE32/SB32/AWE64 wave table synth driver.
- *   version 0.4.3; Oct. 1, 1998
- *
- * Copyright (C) 1996-1998 Takashi Iwai
- *
- * 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 AWE_COMPAT_H_DEF
-#define AWE_COMPAT_H_DEF
-
-/*================================================================
- * version check
- *================================================================*/
-
-#include "awe_config.h"
-
-#define ASC_LINUX_VERSION(V,P,S)    (((V) * 65536) + ((P) * 256) + (S))
-
-#ifndef LINUX_VERSION_CODE
-#include <linux/version.h>
-#endif
-
-/* linux version check */
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
-#define AWE_OBSOLETE_VOXWARE
-#endif
-
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,0)
-#define AWE_NEW_KERNEL_INTERFACE
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,80)
-#define AWE_MODULE_SUPPORT
-#endif
-#endif
-
-#ifdef AWE_OBSOLETE_VOXWARE
-#include "soundvers.h"
-#else
-#include "../soundvers.h"
-#endif
-
-#if defined(SOUND_INTERNAL_VERSION) && SOUND_INTERNAL_VERSION >= 0x30803
-/* OSS/Free-3.8 */
-#define AWE_NO_PATCHMGR
-#define AWE_OSS38
-#define HAS_LOWLEVEL_H
-#endif
-
-/*================================================================
- * INCLUDE OTHER HEADER FILES
- *================================================================*/
-
-/* set up module */
-
-#if defined(AWE_MODULE_SUPPORT) && defined(MODULE)
-#include <linux/config.h>
-#include <linux/string.h>
-#include <linux/module.h>
-#include "../soundmodule.h"
-#endif
-
-
-/* reading configuration of sound driver */
-
-#ifdef AWE_OBSOLETE_VOXWARE
-
-#include "sound_config.h"
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_AWE32)
-#define CONFIG_AWE32_SYNTH
-#endif
-
-#else /* AWE_OBSOLETE_VOXWARE */
-
-#ifdef HAS_LOWLEVEL_H
-#include "lowlevel.h"
-#endif
-
-#include "../sound_config.h"
-
-#endif /* AWE_OBSOLETE_VOXWARE */
-
-
-/*================================================================
- * include AWE header files
- *================================================================*/
-
-#if defined(CONFIG_AWE32_SYNTH) || defined(CONFIG_AWE32_SYNTH_MODULE)
-
-#include "awe_hw.h"
-#include "awe_version.h"
-#include <linux/awe_voice.h>
-
-#ifdef AWE_HAS_GUS_COMPATIBILITY
-/* include finetune table */
-#ifdef AWE_OBSOLETE_VOXWARE
-#  include "tuning.h"
-#else
-#  include "../tuning.h"
-#endif
-#include <linux/ultrasound.h>
-#endif /* AWE_HAS_GUS_COMPATIBILITY */
-
-
-/*----------------------------------------------------------------
- * compatibility macros for AWE32 driver
- *----------------------------------------------------------------*/
-
-/* redefine following macros */
-#undef IOCTL_IN
-#undef IOCTL_OUT
-#undef OUTW
-#undef COPY_FROM_USER
-#undef COPY_TO_USER
-#undef GET_BYTE_FROM_USER
-#undef GET_SHORT_FROM_USER
-#undef IOCTL_TO_USER
-  
-/* use inline prefix */
-#define INLINE	inline
-
-/*----------------------------------------------------------------
- * memory management for linux
- *----------------------------------------------------------------*/
-
-#ifdef AWE_OBSOLETE_VOXWARE
-/* old type linux system */
-
-/* i/o requests; nothing */
-#define awe_check_port()	0	/* always false */
-#define awe_request_region()	/* nothing */
-#define awe_release_region()	/* nothing */
-
-static int _mem_start;  /* memory pointer for permanent buffers */
-
-#define my_malloc_init(memptr)	_mem_start = (memptr)
-#define my_malloc_memptr()	_mem_start
-#define my_free(ptr)	/* do nothing */
-
-/* allocate buffer only once */
-#define INIT_TABLE(buffer,index,nums,type) {\
-PERMANENT_MALLOC(buffer, char*, size, _mem_start); index = (nums);\
-}
-
-#else
-
-#define AWE_DYNAMIC_BUFFER
-
-#define my_malloc_init(ptr)	/* nothing */
-#define my_malloc_memptr()	0
-#define my_malloc(size)		vmalloc(size)
-#define my_free(ptr)		if (ptr) {vfree(ptr);}
-
-/* do not allocate buffer at beginning */
-#define INIT_TABLE(buffer,index,nums,type) {buffer=NULL; index=0;}
-
-/* old type macro */
-#define RET_ERROR(err)		-err
-
-#endif
-
-/*----------------------------------------------------------------
- * i/o interfaces for linux
- *----------------------------------------------------------------*/
-
-#define OUTW(data,addr)		outw(data, addr)
-
-#ifdef AWE_NEW_KERNEL_INTERFACE
-#define COPY_FROM_USER(target,source,offs,count) \
-	copy_from_user(target, (source)+(offs), count)
-#define GET_BYTE_FROM_USER(target,addr,offs) \
-	get_user(target, (unsigned char*)&((addr)[offs]))
-#define GET_SHORT_FROM_USER(target,addr,offs) \
-	get_user(target, (unsigned short*)&((addr)[offs]))
-#ifdef AWE_OSS38
-#define IOCTL_TO_USER(target,offs,source,count) \
-	memcpy(target, (source)+(offs), count)
-#define IO_WRITE_CHECK(cmd)	(_SIOC_DIR(cmd) & _IOC_WRITE)
-#else
-#define IOCTL_TO_USER(target,offs,source,count) \
-	copy_to_user(target, (source)+(offs), count)
-#define IO_WRITE_CHECK(cmd)	(_IOC_DIR(cmd) & _IOC_WRITE)
-#endif /* AWE_OSS38 */
-#define COPY_TO_USER	IOCTL_TO_USER
-#define IOCTL_IN(arg)	(*(int*)(arg))
-#define IOCTL_OUT(arg,val) (*(int*)(arg) = (val))
-
-#else /* old type i/o */
-#define COPY_FROM_USER(target,source,offs,count) \
-	memcpy_fromfs(target, (source)+(offs), (count))
-#define GET_BYTE_FROM_USER(target,addr,offs) \
-	*((char  *)&(target)) = get_fs_byte((addr)+(offs))
-#define GET_SHORT_FROM_USER(target,addr,offs) \
-	*((short *)&(target)) = get_fs_word((addr)+(offs))
-#ifdef AWE_OSS38
-#define IOCTL_TO_USER(target,offs,source,count) \
-	memcpy(target, (source)+(offs), count)
-#define COPY_TO_USER(target,offs,source,count)  \
-	memcpy_tofs(target, (source)+(offs), (count))
-#define IOCTL_IN(arg)	(*(int*)(arg))
-#define IOCTL_OUT(arg,val) (*(int*)(arg) = (val))
-#define IO_WRITE_CHECK(cmd)	(_SIOC_DIR(cmd) & _IOC_WRITE)
-#else /* AWE_OSS38 */
-#define IOCTL_TO_USER(target,offs,source,count) \
-	memcpy_tofs(target, (source)+(offs), (count))
-#define COPY_TO_USER	IOCTL_TO_USER
-#define IOCTL_IN(arg)		get_fs_long((long *)(arg))
-#define IOCTL_OUT(arg,ret)	snd_ioctl_return((int *)arg, ret)
-#define IO_WRITE_CHECK(cmd)	(cmd & IOC_IN)
-#endif /* AWE_OSS38 */
-
-#endif /* AWE_NEW_KERNEL_INTERFACE */
-
-#define BZERO(target,len)	memset(target, 0, len)
-#define MEMCPY(dst,src,len)	memcpy(dst, src, len)
-
-/* old style device tables (not modulized) */
-#ifndef AWE_MODULE_SUPPORT
-
-#define sound_alloc_synthdev() \
-	(num_synths >= MAX_SYNTH_DEV ? -1 : num_synths++)
-#define sound_alloc_mixerdev() \
-	(num_mixers >= MAX_MIXER_DEV ? -1 : num_mixers++)
-#define sound_alloc_mididev() \
-	(num_midis >= MAX_MIXER_DEV ? -1 : num_midis++)
-#define sound_unload_synthdev(dev)	/**/
-#define sound_unload_mixerdev(dev)	/**/
-#define sound_unload_mididev(dev)	/**/
-
-#endif /* AWE_MODULE_SUPPORT */
-
-#endif /* CONFIG_AWE32_SYNTH */
-
-#endif /* AWE_COMPAT_H_DEF */
diff -u --recursive --new-file v2.3.13/linux/drivers/sound/sonicvibes.c linux/drivers/sound/sonicvibes.c
--- v2.3.13/linux/drivers/sound/sonicvibes.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/sound/sonicvibes.c	Thu Aug 12 12:21:48 1999
@@ -73,6 +73,7 @@
  *    28.06.99   0.16  Add pci_set_master
  *    03.08.99   0.17  adapt to Linus' new __setup/__initcall
  *                     added kernel command line options "sonicvibes=reverb" and "sonicvibesdmaio=dmaioaddr"
+ *    12.08.99   0.18  module_init/__setup fixes
  *
  */
 
@@ -1268,9 +1269,9 @@
                         current->state = TASK_RUNNING;
                         return -EBUSY;
                 }
-		tmo = (count * HZ) / s->ratedac;
+		tmo = 3 * HZ * (count + s->dma_dac.fragsize) / 2 / s->ratedac;
 		tmo >>= sample_shift[(s->fmt >> SV_CFMT_ASHIFT) & SV_CFMT_MASK];
-		if (!schedule_timeout(tmo ? : 1) && tmo)
+		if (!schedule_timeout(tmo + 1))
 			printk(KERN_DEBUG "sv: dma timed out??\n");
         }
         remove_wait_queue(&s->dma_dac.wait, &wait);
@@ -2297,6 +2298,19 @@
 
 static unsigned dmaio = 0xac00;
 
+MODULE_PARM(reverb, "1-" __MODULE_STRING(NR_DEVICE) "i");
+MODULE_PARM_DESC(reverb, "if 1 enables the reverb circuitry. NOTE: your card must have the reverb RAM");
+#if 0
+MODULE_PARM(wavetable, "1-" __MODULE_STRING(NR_DEVICE) "i");
+MODULE_PARM_DESC(wavetable, "if 1 the wavetable synth is enabled");
+#endif
+
+MODULE_PARM(dmaio, "i");
+MODULE_PARM_DESC(dmaio, "if the motherboard BIOS did not allocate DDMA io, allocate them starting at this address");
+
+MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
+MODULE_DESCRIPTION("S3 SonicVibes Driver");
+
 /* --------------------------------------------------------------------- */
 
 static struct initvol {
@@ -2314,10 +2328,7 @@
 	{ SOUND_MIXER_WRITE_PCM, 0x4040 }
 };
 
-#ifndef MODULE
-static
-#endif
-int __init init_module(void)
+static int __init init_sonicvibes(void)
 {
 	struct sv_state *s;
 	struct pci_dev *pcidev = NULL;
@@ -2326,7 +2337,7 @@
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "sv: version v0.17 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "sv: version v0.18 time " __TIME__ " " __DATE__ "\n");
 #if 0
 	if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT)))
 		printk(KERN_INFO "sv: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n");
@@ -2499,24 +2510,7 @@
 	return 0;
 }
 
-/* --------------------------------------------------------------------- */
-
-#ifdef MODULE
-
-MODULE_PARM(reverb, "1-" __MODULE_STRING(NR_DEVICE) "i");
-MODULE_PARM_DESC(reverb, "if 1 enables the reverb circuitry. NOTE: your card must have the reverb RAM");
-#if 0
-MODULE_PARM(wavetable, "1-" __MODULE_STRING(NR_DEVICE) "i");
-MODULE_PARM_DESC(wavetable, "if 1 the wavetable synth is enabled");
-#endif
-
-MODULE_PARM(dmaio, "i");
-MODULE_PARM_DESC(dmaio, "if the motherboard BIOS did not allocate DDMA io, allocate them starting at this address");
-
-MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
-MODULE_DESCRIPTION("S3 SonicVibes Driver");
-
-void cleanup_module(void)
+static void __exit cleanup_sonicvibes(void)
 {
 	struct sv_state *s;
 
@@ -2545,7 +2539,12 @@
 	printk(KERN_INFO "sv: unloading\n");
 }
 
-#else /* MODULE */
+module_init(init_sonicvibes);
+module_exit(cleanup_sonicvibes);
+
+/* --------------------------------------------------------------------- */
+
+#ifndef MODULE
 
 /* format is: sonicvibes=[reverb] sonicvibesdmaio=dmaioaddr */
 
@@ -2555,12 +2554,12 @@
 
 	if (nr_dev >= NR_DEVICE)
 		return 0;
-
-	(   (get_option(&str, &reverb   [nr_dev]) == 2)
 #if 0
-	 &&  get_option(&str, &wavetable[nr_dev])
+	if (get_option(&str, &reverb[nr_dev]) == 2)
+		get_option(&str, &wavetable[nr_dev]);
+#else
+	get_option(&str, &reverb[nr_dev]);
 #endif
-	};
 
 	nr_dev++;
 	return 1;
@@ -2568,16 +2567,14 @@
 
 static int __init sonicvibesdmaio_setup(char *str)
 {
-        int ints[11];
+        int io;
 
-        get_options(str, ints);
-	if (ints[0] >= 1)
-		dmaio = ints[1];
+	if (get_option(&str, &io))
+		dmaio = io;
 	return 1;
 }
 
 __setup("sonicvibes=", sonicvibes_setup);
 __setup("sonicvibesdmaio=", sonicvibesdmaio_setup);
-__initcall(init_module);
 
 #endif /* MODULE */
diff -u --recursive --new-file v2.3.13/linux/drivers/usb/Makefile linux/drivers/usb/Makefile
--- v2.3.13/linux/drivers/usb/Makefile	Mon Aug  9 14:59:23 1999
+++ linux/drivers/usb/Makefile	Fri Aug 13 11:54:47 1999
@@ -15,6 +15,7 @@
 L_TARGET := usb.a
 M_OBJS   :=
 L_OBJS   :=
+MOD_LIST_NAME := USB_MODULES
 
 ifeq ($(CONFIG_USB),y)
   L_OBJS +=usbcore.o
diff -u --recursive --new-file v2.3.13/linux/drivers/usb/README.ohci_hcd linux/drivers/usb/README.ohci_hcd
--- v2.3.13/linux/drivers/usb/README.ohci_hcd	Mon May 10 10:18:34 1999
+++ linux/drivers/usb/README.ohci_hcd	Wed Aug 18 16:22:23 1999
@@ -1,13 +1,13 @@
 
 The OHCI HCD layer is a simple but nearly complete implementation of what the
 USB people would call a HCD  for the OHCI. 
- (ISO comming soon, Bulk disabled, INT u. CTRL transfers enabled)
+ (ISO comming soon, Bulk, INT u. CTRL transfers enabled)
 It is based on Linus Torvalds UHCI code and Gregory Smith OHCI fragments (0.03 source tree).
 The layer (functions) on top of it, is for interfacing to the alternate-usb device-drivers. 
 
 - Roman Weissgaerber <weissg@vienna.at>
 
-
+ * v4.0 1999/08/18 removed all dummy eds, unlink unused eds, code cleanup, bulk transfers 
  * v2.1 1999/05/09 ep_addr correction, code cleanup
  * v0.2.0 1999/05/04 
  * everything has been moved into 2 files (ohci-hcd.c, ohci-hub-root.c and headers)
@@ -21,16 +21,14 @@
  * v0.1.0 1999/04/27 initial release
  
 to remove the module try:
-killall root-hub
-:
 rmmod usb-ohci-hcd
 
 Features:
 - virtual root hub, all basic hub descriptors and commands (state: complete) 
   this is an option now (v0.2.0)
   #define  CONFIG_USB_OHCI_VROOTHUB includes the virtual hub code, (VROOTHUB)
-  default is without. 
-  (at the moment: the Virtual Root Hub option is not recommended)
+  default is with. 
+  (at the moment: the Virtual Root Hub is included automatically)
   
   files: ohci-root-hub.c, ohci-root-hub.h 
  
@@ -41,6 +39,7 @@
  In the HCD layer the EDs has to be allocated manually either by calling a subroutine
  or by sending a USB root hub vendor specific command to the virtual root hub.
  At the alternate linux usb stack EDs will be added (allocated) at their first use.
+ ED will be unlinked from the HC chains if they are not bussy.
  
  files: ohci-hcd.c ohci-hcd.h
  routines:   (do not use for drivers, use the top layer alternate usb commands instead)
@@ -49,10 +48,10 @@
             int interval, int load, f_handler handler, int ep_size, int speed)
        adds an endpoint, (if the endpoint already exists some parameters will be updated)
        
- int usb_ohci_rm_ep(struct  usb_ohci_ed *ed, struct ohci * ohci) 
+ int usb_ohci_rm_ep( ) 
        removes an endpoint and all pending TDs of that EP
        
-  usb_ohci_rm_function( struct ohci * ohci, union ep_addr_ ep_addr)
+  usb_ohci_rm_function( )
        removes all Endpoints of a function (device)
 
 - Transfer Descriptors (TD): handling and allocation of TDs is transparent to the upper layers
@@ -62,7 +61,7 @@
 
   There is one basic command for all types of bus transfers (INT, BULK, ISO, CTRL):
   
-  int ohci_trans_req(struct ohci * ohci, int ep_addr, int ctrl_len, void  *ctrl, void * data, int data_len, __OHCI_BAG lw0, __OHCI_BAG lw1)
+  int ohci_trans_req(struct ohci * ohci, hcd_ed, int ctrl_len, void  *ctrl, void * data, int data_len, __OHCI_BAG lw0, __OHCI_BAG lw1)
   
   CTRL: ctrl, ctrl_len ... cmd buffer 
         data, data_len ... data buffer (in or out)
@@ -95,18 +94,5 @@
 - Done list handling: returns the requests (callback f_handler in ED) and does 
   some error handling, root-hub request dequeuing
   (files: ohci-done-list.c in ohci-hcd.c now(v0.2.0))
-
-ep_addr union or int  is for addressing devices&endpoints: 
-__u8 ep_addr.bep.ep ... bit 3..0  endpoint address
-						bit 4     0
-						bit 6,5  type: eg. 10 CTRL, 11 BULK, 01 INT, 00 ISO
-						bit 7	direction 1 IN, 0 OUT
-
-__u8 ep_addr.bep.fa ... bit 6..0  function address
-						bit 7	  0
-
-(__u8 ep_addr.bep.hc ... host controller nr) not used
-(__u8 ep_addr.bep.host ... host nr) not used
-
 
   
diff -u --recursive --new-file v2.3.13/linux/drivers/usb/audio.c linux/drivers/usb/audio.c
--- v2.3.13/linux/drivers/usb/audio.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/usb/audio.c	Mon Aug 16 23:19:13 1999
@@ -6,6 +6,7 @@
 #include <linux/module.h>
 
 #include "usb.h"
+#define AUDIO_DEBUG 1
 
 static int usb_audio_probe(struct usb_device *dev);
 static void usb_audio_disconnect(struct usb_device *dev);
@@ -35,23 +36,23 @@
 
 static int usb_audio_probe(struct usb_device *dev)
 {
-	struct usb_interface_descriptor *interface;
+	struct usb_interface_descriptor *intf_desc;
 	struct usb_endpoint_descriptor *endpoint;
 	struct usb_audio *aud;
+	int bEndpointAddress = 0;
 	int i;
 	int na=0;
 	
-	interface = &dev->config[0].altsetting[0].interface[0];
 
 	for (i=0; i<dev->config[0].bNumInterfaces; i++) {
-		endpoint = &interface->endpoint[i];
+		intf_desc = &dev->config->interface[i].altsetting[0];
 
-		if(interface->bInterfaceClass != 1) 
+		if(intf_desc->bInterfaceClass != 1) 
 	        	continue;
 
 		printk(KERN_INFO "USB audio device detected.\n");
 	
-		switch(interface->bInterfaceSubClass) {
+		switch(intf_desc->bInterfaceSubClass) {
 			case 0x01:
 				printk(KERN_INFO "audio: Control device.\n");
 				break;
@@ -74,8 +75,6 @@
         	aud->dev = dev;
         	dev->private = aud;
 
-		endpoint = &interface->endpoint[0];
-
 //        	if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) {
 //			printk (KERN_INFO " Failed usb_set_configuration: Audio\n");
 //			break;
@@ -83,11 +82,11 @@
 //        	usb_set_protocol(dev, 0);
 //        	usb_set_idle(dev, 0, 0);
         
-        	usb_request_irq(dev,
-                        usb_rcvctrlpipe(dev, endpoint->bEndpointAddress),
-                        usb_audio_irq,
-                        endpoint->bInterval,
-                        aud);
+//        	usb_request_irq(dev,
+//                        usb_rcvctrlpipe(dev, bEndpointAddress),
+//                        usb_audio_irq,
+//                        endpoint->bInterval,
+//                        aud);
 
 		list_add(&aud->list, &usb_audio_list);
 		
@@ -123,10 +122,16 @@
  
 void usb_audio_interface(struct usb_interface_descriptor *interface, u8 *data)
 {
+#ifdef AUDIO_DEBUG
+	printk(KERN_DEBUG "usb_audio_interface.\n");
+#endif
 }
 
 void usb_audio_endpoint(struct usb_endpoint_descriptor *interface, u8 *data)
 {
+#ifdef AUDIO_DEBUG
+	printk(KERN_DEBUG "usb_audio_interface.\n");
+#endif
 }
 
 #ifdef MODULE
diff -u --recursive --new-file v2.3.13/linux/drivers/usb/hub.c linux/drivers/usb/hub.c
--- v2.3.13/linux/drivers/usb/hub.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/usb/hub.c	Mon Aug 16 23:19:13 1999
@@ -199,7 +199,7 @@
 
 static int hub_probe(struct usb_device *dev)
 {
-	struct usb_interface_descriptor *interface;
+	struct usb_interface_descriptor *intf_desc;
 	struct usb_endpoint_descriptor *endpoint;
 	struct usb_hub *hub;
 	unsigned long flags;
@@ -212,20 +212,20 @@
 	if (dev->config[0].bNumInterfaces != 1)
 		return -1;
 
-	interface = &dev->config[0].altsetting[0].interface[0];
+	intf_desc = &dev->config[0].interface[0].altsetting[0];
 
 	/* Is it a hub? */
-	if (interface->bInterfaceClass != 9)
+	if (intf_desc->bInterfaceClass != 9)
 		return -1;
-	if ((interface->bInterfaceSubClass != 0) &&
-	    (interface->bInterfaceSubClass != 1))
+	if ((intf_desc->bInterfaceSubClass != 0) &&
+	    (intf_desc->bInterfaceSubClass != 1))
 		return -1;
 
 	/* Multiple endpoints? What kind of mutant ninja-hub is this? */
-	if (interface->bNumEndpoints != 1)
+	if (intf_desc->bNumEndpoints != 1)
 		return -1;
 
-	endpoint = &interface->endpoint[0];
+	endpoint = &intf_desc->endpoint[0];
 
 	/* Output endpoint? Curiousier and curiousier.. */
 	if (!(endpoint->bEndpointAddress & USB_DIR_IN))
diff -u --recursive --new-file v2.3.13/linux/drivers/usb/mouse.c linux/drivers/usb/mouse.c
--- v2.3.13/linux/drivers/usb/mouse.c	Wed Jul 28 14:47:42 1999
+++ linux/drivers/usb/mouse.c	Mon Aug 16 23:19:13 1999
@@ -256,7 +256,7 @@
 
 static int mouse_probe(struct usb_device *dev)
 {
-	struct usb_interface_descriptor *interface;
+	struct usb_interface_descriptor *intf_desc;
 	struct usb_endpoint_descriptor *endpoint;
 	struct mouse_state *mouse = &static_mouse_state;
 
@@ -269,19 +269,19 @@
 		return -1;
 
 	/* Is it a mouse interface? */
-	interface = &dev->config[0].altsetting[0].interface[0];
-	if (interface->bInterfaceClass != 3)
+	intf_desc = &dev->config[0].interface[0].altsetting[0];
+	if (intf_desc->bInterfaceClass != 3)
 		return -1;
-	if (interface->bInterfaceSubClass != 1)
+	if (intf_desc->bInterfaceSubClass != 1)
 		return -1;
-	if (interface->bInterfaceProtocol != 2)
+	if (intf_desc->bInterfaceProtocol != 2)
 		return -1;
 
 	/* Multiple endpoints? What kind of mutant ninja-mouse is this? */
-	if (interface->bNumEndpoints != 1)
+	if (intf_desc->bNumEndpoints != 1)
 		return -1;
 
-	endpoint = &interface->endpoint[0];
+	endpoint = &intf_desc->endpoint[0];
 
 	/* Output endpoint? Curiousier and curiousier.. */
 	if (!(endpoint->bEndpointAddress & 0x80))
diff -u --recursive --new-file v2.3.13/linux/drivers/usb/ohci-hcd.c linux/drivers/usb/ohci-hcd.c
--- v2.3.13/linux/drivers/usb/ohci-hcd.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/usb/ohci-hcd.c	Wed Aug 18 16:22:23 1999
@@ -17,8 +17,8 @@
  * [ $Log: ohci.c,v $ ]
  * [ Revision 1.1  1999/04/05 08:32:30  greg ]
  * 
- * 
- * v2.1 1999/05/09 ep_addr correction, code clean up
+ * v3.0 1999/06/25 
+ * v2.1 1999/05/09  code clean up
  * v2.0 1999/05/04 
  * virtual root hub is now an option, 
  * memory allocation based on kmalloc and kfree now, Bus error handling, 
@@ -31,7 +31,6 @@
  * ohci-hcd.c
  */
 
-/* #define OHCI_DBG  */  /* printk some debug information */
 
  
 #include <linux/config.h>
@@ -59,188 +58,233 @@
 static int handle_apm_event(apm_event_t event);
 static int apm_resume = 0;
 #endif
-
- 
-static DECLARE_WAIT_QUEUE_HEAD(bulk_wakeup);
-static DECLARE_WAIT_QUEUE_HEAD(control_wakeup);
-static DECLARE_WAIT_QUEUE_HEAD(root_hub);
- 
-static __u8 cc_to_status[16] = { /* mapping of the OHCI CC to the UHCI status codes; first guess */
-/* Activ, Stalled, Data Buffer Err, Babble Detected : NAK recvd, CRC/Timeout, Bitstuff, reservd */
-/* No  Error  */		0x00,
-/* CRC Error  */		0x04,
-/* Bit Stuff  */		0x02,
-/* Data Togg  */ 		0x40,
-/* Stall      */		0x40,
-/* DevNotResp */		0x04,
-/* PIDCheck   */		0x04,
-/* UnExpPID   */		0x40,
-/* DataOver   */		0x20,
-/* DataUnder  */ 		0x20,
-/* reservd    */		0x40,
-/* reservd    */		0x40,
-/* BufferOver */		0x20,
-/* BuffUnder  */		0x20,
-/* Not Access */		0x80,
-/* Not Access */		0x80
- };
+static int ohci_link_ed(struct ohci * ohci, struct usb_ohci_ed *ed);
  
+static DECLARE_WAIT_QUEUE_HEAD(op_wakeup);
  
+void usb_pipe_to_hcd_ed(struct usb_device *usb_dev, unsigned int pipe, struct usb_hcd_ed  *hcd_ed) 
+{
+	hcd_ed->endpoint = usb_pipeendpoint(pipe);
+	hcd_ed->out      = usb_pipeout(pipe);
+	hcd_ed->function = usb_pipedevice(pipe);
+	hcd_ed->type     = usb_pipetype(pipe);
+	hcd_ed->slow     = usb_pipeslow(pipe);
+	hcd_ed->maxpack  = usb_maxpacket(usb_dev, pipe, usb_pipeout(pipe));
+	OHCI_DEBUG(printk("******* hcd_ed: endpoint: %4x, function: %4x, out: %4x, type: %4x, slow: %4x, maxpack: %4x\n", hcd_ed->endpoint, hcd_ed->function, hcd_ed->out, hcd_ed->type, hcd_ed->slow, hcd_ed->maxpack); )
+}
+
+
 /********
  **** Interface functions
  ***********************************************/
  
-static int sohci_int_handler(void * ohci_in, unsigned int ep_addr, int ctrl_len, void * ctrl, void * data, int data_len, int status, __OHCI_BAG lw0, __OHCI_BAG lw1)
+static int sohci_blocking_handler(void * ohci_in, struct usb_ohci_ed *ed, void * data, int data_len, int status, __OHCI_BAG lw0, __OHCI_BAG lw1)
+{  
+	if(lw0 != NULL) {
+		((struct ohci_state * )lw0)->status = status;
+		((struct ohci_state * )lw0)->len = data_len;
+	}
+	if(lw1 != NULL) {
+		add_wait_queue(&op_wakeup, lw1);   
+		wake_up(&op_wakeup);
+	}
+	
+	OHCI_DEBUG( { int i; printk("USB HC bh <<<: %x: ", ed->hwINFO);)
+	OHCI_DEBUG( printk(" data(%d):", data_len);) 
+	OHCI_DEBUG( for(i=0; i < data_len; i++ ) printk(" %02x", ((__u8 *) data)[i]);)
+	OHCI_DEBUG( printk(" ret_status: %x\n", status); })
+	
+    return 0;                       
+}
+  
+static int sohci_int_handler(void * ohci_in, struct usb_ohci_ed *ed, void * data, int data_len, int status, __OHCI_BAG lw0, __OHCI_BAG lw1)
 {
 
 	struct ohci * ohci = ohci_in; 
 	usb_device_irq handler=(void *) lw0;
 	void *dev_id = (void *) lw1;
 	int ret;
-	
-	OHCI_DEBUG({ int i; printk("USB HC IRQ <<<: %x: data(%d):", ep_addr, data_len);)
+
+	OHCI_DEBUG({ int i; printk("USB HC IRQ <<<: %x: data(%d):", ed->hwINFO, data_len);)
 	OHCI_DEBUG( for(i=0; i < data_len; i++ ) printk(" %02x", ((__u8 *) data)[i]);)
 	OHCI_DEBUG( printk(" ret_status: %x\n", status); })
-	
- 	ret = handler(cc_to_status[status & 0xf], data, data_len, dev_id);
+ 
+	ret = handler(status, data, data_len, dev_id);
 	if(ret == 0) return 0; /* 0 .. do not requeue  */
 	if(status > 0) return -1; /* error occured do not requeue ? */
-	ohci_trans_req(ohci, ep_addr, 0, NULL, data, 8, (__OHCI_BAG) handler, (__OHCI_BAG) dev_id); /* requeue int request */
+	ohci_trans_req(ohci, ed, 0, NULL, data, (ed->hwINFO >> 16) & 0x3f, (__OHCI_BAG) handler, (__OHCI_BAG) dev_id, INT_IN, sohci_int_handler); /* requeue int request */
+ 
 	return 0;
 }
-
-static int sohci_ctrl_handler(void * ohci_in, unsigned int ep_addr, int ctrl_len, void * ctrl, void * data, int data_len, int status, __OHCI_BAG lw0, __OHCI_BAG lw)
-{  
-	*(int * )lw0 = status;
-	wake_up(&control_wakeup);
-
-	OHCI_DEBUG( { int i; printk("USB HC CTRL<<<: %x: ctrl(%d):", ep_addr, ctrl_len);)
-	OHCI_DEBUG( for(i=0; i < 8; i++ ) printk(" %02x", ((__u8 *) ctrl)[i]);)
-	OHCI_DEBUG( printk(" data(%d):", data_len);) 
-	OHCI_DEBUG( for(i=0; i < data_len; i++ ) printk(" %02x", ((__u8 *) data)[i]);)
-	OHCI_DEBUG( printk(" ret_status: %x\n", status); })
-    return 0;                       
-} 
-
-static int sohci_bulk_handler(void * ohci_in, unsigned int ep_addr, int ctrl_len, void * ctrl, void * data, int data_len, int status, __OHCI_BAG lw0, __OHCI_BAG lw)
-{  
-	*(int * )lw0 = status;
-	wake_up(&bulk_wakeup);
-
-	OHCI_DEBUG( { int i; printk("USB HC BULK<<<: %x:", ep_addr, ctrl_len);)
-	OHCI_DEBUG( printk(" data(%d):", data_len);) 
-	OHCI_DEBUG( for(i=0; i < data_len; i++ ) printk(" %02x", ((__u8 *) data)[i]);)
-	OHCI_DEBUG( printk(" ret_status: %x\n", status); })
-    return 0;                       
-}
-                                                           
-static int sohci_request_irq(struct usb_device *usb_dev, unsigned int pipe, usb_device_irq handler, int period, void *dev_id)
+                                                         
+static void * sohci_request_irq(struct usb_device *usb_dev, unsigned int pipe, usb_device_irq handler, int period, void *dev_id)
 {
 	struct ohci * ohci = usb_dev->bus->hcpriv;
-	union ep_addr_ ep_addr;
-	
-	ep_addr.iep = 0;
-	ep_addr.bep.ep = ((pipe >> 15) & 0x0f) 		/* endpoint address */
-				| (pipe  & 0x80)  	 			/* direction */
-				| (1 << 5);						/* type = int*/
-	ep_addr.bep.fa = ((pipe >> 8) & 0x7f);			/* device address */
+	struct ohci_device * dev = usb_to_ohci(usb_dev);
+	struct usb_hcd_ed hcd_ed;
+	struct usb_ohci_ed * ed;
+
+#ifdef  VROOTHUB
+	if(usb_pipedevice(pipe) == ohci->rh.devnum) 
+		return root_hub_request_irq(usb_dev, pipe, handler, period, dev_id);
+#endif		
+
+	usb_pipe_to_hcd_ed(usb_dev, pipe, &hcd_ed);
+	hcd_ed.type = INT;
+	ed = usb_ohci_add_ep(usb_dev, &hcd_ed, period, 1);
+	
+	OHCI_DEBUG( printk("USB HC IRQ>>>: %x: every %d ms\n", ed->hwINFO, period);) 
+	
+	ohci_trans_req(ohci, ed, 0, NULL, dev->data, hcd_ed.maxpack, (__OHCI_BAG) handler, (__OHCI_BAG) dev_id, INT_IN, sohci_int_handler);
+	if (ED_STATE(ed) != ED_OPER)  ohci_link_ed(ohci, ed);	
+	return ed;
+    
+}
 
-	OHCI_DEBUG( printk("USB HC IRQ >>>: %x: every %d ms\n", ep_addr.iep, period);) 
+static int sohci_release_irq(struct usb_device *usb_dev, void * ed)
+{  
+	// struct usb_device *usb_dev = ((struct ohci_device *) ((unsigned int)ed & 0xfffff000))->usb;
+	struct ohci * ohci = usb_dev->bus->hcpriv; 
 	
-	usb_ohci_add_ep(ohci, ep_addr.iep, period, 1, sohci_int_handler, 1 << ((pipe & 0x03) + 3) , (pipe >> 26) & 0x01);
+	OHCI_DEBUG( printk("USB HC RM_IRQ>>>:%4x\n", (unsigned int) ed);)
 	
-   	ohci_trans_req(ohci, ep_addr.iep, 0, NULL, ((struct ohci_device *) usb_dev->hcpriv)->data, 8, (__OHCI_BAG) handler, (__OHCI_BAG) dev_id);
+	if(ed == NULL) return 0;
+			 
+#ifdef  VROOTHUB
+	if(ed == ohci->rh.int_addr) 
+		return root_hub_release_irq(usb_dev, ed);
+#endif		
+	ED_setSTATE((struct usb_ohci_ed *)ed, ED_STOP);
+	 
+    usb_ohci_rm_ep(usb_dev, (struct usb_ohci_ed *) ed, NULL, NULL, NULL, 0);
+     
 	return 0;
 }
 
-
-static int sohci_control_msg(struct usb_device *usb_dev, unsigned int pipe, void *cmd, void *data, int len)
+static int sohci_control_msg(struct usb_device *usb_dev, unsigned int pipe, devrequest *cmd, void *data, int len)
 {
 	DECLARE_WAITQUEUE(wait, current);
+	struct ohci_state state = {0, TD_NOTACCESSED};
 	struct ohci * ohci = usb_dev->bus->hcpriv;
-	int status;
-	union ep_addr_ ep_addr;
+	struct usb_hcd_ed hcd_ed;
+	struct usb_ohci_ed *ed;
+
+#ifdef  VROOTHUB
+	if(usb_pipedevice(pipe) == ohci->rh.devnum) 
+		return root_hub_control_msg(usb_dev, pipe, cmd, data, len);
+#endif		
 
-    ep_addr.iep = 0;
-	ep_addr.bep.ep = ((pipe >> 15) & 0x0f) 		/* endpoint address */		
-				| (pipe  & 0x80)  				/* direction */
-				|  (1 << 6);					/* type = ctrl*/
-	ep_addr.bep.fa	= ((pipe >> 8) & 0x7f);				/* device address */
+	usb_pipe_to_hcd_ed(usb_dev, pipe, &hcd_ed);
+	hcd_ed.type = CTRL; 	
+ 	
+	ed = usb_ohci_add_ep(usb_dev, &hcd_ed, 0, 1);
 	
-	status = 0xf; /* CC not Accessed */
-	OHCI_DEBUG( { int i; printk("USB HC CTRL>>>: %x: ctrl(%d):", ep_addr.iep, 8);)
+ 	OHCI_DEBUG( { int i; printk("USB HC CTRL>>>: %x: ctrl(%d):", ed->hwINFO, 8);)
 	OHCI_DEBUG( for(i=0; i < 8; i++ ) printk(" %02x", ((__u8 *) cmd)[i]);)
 	OHCI_DEBUG( printk(" data(%d):", len);) 
 	OHCI_DEBUG( for(i=0; i < len; i++ ) printk(" %02x", ((__u8 *) data)[i]);)
 	OHCI_DEBUG( printk("\n"); })
-	
-	usb_ohci_add_ep(ohci, ep_addr.iep, 0, 1, sohci_ctrl_handler, 1 << ((pipe & 0x03) + 3) , (pipe >> 26) & 0x01);
-	
 	current->state = TASK_UNINTERRUPTIBLE;
-    add_wait_queue(&control_wakeup, &wait);   
- 
-	ohci_trans_req(ohci, ep_addr.iep, 8, cmd, data, len, (__OHCI_BAG) &status, 0);
-
-	schedule_timeout(HZ/10);
+    
+	ohci_trans_req(ohci, ed, 8, cmd, data, len, (__OHCI_BAG) &state, (__OHCI_BAG) &wait, (usb_pipeout(pipe))?CTRL_OUT:CTRL_IN, sohci_blocking_handler);
 
-    remove_wait_queue(&control_wakeup, &wait); 
-     
-    OHCI_DEBUG(printk("USB HC status::: %x\n", cc_to_status[status & 0x0f]);)
-     
-	return cc_to_status[status & 0x0f];
+    OHCI_DEBUG(printk("USB HC trans req ed %x: %x :", ed->hwINFO, (unsigned int ) ed); )
+ 	OHCI_DEBUG({ int i; for( i= 0; i<8 ;i++) printk(" %4x", ((unsigned int *) ed)[i]) ; printk("\n"); }; )
+ 	if (ED_STATE(ed) != ED_OPER)  ohci_link_ed(ohci, ed);
+ 	schedule_timeout(HZ/10);
+   
+    if(state.status == TD_NOTACCESSED) {	
+    	current->state = TASK_UNINTERRUPTIBLE;
+  		usb_ohci_rm_ep(usb_dev, ed, sohci_blocking_handler, NULL, NULL, 0);
+		schedule();
+  		state.status = USB_ST_TIMEOUT;
+  	}
+  	remove_wait_queue(&op_wakeup, &wait); 
+	return state.status;
 }
 
-static int sohci_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *data, int len)
+static int sohci_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, unsigned long *rval)
 {
 	DECLARE_WAITQUEUE(wait, current);
+	struct ohci_state state = {0, TD_NOTACCESSED};
 	struct ohci * ohci = usb_dev->bus->hcpriv;
-	int status;
-	union ep_addr_ ep_addr;
-
-    ep_addr.iep = 0;
-	ep_addr.bep.ep = ((pipe >> 15) & 0x0f) 		/* endpoint address */		
-				| (pipe  & 0x80)  				/* direction */
-				|  (11 << 5);					/* type = bulk*/
-	ep_addr.bep.fa	= ((pipe >> 8) & 0x7f);				/* device address */
+	struct usb_hcd_ed hcd_ed;
+	struct usb_ohci_ed *ed;
 	
-	status = 0xf; /* CC not Accessed */
-	OHCI_DEBUG( { int i; printk("USB HC BULK>>>: %x:", ep_addr.iep);)
+	usb_pipe_to_hcd_ed(usb_dev, pipe, &hcd_ed);
+	hcd_ed.type = BULK; 
+	ed = usb_ohci_add_ep(usb_dev, &hcd_ed, 0, 1);
+	OHCI_DEBUG( { int i; printk("USB HC BULK>>>: %x: ", ed->hwINFO);)
 	OHCI_DEBUG( printk(" data(%d):", len);) 
 	OHCI_DEBUG( for(i=0; i < len; i++ ) printk(" %02x", ((__u8 *) data)[i]);)
 	OHCI_DEBUG( printk("\n"); })
-	
-	usb_ohci_add_ep(ohci, ep_addr.iep, 0, 1, sohci_bulk_handler, 1 << ((pipe & 0x03) + 3) , (pipe >> 26) & 0x01);
-	
-	current->state = TASK_UNINTERRUPTIBLE;
-    add_wait_queue(&bulk_wakeup, &wait);   
+	current->state = TASK_UNINTERRUPTIBLE;  
  
-	ohci_trans_req(ohci, ep_addr.iep, 0, NULL, data, len, (__OHCI_BAG) &status, 0);
-
+	ohci_trans_req(ohci, ed, 0, NULL, data, len, (__OHCI_BAG) &state, (__OHCI_BAG) &wait,(usb_pipeout(pipe))?BULK_OUT:BULK_IN, sohci_blocking_handler);
+	if (ED_STATE(ed) != ED_OPER)  ohci_link_ed(ohci, ed);
+	
 	schedule_timeout(HZ/10);
 
-    remove_wait_queue(&bulk_wakeup, &wait); 
-     
-    OHCI_DEBUG(printk("USB HC status::: %x\n", cc_to_status[status & 0x0f]);)
-     
-	return cc_to_status[status & 0x0f];
+	if(state.status == TD_NOTACCESSED) {		
+    	current->state = TASK_UNINTERRUPTIBLE;
+  		usb_ohci_rm_ep(usb_dev, ed, sohci_blocking_handler, NULL, NULL, 0);
+  		schedule();
+  		state.status = USB_ST_TIMEOUT;
+	}
+	remove_wait_queue(&op_wakeup, &wait); 
+    *rval = state.len;
+	return state.status;
+}
+
+static void * sohci_request_bulk(struct usb_device *usb_dev, unsigned int pipe, usb_device_irq handler, void *data, int len, void *dev_id)
+{
+	struct ohci * ohci = usb_dev->bus->hcpriv;
+	struct usb_hcd_ed hcd_ed;
+	struct usb_ohci_ed * ed;
+ 
+	usb_pipe_to_hcd_ed(usb_dev, pipe, &hcd_ed);
+	hcd_ed.type = BULK;
+	ed = usb_ohci_add_ep(usb_dev, &hcd_ed, 0, 1);
+	
+	OHCI_DEBUG( printk("USB HC BULK_RQ>>>: %x \n", ed->hwINFO);) 
+	
+	ohci_trans_req(ohci, ed, 0, NULL, data, len, (__OHCI_BAG) handler, (__OHCI_BAG) dev_id, (usb_pipeout(pipe))?BULK_OUT:BULK_IN, sohci_int_handler);
+	if (ED_STATE(ed) != ED_OPER)  ohci_link_ed(ohci, ed);
+
+	return ed;   
+}
+ 
+static int sohci_terminate_bulk(struct usb_device *usb_dev, void * ed) 
+{
+	DECLARE_WAITQUEUE(wait, current);
+	
+	OHCI_DEBUG( printk("USB HC TERM_BULK>>>:%4x\n", (unsigned int) ed);)
+ 	
+	current->state = TASK_UNINTERRUPTIBLE;
+    usb_ohci_rm_ep(usb_dev, (struct usb_ohci_ed *) ed, sohci_blocking_handler, NULL, &wait, SEND);
+    schedule();
+    remove_wait_queue(&op_wakeup, &wait); 
+	return 1;
 }
 
 static int sohci_usb_deallocate(struct usb_device *usb_dev) {
+	int cnt;
+    DECLARE_WAITQUEUE(wait, current);
     struct ohci_device *dev = usb_to_ohci(usb_dev); 
-	union ep_addr_ ep_addr;
-
-	ep_addr.iep = 0;
 	
 	OHCI_DEBUG(printk("USB HC dealloc %x\n", usb_dev->devnum);)
-
-	/* wait_ms(20); */
-
-	if(usb_dev->devnum >=0) {
-		ep_addr.bep.fa = usb_dev->devnum;
-    	usb_ohci_rm_function(((struct ohci_device *)usb_dev->hcpriv)->ohci, ep_addr.iep);
+ 	 
+	if(usb_dev->devnum >= 0) {
+		current->state = TASK_UNINTERRUPTIBLE;
+    	cnt = usb_ohci_rm_function(usb_dev, sohci_blocking_handler, NULL, &wait);
+    	if(cnt > 0) {
+    		schedule();
+    		remove_wait_queue(&op_wakeup, &wait);
+    	}
 	}
-	
+ 	 		 
     USB_FREE(dev);
+    usb_destroy_configuration(usb_dev);
 	USB_FREE(usb_dev);
 
 	return 0;
@@ -251,7 +295,6 @@
 	struct usb_device *usb_dev;
 	struct ohci_device *dev;
 	
-	
 	USB_ALLOC(usb_dev, sizeof(*usb_dev));
 	if (!usb_dev)
 		return NULL;
@@ -260,13 +303,14 @@
 
 	USB_ALLOC(dev, sizeof(*dev));
 	if (!dev) {
+		usb_destroy_configuration(usb_dev);
 		USB_FREE(usb_dev);
 		return NULL;
 	}
 
 	/* Initialize "dev" */
 	memset(dev, 0, sizeof(*dev));
-
+	
 	usb_dev->hcpriv = dev;
 	dev->usb = usb_dev;
 
@@ -279,14 +323,35 @@
 	return usb_dev;
 }
 
-
 static void *sohci_alloc_isochronous (struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int maxsze, usb_device_irq completed, void *dev_id)
 {
-	return NULL;
+	struct ohci * ohci = usb_dev->bus->hcpriv;
+	struct ohci_device * dev = usb_to_ohci(usb_dev);
+	struct usb_hcd_ed hcd_ed;
+	struct usb_ohci_ed * ed;
+ 	struct usb_ohci_td * td;
+ 	
+	usb_pipe_to_hcd_ed(usb_dev, pipe, &hcd_ed);
+	hcd_ed.type = ISO;
+	ed = usb_ohci_add_ep(usb_dev, &hcd_ed, 1, 1);
+	
+	OHCI_DEBUG( printk("USB HC ISO>>>: %x:  \n", ed->hwINFO);) 
+	
+	td = ohci_trans_req(ohci, ed, 0, NULL, dev->data, len, (__OHCI_BAG) completed, (__OHCI_BAG) dev_id, (usb_pipeout(pipe))?ISO_OUT:ISO_IN, sohci_int_handler);
+	return td;
 }
 
-static void sohci_delete_isochronous (struct usb_device *dev, void *_isodesc)
+static void sohci_delete_isochronous (struct usb_device *usb_dev, void *td)
 {
+	// struct ohci * ohci = usb_dev->bus->hcpriv; 
+	DECLARE_WAITQUEUE(wait, current);
+	
+	OHCI_DEBUG( printk("USB HC RM_ISO>>>:%4x\n", (unsigned int) td);)
+	 
+	current->state = TASK_UNINTERRUPTIBLE;
+    usb_ohci_rm_ep(usb_dev, ((struct usb_ohci_td *) td)->ed, sohci_blocking_handler, NULL, &wait, SEND);
+    schedule();
+    remove_wait_queue(&op_wakeup, &wait); 
 	return;
 }
 
@@ -305,14 +370,15 @@
 	return USB_ST_NOTSUPPORTED;
 }
 
-
 struct usb_operations sohci_device_operations = {
 	sohci_usb_allocate,
 	sohci_usb_deallocate,
 	sohci_control_msg,
 	sohci_bulk_msg,
 	sohci_request_irq,
-	NULL,	/* FIXME: should be release_irq/remove_irq */
+	sohci_release_irq,
+	sohci_request_bulk,
+	sohci_terminate_bulk,
 	sohci_alloc_isochronous,
 	sohci_delete_isochronous,
 	sohci_sched_isochronous,
@@ -325,357 +391,358 @@
  *** ED handling functions
  ************************************/
 
-
-
+/* just for debugging; prints all 32 branches of the int ed tree inclusive iso eds*/
+void print_int_eds(struct ohci * ohci) {int i; __u32 * ed_p;
+	for(i= 0; i < 32; i++) {
+			OHCI_DEBUG(printk("unlnk_branch int %2d(%2x): ", i,i); )
+			ed_p = &(ohci->hc_area->hcca.int_table[i]);
+			while (*ed_p != 0) {
+				OHCI_DEBUG(printk("ed: %4x; ", (((struct usb_ohci_ed *)bus_to_virt(*ed_p))->hwINFO));)
+				ed_p = &(((struct usb_ohci_ed *)bus_to_virt(*ed_p))->hwNextED);
+			}
+			OHCI_DEBUG(printk("\n");)
+		}
+}
+		
 /* 
- * search for the right place to insert an interrupt ed into the int tree 
- * do some load ballancing
+ * search for the right branch to insert an interrupt ed into the int tree 
+ * do some load ballancing 
+ * returns the branch and 
+ * sets the interval to interval = 2^integer(ld(interval))
  * */
 
-static int usb_ohci_int_ballance(struct ohci * ohci, int interval, int load) {
+static int usb_ohci_int_ballance(struct ohci * ohci, int * interval, int load) {
 
   int i,j;
   
   j = 0;   /* search for the least loaded interrupt endpoint branch of all 32 branches */
   for(i=0; i< 32; i++) if(ohci->ohci_int_load[j] > ohci->ohci_int_load[i]) j=i; 
-
-  if(interval < 1) interval = 1;
-  if(interval > 32) interval = 32;
-  for(i= 0; ((interval >> i) > 1 ); interval &= (0xfffe << i++ )); /* interval = 2^int(ld(interval)) */
   
-
-  for(i=j%interval; i< 32; i+=interval) ohci->ohci_int_load[i] += load;
-  j = interval + (j % interval); 
+  for(i= 0; ((*interval >> i) > 1 ) && (i < 5); i++ ); /* interval = 2^int(ld(interval)) */
+  *interval = 1 << i;
+  
+  j = j % (*interval);
+  for(i=j; i< 32; i+=(*interval)) ohci->ohci_int_load[i] += load;
+   
   
-  OHCI_DEBUG(printk("USB HC new int ed on pos : %x \n",j);)
+  OHCI_DEBUG(printk("USB HC new int ed on pos %d of interval %d \n",j, *interval);)
   
   return j;
 }
 
-/* get the ed from the endpoint / device adress */
-
-struct usb_ohci_ed * ohci_find_ep(struct ohci *ohci, unsigned int ep_addr_in) {
-
-union ep_addr_ ep_addr;
-struct usb_ohci_ed *tmp;
-unsigned int mask;
-
-mask = 0;
-ep_addr.iep = ep_addr_in;
-
-#ifdef VROOTHUB
- if(ep_addr.bep.fa == ohci->root_hub_funct_addr) {
- 	if((ep_addr.bep.ep & 0x0f) == 0)
- 		return &ohci->ed_rh_ep0; /* root hub ep0 */
- 	else
- 		return &ohci->ed_rh_epi; /* root hub int ep */
- }
-#endif
+/* the int tree is a binary tree 
+ * in order to process it sequentielly the indexes of the branches have to be mapped 
+ * the mapping reverses the bits of a word of num_bits length
+ * */
+static int rev(int num_bits, int word) {
+	int i;
+	int wout = 0;
 
- tmp = ohci->ed_func_ep0[ep_addr.bep.fa];
- mask = ((((ep_addr.bep.ep >> 5) & 0x03)==2)?0x7f:0xff); 
- ep_addr.bep.ep &= mask; /* mask out direction of ctrl ep */
- 
-  while (tmp != NULL) {
-    if (tmp->ep_addr.iep == ep_addr.iep) 
-      return tmp;
-    tmp = tmp->ed_list;
-  }
-  return NULL;
+	for(i = 0; i < num_bits; i++) wout |= (((word >> i) & 1) << (num_bits - i - 1));
+	return wout;
 }
- 
-spinlock_t usb_ed_lock = SPIN_LOCK_UNLOCKED;
-/* add a new endpoint ep_addr */
-struct usb_ohci_ed *usb_ohci_add_ep(struct ohci * ohci, unsigned int ep_addr_in, int interval, int load, f_handler handler, int ep_size, int speed) {
-   
-  struct usb_ohci_ed * ed; 
-  struct usb_ohci_td * td;
-  union ep_addr_ ep_addr;
- 
-   
-  int int_junk;
- 
-  struct usb_ohci_ed *tmp;
 
-  ep_addr.iep = ep_addr_in ;
-  ep_addr.bep.ep &= ((((ep_addr.bep.ep >> 5) & 0x03)==2)?0x7f:0xff); /* mask out direction of ctrl ep */
+/* get the ed from the endpoint / usb_device address */
 
-  spin_lock(&usb_ed_lock);
-  
-  tmp =  ohci_find_ep(ohci, ep_addr.iep);
-  if (tmp != NULL) { 
-  
-#ifdef VROOTHUB
-  	if(ep_addr.bep.fa == ohci->root_hub_funct_addr) {
- 		if((ep_addr.bep.ep & 0x0f) != 0) { /* root hub int ep */
-			ohci->ed_rh_epi.handler = handler;
- 			ohci_init_rh_int_timer(ohci, interval);
- 		}
- 		else { /* root hub ep0 */
- 			 ohci->ed_rh_ep0.handler = handler;
- 		}			 	
- 	}
-
- 	else 
-#endif 
-
- 		{
- 		tmp->hw.info = ep_addr.bep.fa | ((ep_addr.bep.ep & 0xf) <<7)
-  		
-    	| (((ep_addr.bep.ep & 0x60) == 0)? 0x8000 : 0)
-    	| (speed << 13)
-    	| ep_size <<16;
- 
-  		tmp->handler = handler; 
-  	}
- 	spin_unlock(&usb_ed_lock);
-    return tmp;    /* ed  already in use */
-  }
-  
-  
-  OHCI_ALLOC(td, sizeof(td)); /* dummy td; end of td list for ed */
-  OHCI_ALLOC(ed, sizeof(ed));
-  td->prev_td = NULL;
-  
-  ed->hw.tail_td = virt_to_bus(&td->hw);
-  ed->hw.head_td = ed->hw.tail_td;
-  ed->hw.info = ep_addr.bep.fa | ((ep_addr.bep.ep & 0xf) <<7)
-  /*  | ((ep_addr.bep.port & 0x80)? 0x1000 : 0x0800 ) */
-    | (((ep_addr.bep.ep & 0x60) == 0)? 0x8000 : 0)
-    | (speed << 13)
-    | ep_size <<16;
-  
-  ed->handler = handler;
-
-  switch((ep_addr.bep.ep >> 5) & 0x03) {
-  case CTRL:
-    ed->hw.next_ed = 0;
-    if(ohci->ed_controltail == NULL) {
-      writel(virt_to_bus(&ed->hw), &ohci->regs->ed_controlhead);
-    }
-    else {
-      ohci->ed_controltail->hw.next_ed = virt_to_bus(&ed->hw);
-    }
-    ed->ed_prev = ohci->ed_controltail;
-    ohci->ed_controltail = ed;	  
-    break;
-  case BULK:  
-    ed->hw.next_ed = 0;
-    if(ohci->ed_bulktail == NULL) {
-      writel(virt_to_bus(&ed->hw), &ohci->regs->ed_bulkhead);
-    }
-    else {
-      ohci->ed_bulktail->hw.next_ed = virt_to_bus(&ed->hw);
-    }
-    ed->ed_prev = ohci->ed_bulktail;
-    ohci->ed_bulktail = ed;	  
-    break;
-  case INT:
-    int_junk = usb_ohci_int_ballance(ohci, interval, load);
-    ed->hw.next_ed = ohci->hc_area->ed[int_junk].next_ed; 
-    ohci->hc_area->ed[int_junk].next_ed = virt_to_bus(&ed->hw);
-    ed->ed_prev = (struct usb_ohci_ed *) &ohci->hc_area->ed[int_junk];
-    break;
-  case ISO:
-    ed->hw.next_ed = 0;
-    ohci->ed_isotail->hw.next_ed = virt_to_bus(&ed->hw);
-    ed->ed_prev = ohci->ed_isotail;
-    ohci->ed_isotail = ed;	  
-    break;
-  }
-  ed->ep_addr  = ep_addr;
-  
-  /* Add it to the "hash"-table of known endpoint descriptors */      
-  
-  ed->ed_list = ohci->ed_func_ep0[ed->ep_addr.bep.fa];
-  ohci->ed_func_ep0[ed->ep_addr.bep.fa] = ed; 
-
-  spin_unlock(&usb_ed_lock);
-  
-  OHCI_DEBUG(printk("USB HC new ed %x: %x :", ep_addr.iep, (unsigned int ) ed); )
-  OHCI_DEBUG({ int i; for( i= 0; i<8 ;i++) printk(" %4x", ((unsigned int *) ed)[i]) ; printk("\n"); }; )
-  return 0;
+struct usb_ohci_ed * ohci_find_ep(struct usb_device *usb_dev, struct usb_hcd_ed *hcd_ed) {
+ 	return &(usb_to_ohci(usb_dev)->ed[hcd_ed->endpoint << 1 | ((hcd_ed->type == CTRL)? 0:hcd_ed->out)]);
 }
 
-/*****
- * Request the removal of an endpoint
- * 
- * put the ep on the rm_list and request a stop of the bulk or ctrl list 
- * real removal is done at the next start of frame hardware interrupt 
- */
-int usb_ohci_rm_ep(struct ohci * ohci, struct  usb_ohci_ed *ed)
-{    
-  unsigned int flags;
-  struct usb_ohci_ed *tmp;
-  
-  OHCI_DEBUG(printk("USB HC remove ed %x: %x :\n", ed->ep_addr.iep, (unsigned int ) ed); )
-
-  spin_lock_irqsave(&usb_ed_lock, flags);
-
-  tmp = ohci->ed_func_ep0[ed->ep_addr.bep.fa];
-  if (tmp == NULL) {
-  	spin_unlock_irqrestore(&usb_ed_lock, flags);
-    return 0;
-  }
-
-  if(tmp == ed) {
-     ohci->ed_func_ep0[ed->ep_addr.bep.fa] = ed->ed_list;
-  }
-  else {
-    while (tmp->ed_list != ed) {
-      if (tmp->ed_list == NULL) {
-        spin_unlock_irqrestore(&usb_ed_lock, flags);
-		return 0;
-	  }
-      tmp = tmp->ed_list;
-    }
-    tmp->ed_list = ed->ed_list;
-  }
-  ed->ed_list = ohci->ed_rm_list;
-  ohci->ed_rm_list = ed;
-  ed->hw.info  |=  OHCI_ED_SKIP;
-
-  switch((ed->ep_addr.bep.ep >> 5) & 0x03) {
-  	case CTRL:
-    	writel_mask(~(0x01<<4), &ohci->regs->control); /* stop CTRL list */
-    	break;
-  	case BULK:
-    	writel_mask(~(0x01<<5), &ohci->regs->control); /* stop BULK list */
-    	break;
-  }
-
+/* link an ed into one of the HC chains */
+static int ohci_link_ed(struct ohci * ohci, struct usb_ohci_ed *ed) {	 
 
-  writel( OHCI_INTR_SF, &ohci->regs->intrenable); /* enable sof interrupt */
-
-  spin_unlock_irqrestore(&usb_ed_lock, flags);
-
-  return 1;
+	int int_branch;
+	int i;
+	int inter;
+	int interval;
+	int load;
+	__u32 * ed_p;
+	
+	ED_setSTATE(ed, ED_OPER);
+	
+	switch(ED_TYPE(ed)) {
+	case CTRL:
+		ed->hwNextED = 0;
+		if(ohci->ed_controltail == NULL) {
+			writel(virt_to_bus(ed), &ohci->regs->ed_controlhead);
+		}
+		else {
+			ohci->ed_controltail->hwNextED = virt_to_bus(ed);
+		}
+		ed->ed_prev = ohci->ed_controltail;
+		ohci->ed_controltail = ed;	  
+		break;
+		
+	case BULK:  
+		ed->hwNextED = 0;
+		if(ohci->ed_bulktail == NULL) {
+			writel(virt_to_bus(ed), &ohci->regs->ed_bulkhead);
+		}
+		else {
+			ohci->ed_bulktail->hwNextED = virt_to_bus(ed);
+		}
+		ed->ed_prev = ohci->ed_bulktail;
+		ohci->ed_bulktail = ed;	  
+		break;
+		
+	case INT:
+		interval = ed->int_period;
+		load = ed->int_load;
+		int_branch = usb_ohci_int_ballance(ohci, &interval, load);
+		ed->int_interval = interval;
+		ed->int_branch = int_branch;
+		
+		for( i= 0; i < rev(6, interval); i += inter) {
+			inter = 1;
+			for(ed_p = &(ohci->hc_area->hcca.int_table[rev(5,i)+int_branch]); 
+				(*ed_p != 0) && (((struct usb_ohci_ed *)bus_to_virt(*ed_p))->int_interval >= interval); 
+				ed_p = &(((struct usb_ohci_ed *)bus_to_virt(*ed_p))->hwNextED)) 
+					inter = rev(6,((struct usb_ohci_ed *)bus_to_virt(*ed_p))->int_interval);
+			ed->hwNextED = *ed_p; 
+			*ed_p = virt_to_bus(ed);
+			OHCI_DEBUG(printk("int_link i: %2x, inter: %2x, ed: %4x\n", i, inter, ed->hwINFO);)
+		}
+		break;
+		
+	case ISO:
+		if(ohci->ed_isotail != NULL) {
+			ohci->ed_isotail->hwNextED = virt_to_bus(ed);
+			ed->ed_prev = ohci->ed_isotail;
+		}
+		else {
+			for( i= 0; i < 32; i += inter) {
+				inter = 1;
+				for(ed_p = &(ohci->hc_area->hcca.int_table[rev(5,i)]); 
+					*ed_p != 0; 
+					ed_p = &(((struct usb_ohci_ed *)bus_to_virt(*ed_p))->hwNextED)) 
+						inter = rev(6,((struct usb_ohci_ed *)bus_to_virt(*ed_p))->int_interval);
+				*ed_p = virt_to_bus(ed);	
+			}	
+			ed->ed_prev = NULL;
+		}	
+		ed->hwNextED = 0;
+		ohci->ed_isotail = ed;  
+		break;
+	}
+	
+   	
+	return 1;
 }
 
-/* we have requested to stop the bulk or CTRL list,
- * now we can remove the eds on the rm_list */
- 
-static int ohci_rm_eds(struct ohci * ohci) {
-
-  unsigned int flags;
-  struct usb_ohci_ed *ed;
-  struct usb_ohci_ed *ed_tmp;
-  struct usb_ohci_td *td;
-  __u32 td_hw_tmp;
-  __u32 td_hw;
-  
-  spin_lock_irqsave(&usb_ed_lock, flags);
-
-  ed = ohci->ed_rm_list;
+/* unlink an ed from one of the HC chains. 
+ * just the link to the ed is unlinked.
+ * the link from the ed still points to another operational ed or 0
+ * so the HC can eventually finish the processing of the unlinked ed
+ * */
+static int ohci_unlink_ed(struct ohci * ohci, struct usb_ohci_ed *ed) {
 
-  while (ed != NULL) {
+	int int_branch;
+	int i;
+	int inter;
+	int interval;
+	__u32 * ed_p;
+	 
     
-    switch((ed->ep_addr.bep.ep >> 5) & 0x03) {
+    switch(ED_TYPE(ed)) {
     case CTRL: 
       if(ed->ed_prev == NULL) {
-		writel(ed->hw.next_ed, &ohci->regs->ed_controlhead);
+		writel(ed->hwNextED, &ohci->regs->ed_controlhead);
       }
       else {
-		ed->ed_prev->hw.next_ed = ed->hw.next_ed;
+		ed->ed_prev->hwNextED = ed->hwNextED;
       }
       if(ohci->ed_controltail == ed) {
 		ohci->ed_controltail = ed->ed_prev;
       }
+      else {
+      	((struct usb_ohci_ed *)bus_to_virt(ed->hwNextED))->ed_prev = ed->ed_prev;
+      }
       break;
+      
     case BULK: 
       if(ed->ed_prev == NULL) {
-		writel(ed->hw.next_ed, &ohci->regs->ed_bulkhead);
+		writel(ed->hwNextED, &ohci->regs->ed_bulkhead);
       }
       else {
-		ed->ed_prev->hw.next_ed = ed->hw.next_ed;
+		ed->ed_prev->hwNextED = ed->hwNextED;
       }
       if(ohci->ed_bulktail == ed) {
 		ohci->ed_bulktail = ed->ed_prev;
       }
+      else {
+      	((struct usb_ohci_ed *)bus_to_virt(ed->hwNextED))->ed_prev = ed->ed_prev;
+      }
       break;
+      
     case INT: 
-      	ed->ed_prev->hw.next_ed = ed->hw.next_ed;
-      break;
+      	int_branch = ed->int_branch;
+		interval = ed->int_interval;
+
+		for( i= 0; i < rev(6,interval); i += inter) {
+			for(ed_p = &(ohci->hc_area->hcca.int_table[rev(5,i)+int_branch]), inter = 1; 
+				(*ed_p != 0) && (*ed_p != ed->hwNextED); 
+				ed_p = &(((struct usb_ohci_ed *)bus_to_virt(*ed_p))->hwNextED), 
+				inter = rev(6, ((struct usb_ohci_ed *)bus_to_virt(*ed_p))->int_interval)) {				
+					if(((struct usb_ohci_ed *)bus_to_virt(*ed_p)) == ed) {
+			  			*ed_p = ed->hwNextED;		
+			  			break;
+			  		}
+			  }
+			  OHCI_DEBUG(printk("int_link i: %2x, inter: %2x, ed: %4x\n", i, inter, ed->hwINFO);)
+		}
+		for(i=int_branch; i< 32; i+=interval) ohci->ohci_int_load[i] -= ed->int_load;
+		break;
+		
     case ISO:
-      ed->ed_prev->hw.next_ed = ed->hw.next_ed;
-      if(ohci->ed_isotail == ed) {
-		ohci->ed_isotail = ed->ed_prev;
-      }
-      break;
+    	if(ohci->ed_isotail == ed)
+				ohci->ed_isotail = ed->ed_prev;
+		if(ed->hwNextED != 0) 
+				((struct usb_ohci_ed *)bus_to_virt(ed->hwNextED))->ed_prev = ed->ed_prev;
+				
+		if(ed->ed_prev != NULL) {
+			ed->ed_prev->hwNextED = ed->hwNextED;
+		}	
+		else {
+			for( i= 0; i < 32; i += inter) {
+				inter = 1;
+				for(ed_p = &(ohci->hc_area->hcca.int_table[rev(5,i)]); 
+					*ed_p != 0; 
+					ed_p = &(((struct usb_ohci_ed *)bus_to_virt(*ed_p))->hwNextED)) {
+						inter = rev(6,((struct usb_ohci_ed *)bus_to_virt(*ed_p))->int_interval);
+						if(((struct usb_ohci_ed *)bus_to_virt(*ed_p)) == ed) {
+			  				*ed_p = ed->hwNextED;		
+			  				break;
+			  			}
+			  	}
+			}	
+		}	
+		break;
     }
-    
-    if(ed->hw.next_ed != 0) ((struct usb_ohci_ed *) bus_to_virt(ed->hw.next_ed))->ed_prev = ed->ed_prev;
-    
+    ED_setSTATE(ed, ED_UNLINK);
+    return 1;
+}
 
-/* tds directly connected to ed */
- 
-	td_hw = ed->hw.head_td & 0xfffffff0;
-    while(td_hw != 0) {
-    	td = bus_to_virt(td_hw);
-    	td_hw_tmp = td_hw;
-    	td_hw = td->hw.next_td;
-    	OHCI_FREE(td); /* free pending tds */ 
-    	if(td_hw_tmp == ed->hw.tail_td) break;
-    	
-    }
-     
-    /* mark TDs on the hc done list (if there are any) */      
-	td_hw = readl(&ohci->regs->donehead) & 0xfffffff0;
-    while(td_hw != 0) {
-    	td = bus_to_virt(td_hw);
-    	td_hw = td->hw.next_td;
-    	if(td->ep == ed) td->ep = 0;
-   	}
- 
-    /* mark TDs on the hcca done list (if there are any) */      
-	td_hw = ohci->hc_area->hcca.done_head & 0xfffffff0 ;
-	
-    while(td_hw != 0) { 
-    	td = bus_to_virt(td_hw); 
-    	td_hw = td->hw.next_td;
-    	if(td->ep == ed) td->ep = 0;
-   	}
-
-    ed_tmp = ed;
-    ed = ed->ed_list;
-    OHCI_FREE(ed_tmp);  /* free ed */ 
-  }
-  writel(0, &ohci->regs->ed_controlcurrent); /* reset CTRL list */
-  writel(0, &ohci->regs->ed_bulkcurrent);    /* reset BULK list */
-  writel_set((0x03<<4), &ohci->regs->control);   /* start CTRL u. (BULK list) */ 
+spinlock_t usb_ed_lock = SPIN_LOCK_UNLOCKED;
 
-  spin_unlock_irqrestore(&usb_ed_lock, flags);
-  
-  ohci->ed_rm_list = NULL;
-  OHCI_DEBUG(printk("USB HC after rm ed control: %4x  intrstat: %4x intrenable: %4x\n", readl(&ohci->regs->control),readl(&ohci->regs->intrstatus),readl(&ohci->regs->intrenable));)
+/* add/reinit an endpoint; this should be done once at the usb_set_configuration command,
+ * but the USB stack is a little bit stateless  so we do it at every transaction
+ * if the state of the ed is ED_NEW then a dummy td is added and the state is changed to ED_UNLINK
+ * in all other cases the state is left unchanged
+ * the ed info fields are setted anyway even though they should not change
+ * */
+struct usb_ohci_ed *usb_ohci_add_ep(struct usb_device * usb_dev, struct usb_hcd_ed * hcd_ed, int interval, int load) {
+
+   	// struct ohci * ohci = usb_dev->bus->hcpriv;
+	struct usb_ohci_td * td;  
+	struct usb_ohci_ed * ed; 
+	 
+ 	int ed_state;
  
+	spin_lock(&usb_ed_lock);
+
+	ed = ohci_find_ep(usb_dev, hcd_ed);
 
-  return 0;
+	ed_state = ED_STATE(ed); /* store state of ed */
+	
+	if (ed_state == ED_NEW) {
+  		OHCI_ALLOC(td, sizeof(*td)); /* dummy td; end of td list for ed */
+		ed->hwTailP = virt_to_bus(td);
+		ed->hwHeadP = ed->hwTailP;	
+		ed_state = 	ED_UNLINK;
+	}
+	
+    ed->hwINFO = hcd_ed->function 
+ 			| hcd_ed->endpoint << 7
+    		| (hcd_ed->type == ISO? 0x8000 : 0)
+    		| (hcd_ed->type == CTRL? 0:(hcd_ed->out == 1? 0x800 : 0x1000 )) 
+    		| hcd_ed->slow << 13
+    		| hcd_ed->maxpack << 16
+    		| hcd_ed->type << 27
+    //		| 1 << 14
+    		| ed_state << 29 ;
+ 
+  	if (ED_TYPE(ed) == INT && ed_state == ED_UNLINK) {
+  		ed->int_period = interval;
+  		ed->int_load = load;
+  	}
+  	
+	spin_unlock(&usb_ed_lock);
+	return ed; 
 }
 
-/* remove all endpoints of a function (device) */
-int usb_ohci_rm_function( struct ohci * ohci, unsigned int ep_addr_in)
-{    
-  struct usb_ohci_ed *ed;
-  struct usb_ohci_ed *tmp;
-  union ep_addr_ ep_addr;
 
  
+/*****
+ * Request the removal of an endpoint
+ * 
+ * put the ep on the rm_list and request a stop of the bulk or ctrl list 
+ * real removal is done at the next start of frame (SOF) hardware interrupt 
+ * the dummy td carries the essential information (handler, proc queue, ...)
+ */
+int usb_ohci_rm_ep(struct usb_device * usb_dev, struct usb_ohci_ed *ed, f_handler handler, __OHCI_BAG lw0, __OHCI_BAG lw1, int send)
+{    
+	unsigned int flags;
+   
+	struct ohci * ohci = usb_dev->bus->hcpriv;
+	struct  usb_ohci_td *td; 
   
-  ep_addr.iep = ep_addr_in;
+	OHCI_DEBUG(printk("USB HC remove ed %x: %x :\n", ed->hwINFO, (unsigned int ) ed); )
 
-  for(ed = ohci->ed_func_ep0[ep_addr.bep.fa]; ed != NULL;) {
-	tmp = ed;
-    ed = ed->ed_list;
-    usb_ohci_rm_ep(ohci, tmp);
-  }
- 
+	spin_lock_irqsave(&usb_ed_lock, flags);
+	ed->hwINFO  |=  OHCI_ED_SKIP;
+	writel( OHCI_INTR_SF, &ohci->regs->intrenable); /* enable sof interrupt */
+
+	if(ED_STATE(ed) == ED_OPER) ohci_unlink_ed(ohci, ed);
+
+	td = (struct usb_ohci_td *) bus_to_virt(ed->hwTailP);
+	td->lw0 = lw0;
+	td->lw1 = lw1;
+	td->ed = ed;
+	td->hwINFO = TD_CC;
+	td->handler = handler;
+	td->type = send;
+  
+	ED_setSTATE(ed, ED_DEL);
+	ed->ed_prev = ohci->ed_rm_list;
+	ohci->ed_rm_list = ed;
+   
+	switch(ED_TYPE(ed)) {
+		case CTRL:
+			writel_mask(~(0x01<<4), &ohci->regs->control); /* stop CTRL list */
+  			break;
+		case BULK:
+			writel_mask(~(0x01<<5), &ohci->regs->control); /* stop BULK list */
+			break;
+	}
 
-  
-  return 1;
-}
+	spin_unlock_irqrestore(&usb_ed_lock, flags);
 
+	return 1;
+}
 
+ 
+/* remove all endpoints of a function (device) 
+ * just the last ed sends a reply
+ * the last ed is ed0 as there always should be an ep0
+ * */
+int usb_ohci_rm_function(struct usb_device * usb_dev, f_handler handler,__OHCI_BAG tw0, __OHCI_BAG tw1)
+{   
+	struct usb_ohci_ed *ed;
+	int i;
+	int cnt = 0;
+	
+	
+  	for(i = NUM_EDS - 1 ; i >= 0; i--) {
+  		ed = &(usb_to_ohci(usb_dev)->ed[i]);
+  		if(ED_STATE(ed) != ED_NEW) {
+  		OHCI_DEBUG(printk("USB RM FUNCTION ed: %4x;\n", ed->hwINFO);)
+  			usb_ohci_rm_ep(usb_dev, ed, handler, tw0, tw1, i==0?SEND:0);
+  			cnt++;
+  		}
+  	}
+  	OHCI_DEBUG(printk("USB RM FUNCTION %d eds removed;\n", cnt);)
+  	return cnt;
+}
 
 
 
@@ -684,259 +751,292 @@
  ************************************/
 
 
-#define FILL_TD(TD_PT, HANDLER, INFO, DATA, LEN, LW0, LW1)  \
-    td_pt = (TD_PT); \
-    td_pt1 = (struct usb_ohci_td *) bus_to_virt(usb_ep->hw.tail_td); \
-    td_pt1->ep = usb_ep; \
+#define FILL_TD(INFO, DATA, LEN, LW0, LW1, TYPE, HANDLER)  \
+	OHCI_ALLOC(td_pt, sizeof(*td_pt)); \
+    td_ret = (struct usb_ohci_td *) bus_to_virt(usb_ed->hwTailP & 0xfffffff0); \
+    td_pt1 = td_ret; \
+    td_pt1->ed = ed; \
+    td_pt1->buffer_start = (DATA); \
+    td_pt1->type = (TYPE); \
     td_pt1->handler = (HANDLER); \
+    td_pt1->lw0 = (LW0); \
+    td_pt1->lw1 = (LW1); \
+    td_pt1->hwINFO = (INFO); \
+    td_pt1->hwCBP = (((DATA)==NULL)||((LEN)==0))?0:virt_to_bus(DATA); \
+    td_pt1->hwBE = (((DATA)==NULL)||((LEN)==0))?0:virt_to_bus((DATA) + (LEN) - 1); \
+    td_pt1->hwNextTD = virt_to_bus(td_pt); \
+    td_pt->hwNextTD = 0; \
+    usb_ed->hwTailP =  td_pt1->hwNextTD
+
+#define FILL_ISO_TD(INFO, DATA, LEN, LW0, LW1, TYPE, HANDLER)  \
+	OHCI_ALLOC(td_pt, sizeof(*td_pt)); \
+    td_ret = (struct usb_ohci_td *) bus_to_virt(usb_ed->hwTailP); \
+    td_pt1 = td_ret; \
+    td_pt1->ed = ed; \
     td_pt1->buffer_start = (DATA); \
+    td_pt1->type = (TYPE); \
+    td_pt1->handler = (HANDLER); \
     td_pt1->lw0 = (LW0); \
     td_pt1->lw1 = (LW1); \
-    td_pt1->hw.info = (INFO); \
-    td_pt1->hw.cur_buf = virt_to_bus(DATA); \
-    td_pt1->hw.buf_end = td_pt1->hw.cur_buf + (LEN) - 1; \
-    td_pt1->hw.next_td = virt_to_bus(td_pt); \
-    usb_ep->hw.tail_td = virt_to_bus(td_pt); \
-    td_pt->prev_td = td_pt1; \
-    td_pt->hw.next_td = 0
-
+    td_pt1->hwINFO = (INFO); \
+    td_pt1->hwCBP = (virt_to_bus(DATA) & 0xfffff000); \
+    td_pt1->hwBE = virt_to_bus((DATA) + (LEN) - 1); \
+    td_pt1->hwNextTD = virt_to_bus(td_pt); \
+    td_pt1->hwPSW[0] = virt_to_bus(DATA) & 0xfff; \
+    usb_ed->hwTailP = virt_to_bus(td_pt); \
+    td_pt->hwNextTD = 0
+    
 spinlock_t usb_req_lock = SPIN_LOCK_UNLOCKED;
 
-int ohci_trans_req(struct ohci * ohci, unsigned int ep_addr, int ctrl_len, void  *ctrl, void * data, int data_len, __OHCI_BAG lw0, __OHCI_BAG lw1) {
+struct usb_ohci_td * ohci_trans_req(struct ohci * ohci, struct usb_ohci_ed * ed, int ctrl_len, 
+			void  *ctrl, void * data, int data_len, __OHCI_BAG lw0, __OHCI_BAG lw1, unsigned int ed_type, f_handler handler) {
 
-  int ed_type;
+   
   unsigned int flags;
-  struct usb_ohci_td *td_pt;
-  struct usb_ohci_td *td_pt1;
-  struct usb_ohci_td *td_pt_a1, *td_pt_a2, *td_pt_a3;
-  struct usb_ohci_ed *usb_ep;
-  f_handler handler;
+  volatile struct usb_ohci_ed *usb_ed = ed;
+  volatile struct usb_ohci_td *td_pt;
+  volatile struct usb_ohci_td *td_pt1 = NULL;
 
-  
- td_pt_a1 =NULL;
- td_pt_a2 =NULL;
- td_pt_a3 =NULL;
-  
-  usb_ep = ohci_find_ep(ohci, ep_addr);
-  if(usb_ep == NULL ) return -1; /* not known ep */
-  
-  handler = usb_ep->handler;
+	struct usb_ohci_td *td_ret = NULL;
+	
+  int cnt = 0;
  
-#ifdef VROOTHUB 
-  if(usb_ep == &ohci->ed_rh_ep0) { /* root hub ep 0 control endpoint */  
-    root_hub_control_msg(ohci, 8, ctrl, data, data_len, lw0, lw1, handler);
-    return 0;
-  }
-
-  if(usb_ep == &ohci->ed_rh_epi) { /* root hub interrupt endpoint */
+   
+  if(usb_ed == NULL ) return NULL; /* not known ep */
   
-    root_hub_int_req(ohci, 8, ctrl, data, data_len, lw0, lw1, handler);  
-	return 0;
-  }
-#endif
-  /*  struct usb_ohci_ed * usb_ep = usb_ohci_add_ep(pipe, ohci, interval, 1); */
- 
-   ed_type = ((((union ep_addr_)ep_addr).bep.ep >> 5) & 0x07);
   
-  switch(ed_type) {
-  case BULK_IN:
-  case BULK_OUT:   
-  case INT_IN:
-  case INT_OUT:    
-    OHCI_ALLOC(td_pt_a1, sizeof(td_pt_a1));
-    break;
-
-  case CTRL_IN:
-  case CTRL_OUT:
-    OHCI_ALLOC(td_pt_a1, sizeof(td_pt_a1));
-    OHCI_ALLOC(td_pt_a3, sizeof(td_pt_a3));  
-    if(data_len > 0) {
-      OHCI_ALLOC(td_pt_a2, sizeof(td_pt_a2));
-    }
-    break;
-
-  case ISO_IN:
-  case ISO_OUT:
-
-  }
-    
   spin_lock_irqsave(&usb_req_lock, flags);
   
   switch(ed_type) {
-  case BULK_IN:
-    FILL_TD( td_pt_a1, handler, TD_CC | TD_R | TD_DP_IN | TD_T_TOGGLE, data, data_len, lw0, lw1 );
+  case BULK_IN: 
+  	while(data_len > 4096)
+	{	
+		FILL_TD( TD_CC | TD_R | TD_DP_IN | TD_T_TOGGLE, data, 4096, NULL, NULL, BULK_IN | ADD_LEN|(cnt++?0:ST_ADDR), NULL);
+		data += 4096; data_len -= 4096;
+	}
+    FILL_TD( TD_CC | TD_R | TD_DP_IN | TD_T_TOGGLE, data, data_len, lw0, lw1, BULK_IN |ADD_LEN|SEND|(cnt++?0:ST_ADDR), handler);
     writel( OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
     break;
 
   case BULK_OUT: 
-    FILL_TD( td_pt_a1, handler, TD_CC | TD_DP_OUT | TD_T_TOGGLE, data, data_len, lw0, lw1 );
+  	while(data_len > 4096)
+	{
+		FILL_TD( TD_CC | TD_DP_OUT | TD_T_TOGGLE, data, 4096, NULL, NULL, BULK_OUT | ADD_LEN|(cnt++?0:ST_ADDR), NULL);
+		data += 4096; data_len -= 4096;
+	}
+    FILL_TD( TD_CC | TD_DP_OUT | TD_T_TOGGLE, data, data_len, lw0, lw1, BULK_OUT |ADD_LEN|SEND|(cnt++?0:ST_ADDR), handler);
     writel( OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
     break;
 
   case INT_IN: 
-    FILL_TD( td_pt_a1, handler, TD_CC | TD_R | TD_DP_IN | TD_T_TOGGLE, data, data_len, lw0, lw1 );  
+    FILL_TD( TD_CC | TD_R | TD_DP_IN | TD_T_TOGGLE, data, data_len, lw0, lw1, INT_IN | ST_ADDR|ADD_LEN|SEND, handler);  
     break;
 
   case INT_OUT: 
-    FILL_TD( td_pt_a1, handler, TD_CC | TD_DP_OUT | TD_T_TOGGLE, data, data_len, lw0, lw1 );
+    FILL_TD( TD_CC | TD_DP_OUT | TD_T_TOGGLE, data, data_len, lw0, lw1, INT_OUT | ST_ADDR|ADD_LEN|SEND, handler);
     break;
 
-  case CTRL_IN: 
-    FILL_TD( td_pt_a1, NULL, TD_CC | TD_DP_SETUP | TD_T_DATA0, ctrl, ctrl_len, 0, 0 );  
-    if(data_len > 0) { 
-      FILL_TD( td_pt_a2, NULL, TD_CC | TD_R |  TD_DP_IN | TD_T_DATA1, data, data_len, 0, 0 );  
+  case CTRL_IN:
+    FILL_TD( TD_CC | TD_DP_SETUP | TD_T_DATA0, ctrl, ctrl_len, 0, 0, CTRL_SETUP |ST_ADDR, NULL);  
+    if(data_len > 0) {  
+      	FILL_TD( TD_CC | TD_R |  TD_DP_IN | TD_T_DATA1, data, data_len, 0, 0, CTRL_DATA_IN | ST_ADDR|ADD_LEN, NULL);  
     } 
-    FILL_TD( td_pt_a3, handler, TD_CC | TD_DP_OUT | TD_T_DATA1, NULL, 0, lw0, lw1 );
+    FILL_TD( TD_CC | TD_DP_OUT | TD_T_DATA1, NULL, 0, lw0, lw1, CTRL_STATUS_OUT |SEND, handler);
     writel( OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
     break;
 
-  case CTRL_OUT:     
-    FILL_TD( td_pt_a1, NULL, TD_CC | TD_DP_SETUP | TD_T_DATA0, ctrl, ctrl_len, 0, 0 );  
-    if(data_len > 0) { 
-      FILL_TD( td_pt_a2, NULL, TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1, data, data_len, 0, 0 );  
-    } 
-    FILL_TD( td_pt_a3, handler, TD_CC | TD_DP_IN | TD_T_DATA1, NULL, 0, lw0, lw1 );
+  case CTRL_OUT:
+    FILL_TD( TD_CC | TD_DP_SETUP | TD_T_DATA0, ctrl, ctrl_len, 0, 0, CTRL_SETUP |ST_ADDR, NULL);  
+    if(data_len > 0) {
+      	FILL_TD( TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1, data, data_len, 0, 0, CTRL_DATA_OUT | ST_ADDR|ADD_LEN, NULL);  
+    }  
+    FILL_TD( TD_CC | TD_DP_IN | TD_T_DATA1, NULL, 0, lw0, lw1, CTRL_STATUS_IN |SEND, handler);
     writel( OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
     break;
 
   case ISO_IN:
+   	FILL_ISO_TD( TD_CC|TD_ISO|(ctrl_len & 0xffff), data, data_len, lw0, lw1, ISO_IN | ST_ADDR|ADD_LEN|SEND, handler); 
+   	break;
+   	
   case ISO_OUT:
+  	FILL_ISO_TD( TD_CC|TD_ISO|(ctrl_len & 0xffff), data, data_len, lw0, lw1, ISO_OUT | ST_ADDR|ADD_LEN|SEND, handler); 
     break;
   }
-
-
   
-
- td_pt1 = (struct usb_ohci_td *) bus_to_virt(usb_ep->hw.tail_td); 
-
- 
-  if(td_pt_a3 != NULL) td_pt_a3->prev_td = NULL;
-  	else if (td_pt_a2 != NULL) td_pt_a2->prev_td = NULL;
-  	  	else if (td_pt_a1 != NULL) td_pt_a1->prev_td = NULL;
-  	  
-  spin_unlock_irqrestore(&usb_req_lock, flags);
-  return 0;
+  spin_unlock_irqrestore(&usb_req_lock, flags); 
+  return td_ret;
 }
 
 
 /******
  *** Done List handling functions
  ************************************/
+/* the HC halts an ED if an error occurs;  
+ * on error move all pending tds of a transaction (from ed) onto the done list 
+ * * */
+static struct usb_ohci_td * ohci_append_error_tds(struct usb_ohci_td * td_list, struct usb_ohci_td * td_rev) {
+
+	struct usb_ohci_td * tdl;
+	struct usb_ohci_td * tdx;
+	struct usb_ohci_td * tdt;
+	int cc;
+
+	tdl = (struct  usb_ohci_td *) bus_to_virt( td_list->ed->hwHeadP & 0xfffffff0);
+	tdt = (struct  usb_ohci_td *) bus_to_virt( td_list->ed->hwTailP);
+	cc = TD_CC_GET(td_list->hwINFO);
+	
+	for	( tdx = tdl; tdx != tdt; tdx = tdx->next_dl_td) {
+		if(tdx->type & SEND) break;
+		tdx->next_dl_td = bus_to_virt(tdx->hwNextTD & 0xfffffff0);	
+	}
+	tdx->next_dl_td = td_rev;
+	td_list->ed->hwHeadP = (tdx->hwNextTD & 0xfffffff0) | (td_list->ed->hwHeadP & 0x2);
+	TD_CC_SET(tdx->hwINFO, cc);
+	return tdl;
+}
 
 /* replies to the request have to be on a FIFO basis so
  * we reverse the reversed done-list */
  
 static struct usb_ohci_td * ohci_reverse_done_list(struct ohci * ohci) {
 
-  __u32 td_list_hc;
-  struct usb_ohci_td      * td_list = NULL;
-  struct usb_ohci_td      * td_rev = NULL;
+	__u32 td_list_hc;
+	struct usb_ohci_td * td_rev = NULL;
+	struct usb_ohci_td * td_list = NULL;
   	
 	td_list_hc = ohci->hc_area->hcca.done_head & 0xfffffff0;
-    ohci->hc_area->hcca.done_head = 0;
-    
- 	while(td_list_hc) {
+	ohci->hc_area->hcca.done_head = 0;
+
+ 
+	while(td_list_hc) {
 		
 		td_list = (struct  usb_ohci_td *) bus_to_virt(td_list_hc);
-		td_list->next_dl_td = td_rev;
+		if(TD_CC_GET(td_list->hwINFO) && !(td_list->type & SEND)) 
+			td_list->next_dl_td = ohci_append_error_tds(td_list, td_rev);
+		else
+			td_list->next_dl_td = td_rev;
 			
 		td_rev = td_list;
-		td_list_hc = td_list->hw.next_td & 0xfffffff0;
-	}
+		td_list_hc = td_list->hwNextTD & 0xfffffff0;
+		
+		
+	}	
  return td_list;
 }
 
-/* all done requests are replied here */
-static int usb_ohci_done_list(struct ohci *  ohci) {
+/* there are some pending requests to remove some of the eds 
+ * we process every td including the dummy td of these eds 
+ * and link them to a list
+ * */
+static struct usb_ohci_td * usb_ohci_del_list(struct ohci *  ohci) {
+	struct usb_ohci_ed * ed;
+	struct usb_ohci_td * td;
+	struct usb_ohci_td * td_tmp = NULL;
+	struct usb_ohci_td * td_list = NULL;
+	__u32 * td_hw; 
+	
+	for(ed = ohci->ed_rm_list; ed != NULL; ed = ed->ed_prev) {
+		 OHCI_DEBUG(printk("USB HC ed_rm_list: %4x :\n", ed->hwINFO);)
+		  
+  			
+		for( td_hw = &(ed->hwHeadP); (*td_hw & 0xfffffff0) != ed->hwTailP; td_hw = &(td->hwNextTD)) {
+				td = (struct usb_ohci_td *)bus_to_virt(*td_hw & 0xfffffff0);
+   	 	 		if((ED_STATE(ed) == ED_DEL)	|| (td->type & DEL)) {
+   	 	 			*td_hw = td->hwNextTD;
+   	 	 			if(td_list == NULL)
+   	 	 				td_list = td; 
+   	 	 			else
+   	 	 				td_tmp->next_dl_td = td;
+   	 	 			td_tmp = td;
+   	 	 			OHCI_DEBUG(printk("USB HC ed_rm_list: td: %4x\n", (unsigned int) td);)
+   	 	 			td->next_dl_td = NULL; 
+   	 	 		}
+   	 	}
+   	 	if(ED_STATE(ed) == ED_DEL) { /* send dummy td */
+   	 		td = (struct usb_ohci_td *)bus_to_virt(*td_hw & 0xfffffff0);
+   	 		td->ed = ed;
+   	 		if(td_list == NULL)
+   	 	 		td_list = td; 
+   	 	 	else
+   	 	 		td_tmp->next_dl_td = td; 
+   	 	 	td_tmp = td;
+   	 	 	td->type |= DEL_ED;
+   	 	 	OHCI_DEBUG(printk("USB HC ed_rm_list: dummy (ED_DEL) td: %4x\n", (unsigned int) td);)
+   	 	 	ED_setSTATE(td->ed, ED_DEL| ED_NEW);
+   	 	 	td->next_dl_td = NULL;
+   	 	}	
+   	}  
+   	  
+  	writel(0, &ohci->regs->ed_controlcurrent); /* reset CTRL list */
+  	writel(0, &ohci->regs->ed_bulkcurrent);    /* reset BULK list */
+  	writel_set((0x03<<4), &ohci->regs->control);   /* start CTRL u. BULK list */ 
 
-  struct usb_ohci_td      * td = NULL;
-  struct usb_ohci_td      * td_list; 
-  struct usb_ohci_td      * td_list_next = NULL;
-  struct usb_ohci_td      * td_err = NULL;
-	__u32 td_hw;
- 
-	
-  td_list = ohci_reverse_done_list(ohci);
-
-  while(td_list) {
-   	td_list_next = td_list->next_dl_td;
-    td = td_list;
-
-    if(td->ep == NULL) { /* removed ep */
-   		OHCI_FREE(td_list);
-   		break;
-   	}
+   	ohci->ed_rm_list = NULL;
    	
-   	/* the HC halts an ED if an error occurs; put all pendings TDs of an halted ED on the
-   	 * done list; they are marked with an 0xf CC_error code 
-   	 */
-   	 
- 	if(TD_CC_GET(td_list->hw.info) != TD_CC_NOERROR) { /* on error move all pending tds of an ed into the done list */
- 		printk("******* USB BUS error %x @ep %x\n", TD_CC_GET(td_list->hw.info), td_list->ep->ep_addr.iep);
-    td_err= td_list;
-	td_hw = td_list->ep->hw.head_td & 0xfffffff0;
-    while(td_hw != 0) { 
-    	if(td_hw == td_list->ep->hw.tail_td) break;
-    	td = bus_to_virt(td_hw);
-    	td_err->next_dl_td = td;
-    	td_err= td;
-    	td_hw = td->hw.next_td;
-    }
-    td_list->ep->hw.head_td = td_list->ep->hw.tail_td;
-    td->next_dl_td = td_list_next;
-    td_list_next = td_list->next_dl_td;
- 	
-    }
-  /*  send the reply  */
- 	if(td_list->handler != NULL)  {
-    	if(td_list->prev_td == NULL) {
-			td_list->handler((void *) ohci,
-						td_list->ep->ep_addr.iep,
-						0, 
-						NULL, 
-						td_list->buffer_start, 
-						td_list->hw.buf_end-virt_to_bus(td_list->buffer_start)+1, 
-						TD_CC_GET(td_list->hw.info),
-						td_list->lw0,
-						td_list->lw1);
-			OHCI_FREE(td_list);			
-   	  	}
-      	else {
-      		if(td_list->prev_td->prev_td == NULL) { /* cntrl 2 Transactions dataless */
-	  		td_list->handler((void *) ohci,
-	  		            td_list->ep->ep_addr.iep,
-	  					td_list->prev_td->hw.buf_end-virt_to_bus(td_list->prev_td->buffer_start)+1,
-	  					td_list->prev_td->buffer_start, 
-	  					NULL,
-	  					0, 
-	  					(TD_CC_GET(td_list->prev_td->hw.info) > 0) ? TD_CC_GET(td_list->prev_td->hw.info) : TD_CC_GET(td_list->hw.info),
-						td_list->lw0,
-						td_list->lw1);
-			OHCI_FREE(td_list->prev_td);
-			OHCI_FREE(td_list);
-			}
-			else { /* cntrl 3 Transactions */
-	  			td_list->handler((void *) ohci,
-	  					td_list->ep->ep_addr.iep, 
-	  					td_list->prev_td->prev_td->hw.buf_end-virt_to_bus(td_list->prev_td->prev_td->buffer_start)+1, 
-	  					td_list->prev_td->prev_td->buffer_start, 
-	  					td_list->prev_td->buffer_start, 
-	  					td_list->prev_td->hw.buf_end-virt_to_bus(td_list->prev_td->buffer_start)+1, 
-	  					(TD_CC_GET(td_list->prev_td->prev_td->hw.info) > 0) ? TD_CC_GET(td_list->prev_td->prev_td->hw.info)
-	  						: (TD_CC_GET(td_list->prev_td->hw.info) > 0) ? TD_CC_GET(td_list->prev_td->hw.info) : TD_CC_GET(td_list->hw.info),
+ 
+   	return td_list;
+}
+
+
+/* all tds ever alive go through this loop
+ *  requests are replied here 
+ *  the handler is the 
+ *  interface handler (blocking/non blocking) the real reply-handler 
+ *  is called in the non blocking interface routine
+ * */
+static int usb_ohci_done_list(struct ohci * ohci, struct usb_ohci_td * td_list) {
+
+  	struct usb_ohci_td      * td_list_next = NULL;
+
+	int cc;
+	int i;
+ 
+  	while(td_list) {
+   		td_list_next = td_list->next_dl_td;
+  		 
+  		if(td_list->type & ST_ADDR) { /* remember start address of data buffer */
+ 			td_list->ed->buffer_start = td_list->buffer_start;
+ 			td_list->ed->len = 0;
+ 		}
+ 				
+ 		if(td_list->type & ADD_LEN) { /* accumulate length of multi td transfers */
+ 			if(td_list->hwINFO & TD_ISO) {
+				for(i= 0; i <= ((td_list->hwINFO >> 24) & 0x7); i++) 
+					if((td_list->hwPSW[i] >> 12) < 0xE)  td_list->ed->len += (td_list->hwPSW[i] & 0x3ff);
+ 			}
+ 			else {
+ 				if(td_list->hwBE != 0) {
+ 					if(td_list->hwCBP == 0)
+  			    		td_list->ed->len += (bus_to_virt(td_list->hwBE) - td_list->buffer_start + 1);
+  					else
+  			    		td_list->ed->len += (bus_to_virt(td_list->hwCBP) - td_list->buffer_start);
+  			    }
+  			}
+  		}
+  		/* error code of transfer */
+  		cc = (ED_STATE(td_list->ed) == ED_DEL || (td_list->type & DEL))? USB_ST_REMOVED : TD_CC_GET(td_list->hwINFO);
+
+  	 	if(td_list->type & DEL_ED) ED_setSTATE(td_list->ed, ED_NEW); /* remove ed */
+ 		
+  		if((td_list->type & SEND) && (ED_STATE(td_list->ed) != ED_STOP)) {  /*  send the reply  */	
+  			td_list->handler((void *) ohci,
+						td_list->ed,				  
+						td_list->ed->buffer_start, 
+						td_list->ed->len,
+						cc,
 						td_list->lw0,
 						td_list->lw1); 
-				OHCI_FREE(td_list->prev_td->prev_td);			
-				OHCI_FREE(td_list->prev_td);
-				OHCI_FREE(td_list);
-					
-			}
-      	} 
-    	
-    }
-    td_list = td_list_next;
-  }  
-  return 0; 
+			OHCI_DEBUG(if(cc != TD_CC_NOERROR) printk("******* USB BUS error %x @ep %x\n", TD_CC_GET(td_list->hwINFO), td_list->ed->hwINFO);)		
+			
+		}
+		
+     	if(((td_list->ed->hwHeadP & 0xfffffff0) == td_list->ed->hwTailP) && (ED_STATE(td_list->ed) > ED_UNLINK)) 
+     		ohci_unlink_ed(ohci, td_list->ed); 		/* unlink eds if they are not busy */
+      	
+    	OHCI_FREE(td_list);
+    	td_list = td_list_next;
+  	}  
+ 	return 0; 
 }
 
 
@@ -946,28 +1046,21 @@
  ************************************/
  
 
- 
+/* reset the HC not the BUS */
 void reset_hc(struct ohci *ohci) {
-	int retries = 5;
+
 	int timeout = 30;
-	int fminterval;
-	
+	 	
 	if(readl(&ohci->regs->control) & 0x100) { /* SMM owns the HC */
 		writel(0x08,  &ohci->regs->cmdstatus); /* request ownership */
 		printk("USB HC TakeOver from SMM\n");
-		do {
-			wait_ms(100);
-			if(--retries) { 
-				printk("USB HC TakeOver timed out!\n");
-				break;
-			}
-		}
-		while(readl(&ohci->regs->control) & 0x100); 
+		if(readl(&ohci->regs->control) & 0x100)
+			printk("USB HC TakeOver failed!\n");
 	}	
 		
 	writel((1<<31), &ohci->regs->intrdisable); /* Disable HC interrupts */
-	OHCI_DEBUG(printk("USB HC reset_hc: %x ; retries: %d\n", readl(&ohci->regs->control), 5-retries);)
-	fminterval = readl(&ohci->regs->fminterval) & 0x3fff;
+	OHCI_DEBUG(printk("USB HC reset_hc: %x ; \n", readl(&ohci->regs->control));)
+	
 	writel(1,  &ohci->regs->cmdstatus);	   /* HC Reset */
 	while ((readl(&ohci->regs->cmdstatus) & 0x01) != 0) { /* 10us Reset */
 		if (--timeout == 0) {
@@ -975,507 +1068,237 @@
 			return;
 		}	
 		udelay(1);
-	}
-	/* set the timing */
-	fminterval |= (((fminterval -210) * 6)/7)<<16; 
-	writel(fminterval, &ohci->regs->fminterval);
-	writel(((fminterval&0x3fff)*9)/10, &ohci->regs->periodicstart);
+	}	 
 }
-
+static struct ohci *__ohci;
 
 /*
- * Reset and start an OHCI controller
- */
-void start_hc(struct ohci *ohci)
+ * Start an OHCI controller, set the BUS operational
+ * set and enable interrupts 
+ * connect the virtual root hub
+ * * */
+
+int start_hc(struct ohci *ohci)
 {
-   /*  int fminterval; */
     unsigned int mask;
-    int port_nr;
-  /*  fminterval = readl(&ohci->regs->fminterval) & 0x3fff;
-	reset_hc(ohci); */
- 
-
+  	int fminterval;
+  	
+	/*
+	 * Tell the controller where the control and bulk lists are
+	 * The lists are empty now.
+	 */	
+	writel(0, &ohci->regs->ed_controlhead);
+	writel(0, &ohci->regs->ed_bulkhead);
+	
 	writel(virt_to_bus(&ohci->hc_area->hcca), &ohci->regs->hcca); /* a reset clears this */
- 
-	/* Choose the interrupts we care about now, others later on demand */
-	mask = OHCI_INTR_MIE | OHCI_INTR_WDH;
-	/* | OHCI_INTR_SO | OHCI_INTR_UE |OHCI_INTR_RHSC |OHCI_INTR_SF|  
-		OHCI_INTR_FNO */
-		
-	if(readl(&ohci->regs->roothub.a) & 0x100) /* global power on */
- 		writel( 0x10000, &ohci->regs->roothub.status); /* root hub power on */
-	else { /* port power on */
- 		for(port_nr=0; port_nr < (ohci->regs->roothub.a & 0xff); port_nr++)
-	     		 writel(0x100, &ohci->regs->roothub.portstatus[port_nr]);
-	}
-	wait_ms(50); 		
-	 
-	writel((0x00), &ohci->regs->control); /* USB Reset BUS */
-	wait_ms(10);
-	  
-	writel((0xB7), &ohci->regs->control); /* USB Operational  */
+   
+	writel((0xB7), &ohci->regs->control); /* USB Operational */
  		
-	OHCI_DEBUG(printk("USB HC rstart_hc_operational: %x\n", readl(&ohci->regs->control)); )
+  	fminterval = 0x2edf;
+	writel(((fminterval)*9)/10, &ohci->regs->periodicstart);
+	fminterval |= ((((fminterval -210) * 6)/7)<<16); 
+	writel(fminterval, &ohci->regs->fminterval);	
+	writel(0x628, &ohci->regs->lsthresh);
+	OHCI_DEBUG(printk("USB HC fminterval: %x \n", readl( &(ohci->regs->fminterval) )); )
+	OHCI_DEBUG(printk("USB HC periodicstart: %x \n", readl( &(ohci->regs->periodicstart) )); )
+	OHCI_DEBUG(printk("USB HC lsthresh: %x \n", readl( &(ohci->regs->lsthresh) )); )
+	OHCI_DEBUG(printk("USB HC control: %x\n", readl(&ohci->regs->control)); )
  	OHCI_DEBUG(printk("USB HC roothubstata: %x \n", readl( &(ohci->regs->roothub.a) )); )
  	OHCI_DEBUG(printk("USB HC roothubstatb: %x \n", readl( &(ohci->regs->roothub.b) )); )
  	OHCI_DEBUG(printk("USB HC roothubstatu: %x \n", readl( &(ohci->regs->roothub.status) )); )
  	OHCI_DEBUG(printk("USB HC roothubstat1: %x \n", readl( &(ohci->regs->roothub.portstatus[0]) )); )
    	OHCI_DEBUG(printk("USB HC roothubstat2: %x \n", readl( &(ohci->regs->roothub.portstatus[1]) )); )
-  
-	/* control_wakeup = NULL; */
+	/* Choose the interrupts we care about now, others later on demand */
+	mask = OHCI_INTR_MIE | OHCI_INTR_WDH | OHCI_INTR_SO;
+
 	writel(mask, &ohci->regs->intrenable);
 	writel(mask, &ohci->regs->intrstatus);
  
 #ifdef VROOTHUB
-	{
-
+  {
+	/* connect the virtual root hub */
 	struct usb_device * usb_dev;
 	struct ohci_device *dev;
-	struct ohci_device *tmp_root_hub= usb_to_ohci(ohci->bus->root_hub);
-	usb_dev = sohci_usb_allocate(tmp_root_hub->usb);
-	dev = usb_dev->hcpriv; 
+ 
 
-	dev->ohci = ohci; 
+	usb_dev = sohci_usb_allocate(NULL);
+	if (!usb_dev) return -1;
 
+	dev = usb_to_ohci(usb_dev);
+	usb_dev->bus = ohci->bus;
+	ohci->bus->root_hub = usb_dev;
+	dev->ohci = ohci;
 	usb_connect(usb_dev);
-
-	tmp_root_hub->usb->children[0] = usb_dev;
-
-	usb_new_device(usb_dev);
+	if(usb_new_device(usb_dev) != 0) {
+		sohci_usb_deallocate(usb_dev); 
+		return -1;
 	}
-#endif
 
- 
-	
+  }
+#endif	
+	return 0;
 }
 
-
-
-
+/* an interrupt happens */
 static void ohci_interrupt(int irq, void *__ohci, struct pt_regs *r)
 {
-  struct ohci *ohci = __ohci;
-  struct ohci_regs *regs = ohci->regs;
- 
-  int ints; 
+	struct ohci *ohci = __ohci;
+	struct ohci_regs *regs = ohci->regs;
+ 	int ints; 
 
- 
- if((ohci->hc_area->hcca.done_head != 0) && !(ohci->hc_area->hcca.done_head & 0x01)) {
-    ints =  OHCI_INTR_WDH;
-  }
-  else { 
-    if((ints = (readl(&regs->intrstatus) & readl(&regs->intrenable))) == 0)
-      return;
-   } 
+	if((ohci->hc_area->hcca.done_head != 0) && !(ohci->hc_area->hcca.done_head & 0x01)) {
+		ints =  OHCI_INTR_WDH;
+	}
+	else { 
+ 		if((ints = (readl(&regs->intrstatus) & readl(&regs->intrenable))) == 0)
+		return;
+	} 
    
-  ohci->intrstatus |= ints;
-  OHCI_DEBUG(printk("USB HC interrupt: %x (%x) \n", ints, readl(&ohci->regs->intrstatus));)
+	OHCI_DEBUG(printk("USB HC interrupt: %x (%x) \n", ints, readl(&regs->intrstatus));)
 
-  /* ints &= ~(OHCI_INTR_WDH);  WH Bit will be set by done list subroutine */
- /*  if(ints & OHCI_INTR_FNO) {
-   	writel(OHCI_INTR_FNO,  &regs->intrstatus);
-   	if (waitqueue_active(&ohci_tasks)) wake_up(&ohci_tasks);
-  } */
   
-  if(ints & OHCI_INTR_WDH) {
-   	writel(OHCI_INTR_WDH,  &regs->intrdisable);	
-   	ohci->intrstatus &= (~OHCI_INTR_WDH);
-	usb_ohci_done_list(ohci); /* prepare out channel list */
-	writel(OHCI_INTR_WDH, &ohci->regs->intrstatus);
-	writel(OHCI_INTR_WDH, &ohci->regs->intrenable);
-   	 
-  }
+	if(ints & OHCI_INTR_WDH) {
+		writel(OHCI_INTR_WDH, &regs->intrdisable);	
+		usb_ohci_done_list(ohci, ohci_reverse_done_list(ohci));
+		writel(OHCI_INTR_WDH, &regs->intrenable); 
+	}
   
-  if(ints & OHCI_INTR_SF) {
-  	writel(OHCI_INTR_SF,  &regs->intrdisable);	
-  	writel(OHCI_INTR_SF, &ohci->regs->intrstatus);
-	ohci->intrstatus &= (~OHCI_INTR_SF);
-  	if(ohci->ed_rm_list != NULL) {
-			ohci_rm_eds(ohci);
- 	 }
-  }
-#ifndef VROOTHUB 
-  if(ints & OHCI_INTR_RHSC) {  
-  	writel(OHCI_INTR_RHSC, &regs->intrdisable);
-  	writel(OHCI_INTR_RHSC, &ohci->regs->intrstatus);
-	wake_up(&root_hub);
-
-  }
- #endif
-
-  writel(OHCI_INTR_MIE, &regs->intrenable);
-	
-}
- 
-#ifndef VROOTHUB
-/*
- * This gets called if the connect status on the root
- * hub (and the root hub only) changes.
- */
-static void ohci_connect_change(struct ohci *ohci, unsigned int port_nr)
-{
-	struct usb_device *usb_dev;
-    struct ohci_device *dev;
-	struct ohci_device *tmp_root_hub=usb_to_ohci(ohci->bus->root_hub);
-	OHCI_DEBUG(printk("uhci_connect_change: called for %d stat %x\n", port_nr,readl(&ohci->regs->roothub.portstatus[port_nr]) );)
-
-	/*
-	 * Even if the status says we're connected,
-	 * the fact that the status bits changed may
-	 * that we got disconnected and then reconnected.
-	 *
-	 * So start off by getting rid of any old devices..
-	 */
-	usb_disconnect(&tmp_root_hub->usb->children[port_nr]);
-
-	 if(!(readl(&ohci->regs->roothub.portstatus[port_nr]) & RH_PS_CCS)) {
-	 	writel(RH_PS_CCS, &ohci->regs->roothub.portstatus[port_nr]);
-		return; /* nothing connected */
+	if(ints & OHCI_INTR_SO) {
+		printk("****  USB Schedule overrun ");
+		writel(OHCI_INTR_SO, &regs->intrenable); 	 
 	}
-	/*
-	 * Ok, we got a new connection. Allocate a device to it,
-	 * and find out what it wants to do..
-	 */
-	usb_dev = sohci_usb_allocate(tmp_root_hub->usb);
-	dev = usb_dev->hcpriv; 
-	dev->ohci = ohci; 
-	usb_connect(dev->usb);
-	tmp_root_hub->usb->children[port_nr] = usb_dev;
-	wait_ms(200); /* wait for powerup */
-    /* reset port/device */
- 	writel(RH_PS_PRS, &ohci->regs->roothub.portstatus[port_nr]); /* reset port */
- 	while(!(readl( &ohci->regs->roothub.portstatus[port_nr]) & RH_PS_PRSC)) wait_ms(10); /* reset active ? */
- 	writel(RH_PS_PES, &ohci->regs->roothub.portstatus[port_nr]); /* enable port */
- 	wait_ms(10);
-	/* Get speed information */
-	usb_dev->slow = (readl( &ohci->regs->roothub.portstatus[port_nr]) & RH_PS_LSDA) ? 1 : 0;
 
-	/*
-	 * Ok, all the stuff specific to the root hub has been done.
-	 * The rest is generic for any new USB attach, regardless of
-	 * hub type.
-	 */
-	usb_new_device(usb_dev);
+	if(ints & OHCI_INTR_SF) {
+		writel(OHCI_INTR_SF,  &regs->intrdisable);	
+		if(ohci->ed_rm_list != NULL) {
+			usb_ohci_done_list(ohci, usb_ohci_del_list(ohci));
+		}
+	}
+	writel(ints, &regs->intrstatus);
+	writel(OHCI_INTR_MIE, &regs->intrenable);	
 }
-#endif
- 
-
-
-/*
- * Allocate the resources required for running an OHCI controller.
- * Host controller interrupts must not be running while calling this
- * function.
- *
- * The mem_base parameter must be the usable -virtual- address of the
- * host controller's memory mapped I/O registers.
- *
- * This is where OHCI triumphs over UHCI, because good is dumb.
- * Note how much simpler this function is than in uhci.c.
- *
- * OHCI hardware takes care of most of the scheduling of different
- * transfer types with the correct prioritization for us.
- */
 
+/* allocate OHCI */
 
 static struct ohci *alloc_ohci(void* mem_base)
 {
-	int i,j;
+	int i;
 	struct ohci *ohci;
 	struct ohci_hc_area *hc_area;
 	struct usb_bus *bus;
-	struct ohci_device *dev;
-	struct usb_device *usb;
 
-	/*
-	 * Here we allocate some dummy  EDs as well as the
-	 * OHCI host controller communications area.  The HCCA is just
-	 * a nice pool of memory with pointers to endpoint descriptors
-	 * for the different interrupts.
-	 *
-	 * The first page of memory  contains the HCCA and ohci structure
-	 */
 	hc_area = (struct  ohci_hc_area *) __get_free_pages(GFP_KERNEL, 1);
 	if (!hc_area)
 		return NULL;
+		
 	memset(hc_area, 0, sizeof(*hc_area));
     ohci = &hc_area->ohci;
 	ohci->irq = -1;
-	ohci->regs = mem_base;
-    
+	ohci->regs = mem_base;   
 	ohci->hc_area = hc_area;
-	/* Tell the controller where the HCCA is */
-	writel(virt_to_bus(&hc_area->hcca), &ohci->regs->hcca);
-	
- 
-	/*
-	 * Initialize the ED polling "tree",  full tree;
-         * dummy eds ed[i] (hc should skip them) 
-         * i == 0 is the end of the iso list;
-		 * 1 is the   1ms node, 
-         * 2,3        2ms nodes,
-         * 4,5,6,7    4ms nodes,
-         * 8  ... 15  8ms nodes,
-         * 16 ... 31  16ms nodes,
-         * 32 ... 63  32ms nodes
-         * Sequenzes:
-		 * 32-16- 8-4-2-1-0
-         * 33-17- 9-5-3-1-0
-         * 34-18-10-6-2-1-0
-         * 35-19-11-7-3-1-0
-         * 36-20-12-4-2-1-0
-         * 37-21-13-5-3-1-0
-         * 38-22-14-6-2-1-0
-         * 39-23-15-7-3-1-0
-         * 40-24- 8-4-2-1-0
-         * 41-25- 9-5-3-1-0
-         * 42-26-10-6-2-1-0
-         *     :      :
-         * 63-31-15-7-3-1-0
-	 */
-        hc_area->ed[ED_ISO].info |=  OHCI_ED_SKIP; /* place holder, so skip it */
-        hc_area->ed[ED_ISO].next_ed =  0x0000;       /* end of iso list */
-
-        hc_area->ed[1].next_ed = virt_to_bus(&(hc_area->ed[ED_ISO]));
-        hc_area->ed[1].info |=  OHCI_ED_SKIP; /* place holder, skip it */
-	     
-        j=1;
-        for (i = 2; i < (NUM_INTS * 2); i++) {
-          	if (i >= NUM_INTS) 
-	   		 	hc_area->hcca.int_table[i - NUM_INTS] = virt_to_bus(&(hc_area->ed[i]));
-           
-          	if( i == j*4) j *= 2;
-	    	hc_area->ed[i].next_ed = virt_to_bus(&(hc_area->ed[j+ i%j]));
-            hc_area->ed[i].info |=  OHCI_ED_SKIP; /* place holder, skip it */
-        }
-
-
+	__ohci = ohci;
 	/*
 	 * for load ballancing of the interrupt branches 
 	 */
 	for (i = 0; i < NUM_INTS; i++) ohci->ohci_int_load[i] = 0;
-
+	for (i = 0; i < NUM_INTS; i++) hc_area->hcca.int_table[i] = 0;
+	
 	/*
 	 * Store the end of control and bulk list eds. So, we know where we can add
 	 * elements to these lists.
 	 */
-	ohci->ed_isotail     = (struct usb_ohci_ed *) &(hc_area->ed[ED_ISO]);
-        ohci->ed_controltail = NULL;
-        ohci->ed_bulktail    = NULL;
-	
-	/*
-	 * Tell the controller where the control and bulk lists are
-	 * The lists are empty now.
-	 */	
-	writel(0, &ohci->regs->ed_controlhead);
-	writel(0, &ohci->regs->ed_bulkhead);
-
-	
-	USB_ALLOC(bus, sizeof(*bus));
-	if (!bus)
+	ohci->ed_isotail     = NULL;
+	ohci->ed_controltail = NULL;
+	ohci->ed_bulktail    = NULL;
+
+	bus = usb_alloc_bus(&sohci_device_operations);
+	if (!bus) {
+		free_pages((unsigned int) ohci->hc_area, 1);
 		return NULL;
-
-	memset(bus, 0, sizeof(*bus));
+	}
 
 	ohci->bus = bus;
 	bus->hcpriv = (void *) ohci;
-	bus->op = &sohci_device_operations;
-
-	 
-	usb = sohci_usb_allocate(NULL);
-	if (!usb)
-		return NULL;
-
-	dev = usb_to_ohci(usb);
-	usb->bus = bus;
-	bus->root_hub = usb;
-	dev->ohci = ohci;
-	
-	/* Initialize the root hub */
-	 
-	usb->maxchild = readl(&ohci->regs->roothub.a) & 0xff;
-	usb_init_root_hub(usb);
-
+ 
 	return ohci;
 } 
 
 
 /*
  * De-allocate all resources..
- */
-
+ * */
 static void release_ohci(struct ohci *ohci)
 {
-	int i;
-	struct ohci_device *tmp_root_hub=usb_to_ohci(ohci->bus->root_hub);
-	union ep_addr_ ep_addr;
-	ep_addr.iep = 0;
 	
 	OHCI_DEBUG(printk("USB HC release ohci \n"););
-    
+     /* stop hc */
+  
+   
+		
+    /* disconnect all devices */    
+	if(ohci->bus->root_hub) usb_disconnect(&ohci->bus->root_hub);
+	
+	reset_hc(__ohci);
+	writel(OHCI_USB_RESET, &ohci->regs->control);
+	wait_ms(10);
+	
 	if (ohci->irq >= 0) {
 		free_irq(ohci->irq, ohci);
 		ohci->irq = -1;
 	}
 
-    /* stop hc */
-	writel(OHCI_USB_SUSPEND, &ohci->regs->control);
-		
-	/* deallocate all EDs and TDs */
-	for(i=0; i < 128; i ++) {
-		ep_addr.bep.fa = i;
-		usb_ohci_rm_function(ohci, ep_addr.iep);
-	}
-	ohci_rm_eds(ohci); /* remove eds */
-	
-    /* disconnect all devices */    
-	if(ohci->bus->root_hub)
-		for(i = 0; i < tmp_root_hub->usb->maxchild; i++)
-			usb_disconnect(tmp_root_hub->usb->children + i);
-	    
     usb_deregister_bus(ohci->bus);
-    USB_FREE(tmp_root_hub->usb);
-    USB_FREE(tmp_root_hub);
-    USB_FREE(ohci->bus);
+    usb_free_bus(ohci->bus);
     
 	/* unmap the IO address space */
 	iounmap(ohci->regs);
        
-	free_pages((unsigned int) ohci->hc_area, 1);
-	
+	free_pages((unsigned int) ohci->hc_area, 1);	
 }
 
-static int ohci_roothub_thread(void * __ohci)
-{
-        struct ohci *ohci = (struct ohci *)__ohci;
-        lock_kernel(); 
-
-        /*
-         * This thread doesn't need any user-level access,
-         * so get rid of all our resources..
-         */
-        printk("ohci_roothub_thread at %p\n", &ohci_roothub_thread);
-        exit_mm(current);
-        exit_files(current);
-        exit_fs(current);
-
-
-        strcpy(current->comm, "root-hub");
-
-         
-		start_hc(ohci);
-		writel( 0x10000, &ohci->regs->roothub.status);
-		wait_ms(50); /* root hub power on */
-	usb_register_bus(ohci->bus);
-         do {
-#ifdef CONFIG_APM
-		if (apm_resume) {
-			apm_resume = 0;
-			start_hc(ohci);
-			continue;
-		}
-#endif
- 	 
-		OHCI_DEBUG(printk("USB RH tasks: int: %x\n",ohci->intrstatus););
-#ifndef VROOTHUB
-		/*	if (ohci->intrstatus & OHCI_INTR_RHSC)  */
-			{
-				int port_nr;
-	     		for(port_nr=0; port_nr< ohci->root_hub->usb->maxchild; port_nr++)
-	     			if(readl(&ohci->regs->roothub.portstatus[port_nr]) & (RH_PS_CSC | RH_PS_PRSC)) {		
-	     		 		ohci_connect_change(ohci, port_nr);
-	     		 		writel(0xffff0000, &ohci->regs->roothub.portstatus[port_nr]);
-	     		 	}
-	     		 ohci->intrstatus &= ~(OHCI_INTR_RHSC);
-	     		 writel(OHCI_INTR_RHSC, &ohci->regs->intrenable);
-	    	}
-#endif
- 
-         interruptible_sleep_on(&root_hub);
- 
-      	} while (!signal_pending(current)); 
-             	
-#ifdef VROOTHUB
-		ohci_del_rh_int_timer(ohci);
-#endif
- 
-
-		cleanup_drivers();
-      /*  reset_hc(ohci); */
-	 
-        release_ohci(ohci);
-        MOD_DEC_USE_COUNT;
-
-	    printk("ohci_control_thread exiting\n");
-
-        return 0;
-}
 
 /*
  * Increment the module usage count, start the control thread and
  * return success.
- */
+ * */
 static int found_ohci(int irq, void* mem_base)
 {
-	int retval;
 	struct ohci *ohci;
     OHCI_DEBUG(printk("USB HC found  ohci: irq= %d membase= %x \n", irq, (int)mem_base);)
-	/* Allocate the running OHCI structures */
+    
 	ohci = alloc_ohci(mem_base);
 	if (!ohci) {
-	  return -ENOMEM;
+		return -ENOMEM;
 	}
-
+	
 	reset_hc(ohci);
-
-	retval = -EBUSY;
-	if (request_irq(irq, ohci_interrupt, SA_SHIRQ, "ohci-usb", ohci) == 0) {
-		int pid;
-
-		MOD_INC_USE_COUNT; 
-		ohci->irq = irq;
-		 
-		pid = kernel_thread(ohci_roothub_thread, ohci, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
-		if (pid >= 0) 
-		 	return 0;
-		
-
-		MOD_DEC_USE_COUNT;
-		retval = pid;
-	}
+	writel(OHCI_USB_RESET, &ohci->regs->control);
+	wait_ms(10);
+	usb_register_bus(ohci->bus);
 	
+	if (request_irq(irq, ohci_interrupt, SA_SHIRQ, "ohci-usb", ohci) == 0) {
+		ohci->irq = irq;     
+		start_hc(ohci);
+		return 0;
+ 	}	
 	release_ohci(ohci);
-	return retval;
+	return -EBUSY;
 }
  
 static int start_ohci(struct pci_dev *dev)
 {
-	unsigned int mem_base = dev->resource[0].flags;
-
-	/* If its OHCI, its memory */
-	if (mem_base & PCI_BASE_ADDRESS_SPACE_IO)
-		return -ENODEV;
-
-	/* Get the memory address and map it for IO */
-	mem_base = dev->resource[0].start;
-
-	/* 
-	 * FIXME ioremap_nocache isn't implemented on all CPUs (such
-	 * as the Alpha) [?]  What should I use instead...
-	 *
-	 * The iounmap() is done on in release_ohci.
-	 */
+	unsigned int mem_base = dev->resource[0].start;
+	 
 	mem_base = (unsigned int) ioremap_nocache(mem_base, 4096);
 
 	if (!mem_base) {
 		printk("Error mapping OHCI memory\n");
 		return -EFAULT;
 	}
-
 	return found_ohci(dev->irq, (void *) mem_base);
 } 
 
 
-
 #ifdef CONFIG_APM
 static int handle_apm_event(apm_event_t event)
 {
@@ -1497,10 +1320,7 @@
 			break;
 		}
 		down = 0;
-		if (waitqueue_active(&root_hub)) {
-			apm_resume = 1;
-			wake_up(&root_hub);
-		}
+//		start_hc(ohci);
 		break;
 	}
 	return 0;
@@ -1508,41 +1328,34 @@
 #endif
 
 #define PCI_CLASS_SERIAL_USB_OHCI 0x0C0310
-#define PCI_CLASS_SERIAL_USB_OHCI_PG 0x10
  
-
 int ohci_hcd_init(void)
 {
-  int retval;
-  struct pci_dev *dev = NULL;
+	struct pci_dev *dev = NULL;
  
-  retval = -ENODEV;
-   
-  dev = NULL;
-  while((dev = pci_find_class(PCI_CLASS_SERIAL_USB_OHCI, dev))) { /* OHCI */
-    retval = start_ohci(dev);
-    if (retval < 0) break;
-
+	while((dev = pci_find_class(PCI_CLASS_SERIAL_USB_OHCI, dev))) { 
+		if (start_ohci(dev) < 0) return -ENODEV;
+	}
     
 #ifdef CONFIG_APM
-		apm_register_callback(&handle_apm_event);
+	apm_register_callback(&handle_apm_event);
 #endif
   
     return 0;
-  }
-  return retval;
 }
 
 #ifdef MODULE
-int init_module(void){
+int init_module(void)
+{
 	return ohci_hcd_init();
 }
 
 void cleanup_module(void)
-{
+{	
 #	ifdef CONFIG_APM
 	apm_unregister_callback(&handle_apm_event);
 #	endif
+	release_ohci(__ohci);
 }
 #endif //MODULE
 
diff -u --recursive --new-file v2.3.13/linux/drivers/usb/ohci-hcd.h linux/drivers/usb/ohci-hcd.h
--- v2.3.13/linux/drivers/usb/ohci-hcd.h	Mon May 31 09:01:50 1999
+++ linux/drivers/usb/ohci-hcd.h	Wed Aug 18 16:22:23 1999
@@ -5,7 +5,7 @@
  *
  * The OHCI HCD layer is a simple but nearly complete implementation of what the
  * USB people would call a HCD  for the OHCI. 
- * (ISO comming soon, Bulk disabled, INT u. CTRL transfers enabled)
+ * (ISO comming soon, Bulk, INT u. CTRL transfers enabled)
  * The layer on top of it, is for interfacing to the alternate-usb device-drivers.
  * 
  * [ This is based on Linus' UHCI code and gregs OHCI fragments (0.03c source tree). ]
@@ -15,23 +15,26 @@
  * [ $Log: ohci.c,v $ ]
  * [ Revision 1.1  1999/04/05 08:32:30  greg ]
  * 
- * 
+ * v4.0 1999/08/18
  * v2.1 1999/05/09 ep_addr correction, code clean up
  * v2.0 1999/05/04 
  * v1.0 1999/04/27
  * ohci-hcd.h
  */
+ 
+// #define OHCI_DBG    /* printk some debug information */
 
+ 
 #include <linux/config.h>
 
-#ifdef CONFIG_USB_OHCI_VROOTHUB
+// #ifdef CONFIG_USB_OHCI_VROOTHUB
 #define VROOTHUB  
-#endif
+// #endif
 /* enables virtual root hub 
  * (root hub will be managed by the hub controller 
  *  hub.c of the alternate usb driver)
- *  last time I did more testing without virtual root hub 
- *  -> the virtual root hub could be more unstable now */
+ *  must be on now
+ */
  
  
   
@@ -44,57 +47,63 @@
 /* for readl writel functions */
 #include <linux/list.h>
 #include <asm/io.h>
-
+struct usb_ohci_ed;
 /* for ED and TD structures */
 
 typedef void * __OHCI_BAG;
-typedef int (*f_handler )(void * ohci, unsigned int ep_addr, int cmd_len, void *cmd, void *data, int data_len, int status, __OHCI_BAG lw0, __OHCI_BAG lw1);
+typedef int (*f_handler )(void * ohci, struct usb_ohci_ed *ed, void *data, int data_len, int status, __OHCI_BAG lw0, __OHCI_BAG lw1);
 
+ 
+ 
+/* ED States */
 
+#define ED_NEW 		0x00
+#define ED_UNLINK 	0x01
+#define ED_OPER		0x02
+#define ED_STOP     0x03
+#define ED_DEL		0x04
+#define ED_RH		0x07 /* marker for RH ED */
+
+#define ED_STATE(ed) 			(((ed)->hwINFO >> 29) & 0x7)
+#define ED_setSTATE(ed,state) 	(ed)->hwINFO = ((ed)->hwINFO & ~(0x7 << 29)) | (((state)& 0x7) << 29)
+#define ED_TYPE(ed) 			(((ed)->hwINFO >> 27) & 0x3)
 
-struct ep_address {
-  __u8 ep;  /* bit 7: IN/-OUT, 6,5: type 10..CTRL 00..ISO  11..BULK 10..INT, 3..0: ep nr */ 
-  __u8 fa;    /* function address */
-  __u8 hc;
-  __u8 host;
-};
+struct usb_ohci_ed {
+	__u32 hwINFO;       
+	__u32 hwTailP;
+	__u32 hwHeadP;
+	__u32 hwNextED;
+	 
+	void * buffer_start;
+	unsigned int len;
+	struct usb_ohci_ed *ed_prev;  
+	__u8 int_period;
+	__u8 int_branch;
+	__u8 int_load; 
+	__u8 int_interval;
+   
+} __attribute((aligned(32)));
 
-union ep_addr_ {
-  unsigned int iep;
-  struct ep_address bep;
+struct usb_hcd_ed {
+	int endpoint;
+	int function;
+	int out;
+	int type;
+	int slow;
+	int maxpack;
 };
 
-/*
- * ED and TD descriptors has to be 16-byte aligned
- */
-struct ohci_hw_ed {
-  __u32 info;       
-  __u32 tail_td;	/* TD Queue tail pointer */
-  __u32 head_td;	/* TD Queue head pointer */
-  __u32 next_ed;	/* Next ED */
-} __attribute((aligned(16)));
-
-
-struct usb_ohci_ed {
-  struct ohci_hw_ed hw;
-  /*  struct ohci * ohci; */
-  f_handler handler;
-  union ep_addr_ ep_addr;
-  struct usb_ohci_ed *ed_list;
-  struct usb_ohci_ed *ed_prev;
-} __attribute((aligned(32)));
+struct ohci_state {
+	int len;
+	int status;
+};
 
- /* OHCI Hardware fields */
-struct ohci_hw_td {     
-  __u32 info;
-  __u32 cur_buf;		/* Current Buffer Pointer */
-  __u32 next_td;		/* Next TD Pointer */
-  __u32 buf_end;		/* Memory Buffer End Pointer */
-} __attribute((aligned(16)));
 
+ 
 /* TD info field */
 #define TD_CC       0xf0000000
-#define TD_CC_GET(td_p) ((td_p >>28) & 0x04)
+#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f)
+#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28)
 #define TD_EC       0x0C000000
 #define TD_T        0x03000000
 #define TD_T_DATA0  0x02000000
@@ -108,6 +117,9 @@
 #define TD_DP_IN    0x00100000
 #define TD_DP_OUT   0x00080000
 
+#define TD_ISO		0x00010000
+#define TD_DEL      0x00020000
+
 /* CC Codes */
 #define TD_CC_NOERROR      0x00
 #define TD_CC_CRC          0x01
@@ -124,20 +136,25 @@
 #define TD_NOTACCESSED     0x0F
 
 
+#define MAXPSW 2
 
-struct usb_ohci_td {
-  struct ohci_hw_td hw;
-  void *  buffer_start;
-  f_handler handler; 
-  struct usb_ohci_td *prev_td;
-  struct usb_ohci_ed *ep;
-  struct usb_ohci_td *next_dl_td;
-  __OHCI_BAG lw0;
-  __OHCI_BAG lw1;
+struct usb_ohci_td { 
+	__u32 hwINFO;
+  	__u32 hwCBP;		/* Current Buffer Pointer */
+  	__u32 hwNextTD;		/* Next TD Pointer */
+  	__u32 hwBE;		/* Memory Buffer End Pointer */
+  	__u16 hwPSW[MAXPSW];
+
+  	__u32 type;
+  	void *  buffer_start;
+  	f_handler handler;
+  	struct usb_ohci_ed *ed;
+  	struct usb_ohci_td *next_dl_td;
+  	__OHCI_BAG lw0;
+  	__OHCI_BAG lw1;
 } __attribute((aligned(32)));
 
 
-
 /* TD types */
 #define BULK		0x03
 #define INT			0x01
@@ -153,30 +170,21 @@
 #define ISO_IN		0x04
 #define ISO_OUT		0x00
 
-struct ohci_rep_td {
-  int cmd_len;
-  void * cmd;
-  void * data;
-  int data_len;
-  f_handler handler;
-  struct ohci_rep_td *next_td;
-  int ep_addr;
-  __OHCI_BAG lw0;
-  __OHCI_BAG lw1;
-  __u32 status;
-} __attribute((aligned(32))); 
+#define CTRL_SETUP  	0x102
+#define CTRL_DATA_IN	0x206
+#define CTRL_DATA_OUT	0x202
+#define CTRL_STATUS_IN	0x306
+#define CTRL_STATUS_OUT	0x302
+
+ 
+#define SEND            0x00001000
+#define ST_ADDR         0x00002000
+#define ADD_LEN         0x00004000
+#define DEL             0x00008000
+#define DEL_ED          0x00040000
 
 #define OHCI_ED_SKIP	(1 << 14)
-#define OHCI_ED_MPS	(0x7ff << 16)
-#define OHCI_ED_F_NORM	(0)
-#define OHCI_ED_F_ISOC	(1 << 15)
-#define OHCI_ED_S_LOW	(1 << 13)
-#define OHCI_ED_S_HIGH	(0)
-#define OHCI_ED_D	(3 << 11)
-#define OHCI_ED_D_IN	(2 << 11)
-#define OHCI_ED_D_OUT	(1 << 11)
-#define OHCI_ED_EN	(0xf << 7)
-#define OHCI_ED_FA	(0x7f)
+ 
 
  
 /*
@@ -194,18 +202,6 @@
 } __attribute((aligned(256)));
 
   
-
-#define ED_INT_1	1
-#define ED_INT_2	2
-#define ED_INT_4	4
-#define ED_INT_8	8
-#define ED_INT_16	16
-#define ED_INT_32	32
-#define ED_CONTROL	64
-#define ED_BULK		65
-#define ED_ISO		0	/* same as 1ms interrupt queue */
- 
-
 /*
  * This is the maximum number of root hub ports.  I don't think we'll
  * ever see more than two as that's the space available on an ATX
@@ -286,9 +282,19 @@
 /*
  * Control register masks
  */
+#define OHCI_USB_RESET		0
 #define OHCI_USB_OPER		(2 << 6)
 #define OHCI_USB_SUSPEND	(3 << 6)
 
+struct virt_root_hub {
+	int devnum; /* Address of Root Hub endpoint */ 
+	usb_device_irq handler;
+	void * dev_id;
+	void * int_addr;
+	int send;
+	int interval;
+	struct timer_list rh_int_timer;
+};
 /*
  * This is the full ohci controller description
  *
@@ -298,78 +304,54 @@
 
 
 struct ohci {
-    	int irq;
-	    struct ohci_regs *regs;					/* OHCI controller's memory */	
-	    struct ohci_hc_area *hc_area;			/* hcca, int ed-tree, ohci itself .. */                
-        int root_hub_funct_addr;                /* Address of Root Hub endpoint */       
-        int ohci_int_load[32];                       /* load of the 32 Interrupt Chains (for load ballancing)*/     
-        struct usb_ohci_ed * ed_rm_list;        /* list of all endpoints to be removed */
-        struct usb_ohci_ed * ed_bulktail;       /* last endpoint of bulk list */
-        struct usb_ohci_ed * ed_controltail;    /* last endpoint of control list */
-        struct usb_ohci_ed * ed_isotail;        /* last endpoint of iso list */
-        struct usb_ohci_ed ed_rh_ep0;
-        struct usb_ohci_ed ed_rh_epi;
-        struct ohci_rep_td *td_rh_epi;
-        int intrstatus;
-        struct usb_ohci_ed *ed_func_ep0[128];   /* "hash"-table for ep to ed mapping */
-        struct ohci_rep_td *repl_queue;			/* for internal requests */
-        int rh_int_interval;
-        int rh_int_timer;   
-        struct usb_bus *bus;
-       
-       
+	int irq;
+	struct ohci_regs *regs;					/* OHCI controller's memory */	
+	struct ohci_hc_area *hc_area;			/* hcca, int ed-tree, ohci itself .. */                
+                             
+	int ohci_int_load[32];                  /* load of the 32 Interrupt Chains (for load ballancing)*/     
+	struct usb_ohci_ed * ed_rm_list;        /* list of all endpoints to be removed */
+	struct usb_ohci_ed * ed_bulktail;       /* last endpoint of bulk list */
+	struct usb_ohci_ed * ed_controltail;    /* last endpoint of control list */
+ 	struct usb_ohci_ed * ed_isotail;        /* last endpoint of iso list */
+	int intrstatus;
+	struct ohci_rep_td *repl_queue;			/* for internal requests */
+	int rh_int_interval;
+	int rh_int_timer;   
+	struct usb_bus *bus;    
+	struct virt_root_hub rh;
 };
 
-/*
- *  Warning: This constant must not be so large as to cause the
- *  ohci_device structure to exceed one 4096 byte page.  Or "weird
- *  things will happen" as the alloc_ohci() function assumes that
- *  its less than one page at the moment.  (FIXME)
- */
-#define NUM_TDS	4		/* num of preallocated transfer descriptors */
-#define NUM_EDS 80		/* num of preallocated endpoint descriptors */
 
-struct ohci_hc_area {
+#define NUM_TDS	0		/* num of preallocated transfer descriptors */
+#define NUM_EDS 32		/* num of preallocated endpoint descriptors */
 
+struct ohci_hc_area {
 	struct ohci_hcca 	hcca;		/* OHCI mem. mapped IO area 256 Bytes*/
-
-	struct ohci_hw_ed		ed[NUM_EDS];	/* Endpoint Descriptors 80 * 16  : 1280 Bytes */
-	struct ohci_hw_td		td[NUM_TDS];	/* Transfer Descriptors 2 * 32   : 64 Bytes */
-        struct ohci             ohci;
+ 	struct ohci         ohci;
         
 };
 struct ohci_device {
 	struct usb_device	*usb;
 	struct ohci			*ohci;
+	struct usb_ohci_ed	ed[NUM_EDS];
 	unsigned long		data[16];
 };
 
-#define ohci_to_usb(uhci)	((ohci)->usb)
+#define ohci_to_usb(ohci)	((ohci)->usb)
 #define usb_to_ohci(usb)	((struct ohci_device *)(usb)->hcpriv)
 
-/* Debugging code */
-/*void show_ed(struct ohci_ed *ed);
-void show_td(struct ohci_td *td);
-void show_status(struct ohci *ohci); */
-
 /* hcd */
-int ohci_trans_req(struct ohci * ohci, unsigned int ep_addr, int cmd_len, void  *cmd, void * data, int data_len, __OHCI_BAG lw0, __OHCI_BAG lw1); 
-struct usb_ohci_ed *usb_ohci_add_ep(struct ohci * ohci, unsigned int ep_addr, int interval, int load, f_handler handler, int ep_size, int speed);
-int usb_ohci_rm_function(struct ohci * ohci, unsigned int ep_addr); 
-int usb_ohci_rm_ep(struct ohci * ohci, struct  usb_ohci_ed *ed);
-struct usb_ohci_ed * ohci_find_ep(struct ohci *ohci, unsigned int ep_addr_in);
-
+struct usb_ohci_td * ohci_trans_req(struct ohci * ohci, struct usb_ohci_ed * ed, int cmd_len, void  *cmd, void * data, int data_len, __OHCI_BAG lw0, __OHCI_BAG lw1, unsigned int type, f_handler handler); 
+struct usb_ohci_ed *usb_ohci_add_ep(struct usb_device * usb_dev, struct usb_hcd_ed * hcd_ed, int interval, int load);
+int usb_ohci_rm_function(struct usb_device * usb_dev, f_handler handler, __OHCI_BAG lw0, __OHCI_BAG lw1); 
+int usb_ohci_rm_ep(struct usb_device * usb_dev, struct  usb_ohci_ed *ed, f_handler handler, __OHCI_BAG lw0, __OHCI_BAG lw1, int send);
+struct usb_ohci_ed * ohci_find_ep(struct usb_device * usb_dev, struct usb_hcd_ed *hcd_ed);
+ 
 /* roothub */
-int ohci_del_rh_int_timer(struct ohci * ohci);
-int	ohci_init_rh_int_timer(struct ohci * ohci, int interval);  	
-int root_hub_int_req(struct ohci * ohci, int cmd_len, void * ctrl, void *  data, int data_len, __OHCI_BAG lw0, __OHCI_BAG lw1, f_handler handler);
-int root_hub_send_irq(struct ohci * ohci, void * data, int data_len );
-int root_hub_control_msg(struct ohci *ohci, int cmd_len, void *rh_cmd, void *rh_data, int len, __OHCI_BAG lw0, __OHCI_BAG lw1, f_handler handler);
-int queue_reply(struct ohci * ohci, unsigned int ep_addr, int cmd_len,void * cmd, void * data,int  len, __OHCI_BAG lw0, __OHCI_BAG lw1, f_handler handler);
-int send_replies(struct ohci * ohci);
 
-  
- 
+int root_hub_control_msg(struct usb_device *usb_dev, unsigned int pipe, devrequest *cmd, void *data, int len);
+int root_hub_release_irq(struct usb_device *usb_dev, void * ed);  
+void * root_hub_request_irq(struct usb_device *usb_dev, unsigned int pipe, usb_device_irq handler, int period, void *dev_id);
 
 /* Root-Hub Register info */
 
@@ -388,10 +370,10 @@
 
 
 #ifdef OHCI_DBG
-#define OHCI_FREE(x) kfree(x); printk("OHCI FREE: %d\n", -- __ohci_free_cnt)
-#define OHCI_ALLOC(x,size) (x) = kmalloc(size, GFP_KERNEL); printk("OHCI ALLO: %d\n", ++ __ohci_free_cnt)
-#define USB_FREE(x) kfree(x); printk("USB FREE: %d\n", -- __ohci_free1_cnt)
-#define USB_ALLOC(x,size) (x) = kmalloc(size, GFP_KERNEL); printk("USB ALLO: %d\n", ++ __ohci_free1_cnt)
+#define OHCI_FREE(x) kfree(x); printk("OHCI FREE: %d: %4x\n", -- __ohci_free_cnt, (unsigned int) x)
+#define OHCI_ALLOC(x,size) (x) = kmalloc(size, GFP_KERNEL); printk("OHCI ALLO: %d: %4x\n", ++ __ohci_free_cnt,(unsigned int) x)
+#define USB_FREE(x) kfree(x); printk("USB FREE: %d: %4x\n", -- __ohci_free1_cnt, (unsigned int) x)
+#define USB_ALLOC(x,size) (x) = kmalloc(size, GFP_KERNEL); printk("USB ALLO: %d: %4x\n", ++ __ohci_free1_cnt, (unsigned int) x)
 static int __ohci_free_cnt = 0;
 static int __ohci_free1_cnt = 0;
 #else
diff -u --recursive --new-file v2.3.13/linux/drivers/usb/ohci-root-hub.c linux/drivers/usb/ohci-root-hub.c
--- v2.3.13/linux/drivers/usb/ohci-root-hub.c	Mon May 10 10:18:34 1999
+++ linux/drivers/usb/ohci-root-hub.c	Wed Aug 18 16:22:23 1999
@@ -3,11 +3,27 @@
  *
  * (C) Copyright 1999 Roman Weissgaerber (weissg@vienna.at)
  *
+ *	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.
+ *
+ * 
  * The Root Hub is build into the HC (UHCI or OHCI) hardware. 
  * This piece of code lets it look like it resides on the usb
  * like the other hubs.
  * (for anyone who wants to do a control operation on the root hub)
- *  
+ * 
+ * v4.0 1999/08/18 
  * v2.1 1999/05/09 
  * v2.0 1999/05/04
  * v1.0 1999/04/27
@@ -16,7 +32,6 @@
  */
  
 
-
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
@@ -31,7 +46,6 @@
 
 #include "ohci-root-hub.h"
 
-
 static __u8 root_hub_dev_des[] =
 {
         0x12,       /*  __u8  bLength; */
@@ -85,7 +99,7 @@
         0x05,       /*  __u8  ep_bDescriptorType; Endpoint */
         0x81,       /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
         0x03,       /*  __u8  ep_bmAttributes; Interrupt */
-        0x40,       /*  __u16 ep_wMaxPacketSize; 64 Bytes */
+        0x08,       /*  __u16 ep_wMaxPacketSize; 8 Bytes */
         0x00,
         0xff        /*  __u8  ep_bInterval; 255 ms */
 };
@@ -108,385 +122,128 @@
 };
 */
 
+#define OK(x) 			len = (x); req_reply = 0; break
+#define WR_RH_STAT(x) 		writel((x), &ohci->regs->roothub.status)
+#define WR_RH_PORTSTAT(x) 	writel((x), &ohci->regs->roothub.portstatus[wIndex-1])
+#define RD_RH_STAT			readl(&ohci->regs->roothub.status)
+#define RD_RH_PORTSTAT		readl(&ohci->regs->roothub.portstatus[wIndex-1])
 
-int root_hub_control_msg(struct ohci *ohci, int cmd_len, void *rh_cmd, void *rh_data, int leni, __OHCI_BAG lw0, __OHCI_BAG lw1, f_handler handler)
+int root_hub_control_msg(struct usb_device *usb_dev, unsigned int pipe, devrequest * cmd, void *data, int leni)
 { 
-
-  __u32 stat;
-  __u32 rep_handler;
-  int req_reply=0;
-  union ep_addr_ ep_addr;
-  union ep_addr_ ep_addr_ret;
-        __u8 * cmd = rh_cmd;
-	__u8 * data = rh_data;
-	int i;
+	struct ohci * ohci = usb_dev->bus->hcpriv;
+	__u8 data_buf[16];
+	int req_reply=4;
+ 
 	int len =leni;
 
-        __u8  bmRequestType = cmd[0];
-        __u8  bRequest      = cmd[1];
-        __u16 wValue        = cmd[3] << 8 | cmd [2];
-        __u16 wIndex        = cmd[5] << 8 | cmd [4];
-        __u16 wLength       = cmd[7] << 8 | cmd [6];
-printk("USB root hub: adr: %8x cmd(%8x): ", ohci->root_hub_funct_addr, 8);
-for(i=0;i<8;i++)
-	printk("%2x", ((char *)rh_cmd)[i]);
+	__u16 bmRType_bReq  = cmd->requesttype | (cmd->request << 8);
+	__u16 wValue        = cpu_to_le16(cmd->value);
+	__u16 wIndex        = cpu_to_le16(cmd->index);
+	__u16 wLength       = cpu_to_le16(cmd->length);
+
+	OHCI_DEBUG(printk("USB root hub: adr: %2x cmd(%1x): ", ohci->rh.devnum, 8);)
+	OHCI_DEBUG({ int i; for(i=0;i<8;i++) printk(" %02x", ((unsigned char *)cmd)[i]);})
+	OHCI_DEBUG(printk(" ; \n");)
  
-printk(" ; \n");
-
-	ep_addr_ret.iep = 0;
-	ep_addr_ret.bep.fa = ohci->root_hub_funct_addr;
-	ep_addr_ret.bep.ep =  (bmRequestType & 0x80) | 0x40;
-
-  switch (bmRequestType | bRequest << 8) {
-   /* Request Destination:
-      without flags: Device, 
-      RH_INTERFACE: interface, 
-      RH_ENDPOINT: endpoint,
-      RH_CLASS means HUB here, 
-      RH_OTHER | RH_CLASS  almost ever means HUB_PORT here 
-   */
+	switch (bmRType_bReq) {
+	/* Request Destination:
+	   without flags: Device, 
+	   RH_INTERFACE: interface, 
+	   RH_ENDPOINT: endpoint,
+	   RH_CLASS means HUB here, 
+	   RH_OTHER | RH_CLASS  almost ever means HUB_PORT here 
+	*/
   
-   case RH_GET_STATUS:
-     len = 2; 
-     data[0] = 0x01;
-     data[1] = 0x00;
-     req_reply = RH_ACK; 
-     break;
-   case RH_GET_STATUS | RH_INTERFACE:
-     len = 2; 
-     data[0] = 0x00;
-     data[1] = 0x00;     
-     req_reply = RH_ACK;
-     break;
-   case RH_GET_STATUS | RH_ENDPOINT:
-     len = 2; 
-     data[0] = 0x00;
-     data[1] = 0x00;     
-     req_reply = RH_ACK;
-     break;
-   case RH_GET_STATUS | RH_CLASS: /* HUB_STATUS */
-     stat = readl(&ohci->regs->roothub.status) & 0x7fff7fff; /* bit 31 u. 15 has other meaning */ 
-     data[0] = stat & 0xff;
-     data[1] = (stat >> 8) & 0xff;
-     data[2] = (stat >> 16) & 0xff;
-     data[3] = (stat >> 24) & 0xff;
-     len = 4;
-     req_reply = RH_ACK; 
-     break;
-   case RH_GET_STATUS | RH_OTHER | RH_CLASS: /* PORT_STATUS */
-     stat = readl(&ohci->regs->roothub.portstatus[wIndex-1]);
-     data[0] = stat & 0xff;
-     data[1] = (stat >> 8) & 0xff;
-     data[2] = (stat >> 16) & 0xff;
-     data[3] = (stat >> 24) & 0xff;
-     len = 4;
-     req_reply = RH_ACK; 
-     printk("rh: stat %4x wIndex %4x;\n", stat , wIndex);
-     break;
-
-   case RH_CLEAR_FEATURE:
-     switch (wValue) {
-       case (RH_DEVICE_REMOTE_WAKEUP):
-       default:
-     }
-     break;
-
-   case RH_CLEAR_FEATURE | RH_ENDPOINT:  
-     switch (wValue) {
-       case (RH_ENDPOINT_STALL): 
-         len=0;
-         req_reply = RH_ACK;
-         break;
-       default:
-     }
-     break;
-
-   case RH_CLEAR_FEATURE | RH_CLASS:
-     switch (wValue) {
-       /*     case (RH_C_HUB_LOCAL_POWER):  OHCI says: no switching of this one */
-       case (RH_C_HUB_OVER_CURRENT):
-         writel(RH_PS_OCIC, &ohci->regs->roothub.status);
-         len=0;
-         req_reply = RH_ACK;
-         break;
-       default:
-     }
-     break;
-   case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
-     switch (wValue) {
-       case (RH_PORT_ENABLE):
-	     writel(RH_PS_CCS, &ohci->regs->roothub.portstatus[wIndex-1]);
-         len=0;
-         req_reply = RH_ACK;
-         break;
-       case (RH_PORT_SUSPEND):
-         writel(RH_PS_POCI, &ohci->regs->roothub.portstatus[wIndex-1]);
-         len=0;
-         req_reply = RH_ACK;
-         break;
-       case (RH_PORT_POWER):
-         writel(RH_PS_LSDA, &ohci->regs->roothub.portstatus[wIndex-1]);
-         len=0;
-         req_reply = RH_ACK;
-         break;
-       case (RH_C_PORT_CONNECTION):
-         writel(RH_PS_CSC, &ohci->regs->roothub.portstatus[wIndex-1]);
-         len=0;
-         req_reply = RH_ACK;
-         break;
-       case (RH_C_PORT_ENABLE):
-         writel(RH_PS_PESC, &ohci->regs->roothub.portstatus[wIndex-1]);
-         len=0;
-         req_reply = RH_ACK;
-         break;
-       case (RH_C_PORT_SUSPEND):
-         writel(RH_PS_PSSC, &ohci->regs->roothub.portstatus[wIndex-1]);
-         len=0;
-         req_reply = RH_ACK;
-         break;
-       case (RH_C_PORT_OVER_CURRENT):
-         writel(RH_PS_OCIC, &ohci->regs->roothub.portstatus[wIndex-1]);
-         len=0;
-         req_reply = RH_ACK;
-         break;
-       case (RH_C_PORT_RESET):
-         writel(RH_PS_PRSC, &ohci->regs->roothub.portstatus[wIndex-1]);
-         len=0;
-         req_reply = RH_ACK;
-         break;
-       /*
-       case (RH_PORT_CONNECTION):
-       case (RH_PORT_OVER_CURRENT):
-       case (RH_PORT_RESET):
-       case (RH_PORT_LOW_SPEED):
-       */
-       default:
-     }
-     break;
-   case RH_SET_FEATURE:  
-     switch (wValue) {
-       case (RH_DEVICE_REMOTE_WAKEUP):
-       default:
-     }
-     break;
-
-   case RH_SET_FEATURE | RH_ENDPOINT:
-     switch (wValue) {
-       case (RH_ENDPOINT_STALL):
-       default:
-     }
-     break;
-
-   case RH_SET_FEATURE | RH_CLASS: 
-     switch (wValue) {
-       /* case (RH_C_HUB_LOCAL_POWER): Root Hub has no local Power 
-       case (RH_C_HUB_OVER_CURRENT): */
-      default:
-     }
-     break;
-   case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
-     switch (wValue) {
-       case (RH_PORT_SUSPEND):
-         writel(RH_PS_PSS, &ohci->regs->roothub.portstatus[wIndex-1]);
-         len=0;
-         req_reply = RH_ACK;
-         break;
-       case (RH_PORT_RESET):
-         if((readl(&ohci->regs->roothub.portstatus[wIndex-1]) &1) != 0)  /* BUG IN HUP CODE *********/
-         writel(RH_PS_PRS, &ohci->regs->roothub.portstatus[wIndex-1]);
-         len=0;
-         req_reply = RH_ACK;
-         break;
-       case (RH_PORT_POWER):
-         writel(RH_PS_PPS, &ohci->regs->roothub.portstatus[wIndex-1]);
-         len=0;
-         req_reply = RH_ACK;
-         break;
-       case (RH_PORT_ENABLE):
-         writel(RH_PS_PES, &ohci->regs->roothub.portstatus[wIndex-1]);
-         len=0;
-         req_reply = RH_ACK;
-         break;
-       /*
-       case (RH_PORT_CONNECTION):
-       case (RH_PORT_OVER_CURRENT):
-       case (RH_PORT_LOW_SPEED):
-       case (RH_C_PORT_CONNECTION):
-       case (RH_C_PORT_ENABLE):
-       case (RH_C_PORT_SUSPEND):
-       case (RH_C_PORT_OVER_CURRENT):
-       case (RH_C_PORT_RESET):
-       */
-       default:  
-     }
-     break;
-
-  case RH_SET_ADDRESS:
-     ohci->root_hub_funct_addr = wValue; 
-	/* ohci->ed_func_ep0[wValue] = &ohci->ed_rh_ep0;
-	 ohci->ed_func_ep0[wValue]->ep_addr.bep.fa = wValue; 
-	 ohci->ed_func_ep0[wValue]->ed_list = &ohci->ed_rh_epi; */
-	 ohci->ed_rh_epi.ed_list = NULL;
-	 ohci->ed_rh_epi.ep_addr.bep.fa = wValue;
-	 ohci->ed_rh_epi.ep_addr.bep.ep = 0xa1; /* Int in port 1 */
-     ohci->ed_func_ep0[0]= NULL;
-     len = 0;
-     req_reply = RH_ACK;
-     break;
-
-   case RH_GET_DESCRIPTOR:
-     switch ((wValue & 0xff00) >> 8) {
-     case (0x01): /* device descriptor */
-       len = min(sizeof(root_hub_dev_des), wLength);
-       memcpy(data, root_hub_dev_des, len);
-       req_reply = RH_ACK;
-       break;
-     case (0x02): /* configuration descriptor */
-       len = min(sizeof(root_hub_config_des), wLength);
-       memcpy(data, root_hub_config_des, len);
-       req_reply = RH_ACK;
-       break;
-     case (0x03): /* string descriptors */
-     default:
-     }
-     break;
-  case RH_GET_DESCRIPTOR | RH_CLASS:
-     data[1] = 0x29;
-     stat = readl(&ohci->regs->roothub.a);  
-     data[2] = stat & 0xff;        /* number of ports */
-     data[0] = (data[2] / 8) * 2 + 9; /* length of descriptor */
-     if(data[0] > wLength) {
-       req_reply =  RH_REQ_ERR;
-       break;
-     }
-     data[3] = (stat >> 8) & 0xff;
-     data[4] = (stat >> 16) & 0xff;
-     data[5] = (stat >> 24) & 0xff;
-     data[6] = 0; /* Root Hub needs no current from bus */
-     stat = readl(&ohci->regs->roothub.b); 
-     if(data[2] <= 8) { /* less than 8 Ports */
-       data[7] = stat & 0xff;
-       data[8] = (stat >> 16) & 0xff; /* 0xff for USB Rev. 1.1 ?, stat >> 16 for USB Rev. 1.0 */
-     }
-     else {
-       data[7] = stat & 0xff;
-       data[8] = (stat >> 8) & 0xff;
-       data[9] = (stat >> 16) & 0xff;  /* 0xff for USB Rev. 1.1?, stat >> 16 for USB Rev. 1.0 */
-       data[10] = (stat >> 24) & 0xff; /* 0xff for USB Rev. 1.1?, stat >> 24 for USB Rev. 1.0 */
-     }
-     len = data[0];
-     req_reply = RH_ACK;
-     break;
-
-   case RH_SET_DESCRIPTOR:
-     break;
-
-   case RH_GET_CONFIGURATION:
-     len = 1;
-     data[0] = 0x01;
-     req_reply = RH_ACK;
-     break;
-
-   case RH_SET_CONFIGURATION: /* start it up */
-     writel( 0x10000, &ohci->regs->roothub.status);
-     /*writel( OHCI_INTR_RHSC, &ohci->regs->intrenable);*/
-     len = 0;
-     req_reply = RH_ACK;
-     break;
-   /*  Optional or meaningless requests 
-     case RH_GET_STATE | RH_OTHER | RH_CLASS:
-     case RH_GET_INTERFACE | RH_INTERFACE:
-     case RH_SET_INTERFACE | RH_INTERFACE:
-     case RH_SYNC_FRAME | RH_ENDPOINT: 
-   */
-
-  /* Vendor Requests, we are the vendor!
-	Will the USB-Consortium give us a Vendor Id
-	for a virtual hub-device :-) ?
-     We could use these requests for configuration purposes on the HCD Driver, not used in the altenate usb !*/ 
-
-  case RH_SET_FEATURE | RH_VENDOR: /* remove all endpoints of device wIndex = Dev << 8  */
-    switch(wValue) {
-    case RH_REMOVE_EP:
-      ep_addr.iep = 0;
-      ep_addr.bep.ep = wIndex & 0xff;
-      ep_addr.bep.fa = (wIndex << 8) & 0xff00;
-      usb_ohci_rm_function(ohci, ep_addr.iep);
-      len=0;
-      req_reply = RH_ACK;
-      break;
-    }
-    break;
-  case RH_SET_FEATURE | RH_ENDPOINT | RH_VENDOR: /* remove endpoint wIndex = Dev << 8 | EP */
-    switch(wValue) {
-    case RH_REMOVE_EP: 
-      ep_addr.iep = 0;
-      ep_addr.bep.ep = wIndex & 0xff;
-      ep_addr.bep.fa = (wIndex << 8) & 0xff00;
-      usb_ohci_rm_ep(ohci, ohci_find_ep(ohci, ep_addr.iep));
-      len=0;
-      req_reply = RH_ACK;
-      break;
-    }
-    break;
-  case RH_SET_EP | RH_ENDPOINT | RH_VENDOR:   
-    ep_addr.bep.ep = data[0];
-    ep_addr.bep.fa = data[1];
-    ep_addr.bep.hc = data[2];
-    ep_addr.bep.host = data[3];  
-    rep_handler  = data[7] << 24 |data[6] << 16 | data[5] << 8 | data[4];
-    /*  struct usb_ohci_ed *usb_ohci_add_ep(union ep_addr_ ep_addr,
-	struct ohci * ohci, int interval, int load, int (*handler)(int, void*), int ep_size, int speed) */
-    usb_ohci_add_ep(ohci, ep_addr.iep, data[8], data[9], (f_handler) rep_handler, data[11] << 8 | data[10] , data[12]);
-    len=0;
-    req_reply = RH_ACK;
-    break;
-
-  default: 
-  }
- printk("USB HC roothubstat1: %x \n", readl( &(ohci->regs->roothub.portstatus[0]) ));
-  printk("USB HC roothubstat2: %x \n", readl( &(ohci->regs->roothub.portstatus[1]) ));
-
-  /* if (req_reply == RH_ACK) len; */
-  queue_reply(ohci, ep_addr_ret.iep, 8, rh_cmd, data, len, lw0, lw1, handler);
-  return 0;
-}
-
-int root_hub_int_req(struct ohci * ohci, int cmd_len, void * ctrl, void *  data, int data_len, __OHCI_BAG lw0, __OHCI_BAG lw1, f_handler handler){
+		case RH_GET_STATUS: 				 		*(__u16 *)data = cpu_to_le16(1); OK(2);
+		case RH_GET_STATUS | RH_INTERFACE: 	 		*(__u16 *)data = cpu_to_le16(0); OK(2);
+		case RH_GET_STATUS | RH_ENDPOINT:	 		*(__u16 *)data = cpu_to_le16(0); OK(2);   
+		case RH_GET_STATUS | RH_CLASS: 				*(__u32 *)data = cpu_to_le32(RD_RH_STAT & 0x7fff7fff); OK(4);
+		case RH_GET_STATUS | RH_OTHER | RH_CLASS: 	*(__u32 *)data = cpu_to_le32(RD_RH_PORTSTAT); OK(4);
+
+		case RH_CLEAR_FEATURE | RH_ENDPOINT:  
+			switch (wValue) {
+				case (RH_ENDPOINT_STALL): OK(0);
+			}
+			break;
+
+		case RH_CLEAR_FEATURE | RH_CLASS:
+			switch (wValue) {
+				case (RH_C_HUB_OVER_CURRENT): WR_RH_STAT(RH_PS_OCIC); OK(0);
+			}
+			break;
+		
+		case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
+			switch (wValue) {
+				case (RH_PORT_ENABLE): 			WR_RH_PORTSTAT(RH_PS_CCS ); OK(0);
+				case (RH_PORT_SUSPEND):			WR_RH_PORTSTAT(RH_PS_POCI); OK(0);
+				case (RH_PORT_POWER):			WR_RH_PORTSTAT(RH_PS_LSDA); OK(0);
+				case (RH_C_PORT_CONNECTION):	WR_RH_PORTSTAT(RH_PS_CSC ); OK(0);
+				case (RH_C_PORT_ENABLE):		WR_RH_PORTSTAT(RH_PS_PESC); OK(0);
+				case (RH_C_PORT_SUSPEND):		WR_RH_PORTSTAT(RH_PS_PSSC); OK(0);
+				case (RH_C_PORT_OVER_CURRENT):	WR_RH_PORTSTAT(RH_PS_OCIC); OK(0);
+				case (RH_C_PORT_RESET):			WR_RH_PORTSTAT(RH_PS_PRSC); OK(0); 
+			}
+			break;
+ 
+		case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
+			switch (wValue) {
+				case (RH_PORT_SUSPEND):			WR_RH_PORTSTAT(RH_PS_PSS ); OK(0); 
+				case (RH_PORT_RESET): if((RD_RH_PORTSTAT &1) != 0)  WR_RH_PORTSTAT(RH_PS_PRS ); /* BUG IN HUP CODE *********/ OK(0);
+				case (RH_PORT_POWER):			WR_RH_PORTSTAT(RH_PS_PPS ); OK(0); 
+				case (RH_PORT_ENABLE):			WR_RH_PORTSTAT(RH_PS_PES ); OK(0);
+			}
+			break;
+
+		case RH_SET_ADDRESS: ohci->rh.devnum = wValue; OK(0);
+
+		case RH_GET_DESCRIPTOR:
+			switch ((wValue & 0xff00) >> 8) {
+				case (0x01): /* device descriptor */
+					len = min(leni, min(sizeof(root_hub_dev_des), wLength));
+					memcpy(data, root_hub_dev_des, len); OK(len);
+				case (0x02): /* configuration descriptor */
+					len = min(leni, min(sizeof(root_hub_config_des), wLength));
+					memcpy(data, root_hub_config_des, len); OK(len);
+				case (0x03): /* string descriptors */
+				default:
+			}
+			break;
+		
+		case RH_GET_DESCRIPTOR | RH_CLASS:
+			*(__u8 *)(data_buf+1) = 0x29;
+			*(__u32 *)(data_buf+2) = cpu_to_le32(readl(&ohci->regs->roothub.a));  
+	 		*(__u8 *)data_buf = (*(__u8 *)(data_buf+2) / 8) * 2 + 9; /* length of descriptor */
+				 
+			len = min(leni, min(*(__u8 *)data_buf, wLength));
+			*(__u8 *)(data_buf+6) = 0; /* Root Hub needs no current from bus */
+			if(*(__u8 *)(data_buf+2) < 8) { /* less than 8 Ports */
+				*(__u8 *) (data_buf+7) = readl(&ohci->regs->roothub.b) & 0xff; 
+				*(__u8 *) (data_buf+8) = (readl(&ohci->regs->roothub.b) & 0xff0000) >> 16; 
+			}
+			else {
+				*(__u32 *) (data_buf+7) = cpu_to_le32(readl(&ohci->regs->roothub.b)); 
+			}
+			memcpy(data, data_buf, len);
+			OK(len); 
+ 
+		case RH_GET_CONFIGURATION: 	*(__u8 *)data = 0x01; OK(1);
 
-	struct ohci_rep_td *td;
- 	struct ohci_rep_td *tmp;
- 	union ep_addr_ ep_addr;
- 	
- 	td = kmalloc(sizeof(td),GFP_KERNEL);
- 	tmp = ohci->td_rh_epi;
- 	td->next_td = NULL;
- 	if(tmp == NULL) { /* queue td */
- 		ohci->td_rh_epi = td;	
- 	}
- 	else {
- 		while(tmp->next_td != NULL) tmp = tmp->next_td;
- 		tmp->next_td = td;
- 	}
- 	ep_addr.iep = 0;
- 	ep_addr.bep.fa = ohci->root_hub_funct_addr;
- 	ep_addr.bep.ep = 0xA1; /* INT IN EP endpoint 1 */
-  	td->cmd_len = 0;
-  	td->cmd = NULL;
-  	td->data = data;
-  	td->data_len = data_len;
-  	td->handler = handler; 
-  	td->next_td = NULL;
-  	td->ep_addr = ep_addr.iep;
-	td->lw0 = lw0;
-	td->lw1 = lw1;
-	ohci_init_rh_int_timer(ohci, 255);
-	return 0;
+		case RH_SET_CONFIGURATION: 	WR_RH_STAT( 0x10000); OK(0);
+	}
+	
+	OHCI_DEBUG(printk("USB HC roothubstat1: %x \n", readl( &(ohci->regs->roothub.portstatus[0]) ));)
+	OHCI_DEBUG(printk("USB HC roothubstat2: %x \n", readl( &(ohci->regs->roothub.portstatus[1]) ));)
+  		
+	OHCI_DEBUG( { int i; printk("USB HC RH bh <<<: 1: ");)
+	OHCI_DEBUG( printk(" data(%d):", len);) 
+	OHCI_DEBUG( { for(i=0; i < len; i++ ) printk(" %02x", ((__u8 *) data)[i]);)
+	OHCI_DEBUG( printk(" ret_status: %x\n", req_reply); })
+	
+	return req_reply;
 }
 
-
-/* prepare Interrupt pipe transaction data; HUP INTERRUPT ENDPOINT */ 
-int root_hub_send_irq(struct ohci * ohci, void * rh_data, int rh_len ) {
+/* prepare Interrupt pipe transaction data; HUB INTERRUPT ENDPOINT */ 
+static int root_hub_send_irq(struct ohci * ohci, void * rh_data, int rh_len ) {
 
   int num_ports;
   int i;
@@ -496,12 +253,12 @@
   __u8 * data = rh_data;
 
   num_ports = readl(&ohci->regs->roothub.a) & 0xff; 
-  data[0] = (readl(&ohci->regs->roothub.status) & 0x00030000)>0?1:0;
-  ret = data[0];
+  *(__u8 *)data = (readl(&ohci->regs->roothub.status) & 0x00030000)>0?1:0;
+  ret = *(__u8 *)data;
 
   for(i=0; i < num_ports; i++) {
-    data[i/8] |= ((readl(&ohci->regs->roothub.portstatus[i]) & 0x001f0000)>0?1:0) << ((i+1) % 8);
-    ret += data[i/8];
+    *(__u8 *)(data+i/8) |= ((readl(&ohci->regs->roothub.portstatus[i]) & 0x001f0000)>0?1:0) << ((i+1) % 8);
+    ret += *(__u8 *)(data+i/8);
   }
   len = i/8 + 1;
   
@@ -510,95 +267,79 @@
   return  RH_NACK;
 }
 
-
-
-
  
-static struct timer_list rh_int_timer;
+static int ohci_init_rh_int_timer(struct usb_device * usb_dev, int interval);
 
 /* Virtual Root Hub INTs are polled by this timer every "intervall" ms */
 static void rh_int_timer_do(unsigned long ptr) {
 	int len; 
 	int interval;
-	struct ohci * ohci = (struct ohci *) ptr;
-    struct ohci_rep_td *td = ohci->td_rh_epi;
+	int ret;
+	
+	struct usb_device * usb_dev = (struct usb_device *) ptr;
+    struct ohci * ohci = usb_dev->bus->hcpriv;
+	struct ohci_device * dev = usb_to_ohci(usb_dev);
 
-	if(td != NULL) { /* if ther is a TD handle the INT request */
-		
-		len = root_hub_send_irq(ohci, td->data, td->data_len );
-		if(len > 0) {
-			ohci->td_rh_epi = td->next_td;
-			td->next_td = ohci->repl_queue; 
-			ohci->repl_queue = td;
-			send_replies(ohci);
+
+	if(ohci->rh.send) { 
+		len = root_hub_send_irq(ohci, dev->data, 1 );
+
+		if(len > 0) { 
+			OHCI_DEBUG({ int i; printk("USB HC IRQ <<<: RH data(%d):", len);)
+			OHCI_DEBUG( for(i=0; i < len; i++ ) printk(" %02x", ((__u8 *) dev->data)[i]);)
+			OHCI_DEBUG( printk(" ret_status: %x\n", 0); })
+ 
+			ret = ohci->rh.handler(0, dev->data, len, ohci->rh.dev_id);
+			if(ret <= 0)ohci->rh.send = 0; /* 0 .. do not requeue  */
 		}
 	}	
-	interval = ohci->rh_int_interval;
-	init_timer(& rh_int_timer);
-	rh_int_timer.function = rh_int_timer_do;
-	rh_int_timer.data = (unsigned long) ohci;
-	rh_int_timer.expires = jiffies + (HZ * (interval<30?30: interval)) /1000;
-	add_timer(&rh_int_timer);
+	interval = ohci->rh.interval;
+	ohci_init_rh_int_timer(usb_dev, interval);
 }
 
 /* Root Hub INTs are polled by this timer */
-int ohci_init_rh_int_timer(struct ohci * ohci, int interval) {
+static int ohci_init_rh_int_timer(struct usb_device * usb_dev, int interval) {
+	struct ohci * ohci = usb_dev->bus->hcpriv;
 
-	if(!(ohci->rh_int_timer)) { 
-		ohci->rh_int_timer = 1;
-		ohci->rh_int_interval = interval;
-		init_timer(& rh_int_timer);
-		rh_int_timer.function = rh_int_timer_do;
-		rh_int_timer.data = (unsigned long) ohci;
-		rh_int_timer.expires = jiffies + (HZ * (interval<30?30: interval)) /1000;
-		add_timer(&rh_int_timer);
-	}
+	ohci->rh.interval = interval;
+	init_timer(& ohci->rh.rh_int_timer);
+	ohci->rh.rh_int_timer.function = rh_int_timer_do;
+	ohci->rh.rh_int_timer.data = (unsigned long) usb_dev;
+	ohci->rh.rh_int_timer.expires = jiffies + (HZ * (interval<30?30: interval)) /1000;
+	add_timer(&ohci->rh.rh_int_timer);
+	
 	return 0;
 }
 
-int ohci_del_rh_int_timer(struct ohci * ohci) {
-	del_timer(&rh_int_timer);
+static int ohci_del_rh_int_timer(struct ohci * ohci) {
+	del_timer(&ohci->rh.rh_int_timer);
 	return 0;
 }
-/* for root hub replies, queue the reply, (it will be sent immediately now) */
-
-int queue_reply(struct ohci * ohci, unsigned int ep_addr, int cmd_len,void * cmd, void * data,int  len, __OHCI_BAG lw0, __OHCI_BAG lw1, f_handler handler) {
-
- struct ohci_rep_td *td;
- int status = 0;
  
-printk("queue_reply ep: %x len: %x\n", ep_addr, len);
-td = kmalloc(sizeof(td), GFP_KERNEL);
-
-  if (len < 0) { status = len; len = 0;}
-  td->cmd_len = cmd_len;
-  td->cmd = cmd;
-  td->data = data;
-  td->data_len = len;
-  td->handler = handler; 
-  td->next_td = ohci->repl_queue; ohci->repl_queue = td;
-  td->ep_addr = ep_addr;
-  td->lw0 = lw0;
-  td->lw1 = lw1;
-  td->status = status;
-  send_replies(ohci);
-return 0;
+void * root_hub_request_irq(struct usb_device *usb_dev, unsigned int pipe, usb_device_irq handler, int period, void *dev_id) 
+{
+	struct ohci * ohci = usb_dev->bus->hcpriv;
+	
+	OHCI_DEBUG( printk("USB HC-RH IRQ>>>: RH every %d ms\n", period);) 
+	ohci->rh.handler = handler;
+	ohci->rh.dev_id =  dev_id;
+	ohci->rh.send = 1;
+	ohci->rh.interval = period;
+	ohci_init_rh_int_timer(usb_dev, period);
+	return ohci->rh.int_addr = usb_to_ohci(usb_dev);
 }
 
-/* for root hub replies; send the reply */
-int send_replies(struct ohci * ohci) { 
-	struct ohci_rep_td *td;
-	struct ohci_rep_td *tmp;
-
-	td = ohci->repl_queue; ohci->repl_queue = NULL;
-	while ( td != NULL) {
-		td->handler((void *) ohci, td->ep_addr,td->cmd_len,td->cmd, td->data, td->data_len, td->status, td->lw0, td->lw1); 
-		tmp = td;
-		td = td->next_td;
-	
-		kfree(tmp);
-	}
+int root_hub_release_irq(struct usb_device *usb_dev, void * ed) 
+{
+	// struct usb_device *usb_dev = ((struct ohci_device *) ((unsigned int)ed & 0xfffff000))->usb;
+	struct ohci * ohci = usb_dev->bus->hcpriv;
+
+	OHCI_DEBUG( printk("USB HC-RH RM_IRQ>>>:\n");) 
+	ohci->rh.send = 0;
+	ohci_del_rh_int_timer(ohci);
 	return 0;
 }
+
+
  
 #endif
diff -u --recursive --new-file v2.3.13/linux/drivers/usb/ohci.c linux/drivers/usb/ohci.c
--- v2.3.13/linux/drivers/usb/ohci.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/usb/ohci.c	Wed Aug 18 16:22:23 1999
@@ -266,7 +266,7 @@
 	int_ed = &root_hub->ed[ms_to_ed_int(period)];
 
 	/* decide on what the status field should look like */
-	req_status = ed_set_maxpacket(usb_maxpacket(ohci_to_usb(dev), pipe))
+	req_status = ed_set_maxpacket(usb_maxpacket(ohci_to_usb(dev), pipe, usb_pipeout(pipe)))
 		| ed_set_speed(usb_pipeslow(pipe))
 		| (usb_pipe_endpdev(pipe) & 0x7ff)
 		| ed_set_type_isoc(isoc);
@@ -943,7 +943,7 @@
 	struct ohci_device *dev = usb_to_ohci(usb);
 	struct ohci_td *td;
 	struct ohci_ed *interrupt_ed;	/* endpoint descriptor for this irq */
-	int maxps = usb_maxpacket(usb, pipe);
+	int maxps = usb_maxpacket(usb, pipe, usb_pipeout(pipe));
 	unsigned long flags;
 
 	/* Get an ED and TD */
@@ -1011,7 +1011,7 @@
  *
  * This function can NOT be called from an interrupt.
  */
-int ohci_release_irq(void* handle)
+int ohci_release_irq(struct usb_device *usb, void* handle)
 {
 	struct ohci_device *dev;
 	struct ohci_td *int_td;
@@ -1120,8 +1120,8 @@
 	 * device number (function address), and type of TD.
 	 *
 	 */
-	ohci_fill_ed(dev, control_ed, usb_maxpacket(usb,pipe), usb_pipeslow(pipe),
-		usb_pipe_endpdev(pipe), 0 /* normal TDs */);
+	ohci_fill_ed(dev, control_ed, usb_maxpacket(usb, pipe, usb_pipeout(pipe)),
+		usb_pipeslow(pipe), usb_pipe_endpdev(pipe), 0 /* normal TDs */);
 
 	/*
 	 * Build the control TD
@@ -1398,7 +1398,7 @@
 	/* Set the max packet size, device speed, endpoint number, usb
 	 * device number (function address), and type of TD. */
 	ohci_fill_ed(dev, bulk_ed,
-		usb_maxpacket(usb_dev, pipe),
+		usb_maxpacket(usb_dev, pipe, usb_pipeout(pipe)),
 		usb_pipeslow(pipe),
 		usb_pipe_endpdev(pipe), 0 /* bulk uses normal TDs */);
 
@@ -1480,7 +1480,7 @@
 	if (bytes_transferred_p)
 		*bytes_transferred_p = 0;
 
-	if (usb_endpoint_halted(usb_dev, usb_pipeendpoint(pipe))
+	if (usb_endpoint_halted(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))
 	    && usb_clear_halt(usb_dev, usb_pipeendpoint(pipe) | (pipe & 0x80)))
 		return USB_ST_STALL;
 
@@ -1979,6 +1979,23 @@
 	return td_list;
 } /* ohci_reverse_donelist() */
 
+/*
+ * Look at the ed (and td if necessary)
+ * and return its direction as 0 = IN, 1 = OUT.
+ */
+int ed_get_dir (struct ohci_ed *ed, struct ohci_td *td)
+{
+	__u32 status;
+	
+	status = le32_to_cpu(ed->status) & OHCI_ED_D; /* keep only the Direction bits */	
+	if (status == OHCI_ED_D_IN) return 0;
+	if (status == OHCI_ED_D_OUT) return 1;
+	
+	/* but if status == 0 or 3, look at the td for the Direction */
+	status = le32_to_cpu(td->info) & OHCI_TD_D; /* keep only the Direction bits */
+	if (status == OHCI_TD_D_IN) return 0;
+	return 1;
+}
 
 /*
  * Collect this interrupt's goodies off of the list of finished TDs
@@ -2017,7 +2034,7 @@
 
 		if (cc == USB_ST_STALL) {
 			/* mark endpoint as halted */
-			usb_endpoint_halt(ed->ohci_dev->usb, ed_get_en(ed));
+			usb_endpoint_halt(ed->ohci_dev->usb, ed_get_en(ed), ed_get_dir(ed, td));
 		}
 
 		if (cc != 0 && ohci_ed_halted(ed) && !td_endofchain(*td)) {
diff -u --recursive --new-file v2.3.13/linux/drivers/usb/printer.c linux/drivers/usb/printer.c
--- v2.3.13/linux/drivers/usb/printer.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/usb/printer.c	Wed Aug 18 16:22:23 1999
@@ -266,7 +266,7 @@
 		return -1;
 	}
 
-	interface = dev->config->altsetting->interface;
+	interface = &dev->config[0].interface[0].altsetting[0];
 
 	/* Lets be paranoid (for the moment)*/
 	if (interface->bInterfaceClass != 7 ||
diff -u --recursive --new-file v2.3.13/linux/drivers/usb/proc_usb.c linux/drivers/usb/proc_usb.c
--- v2.3.13/linux/drivers/usb/proc_usb.c	Wed Jul 28 14:47:42 1999
+++ linux/drivers/usb/proc_usb.c	Mon Aug 16 23:19:13 1999
@@ -213,7 +213,7 @@
 				const int active, char *buf, int *len)
 {
 	int i, j;
-	struct usb_alternate_setting *as;
+	struct usb_interface *intf;
 
 	if (!config) {		/* getting these some in 2.3.7; none in 2.3.6 */
 		*len += sprintf (buf + *len, "(null Cfg. desc.)\n");
@@ -223,13 +223,13 @@
 	if (usb_dump_config_descriptor (config, active, buf, len) < 0)
 		return -1;
 
-	for (i = 0; i < config->num_altsetting; i++) {
-		as = config->altsetting + i;
-		if ((as) == NULL)
+	for (i = 0; i < config->bNumInterfaces; i++) {
+		intf = config->interface + i;
+		if ((intf) == NULL)
 			break;
 
-		for (j = 0; j < config->bNumInterfaces; j++)
-			if (usb_dump_interface (as->interface + j, buf, len) < 0)
+		for (j = 0; j < intf->num_altsetting; j++)
+			if (usb_dump_interface (intf->altsetting + j, buf, len) < 0)
 				return -1;
 	}
 
diff -u --recursive --new-file v2.3.13/linux/drivers/usb/uhci.c linux/drivers/usb/uhci.c
--- v2.3.13/linux/drivers/usb/uhci.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/usb/uhci.c	Wed Aug 18 16:22:23 1999
@@ -63,7 +63,10 @@
 #define UHCI_DEBUG
 
 /*
- * Map status to standard result codes
+ * Map status to standard result codes.
+ *
+ * <status> is ((td->status >> 16) & 0xff) [a.k.a. uhci_status_bits(td->status)]
+ * <dir_out> is True for output TDs and False for input TDs.
  */
 static int uhci_map_status(int status, int dir_out)
 {
@@ -109,19 +112,19 @@
 	/* locate the first failing td, if any */
 
 	do {
-		status = (tmp->status >> 16) & 0xff;
+		status = uhci_status_bits(tmp->status);
 		if (status) {
 			/* must reset the toggle on first error */
     			if (uhci_debug) {
 				printk(KERN_DEBUG "Set toggle from %x rval %ld\n",
 					(unsigned int)tmp, rval ? *rval : 0);
 			}
-			usb_settoggle(dev->usb, usb_pipeendpoint(tmp->info),
-				usb_pipeout(tmp->info), (tmp->info >> 19) & 1);
+			usb_settoggle(dev->usb, uhci_endpoint(tmp->info),
+				uhci_packetout(tmp->info), uhci_toggle(tmp->info));
 			break;
 		} else {
 		    if (rval)
-			*rval += (tmp->status & 0x3ff) + 1;
+			*rval += uhci_actual_length(tmp->status);
 		}
 		if ((tmp->link & UHCI_PTR_TERM) ||
 		    (tmp->link & UHCI_PTR_QH))
@@ -153,7 +156,8 @@
 
 	if (status & 0x40) {
 		/* endpoint has stalled - mark it halted */
-		usb_endpoint_halt(dev->usb, usb_pipeendpoint(tmp->info));
+		usb_endpoint_halt(dev->usb, uhci_endpoint(tmp->info),
+	    			uhci_packetout(tmp->info));
 		return USB_ST_STALL;
 	}
 
@@ -162,7 +166,7 @@
 		if (!rval)
 			return USB_ST_DATAUNDERRUN;
 	}
-	return uhci_map_status(status, usb_pipeout(tmp->info));		
+	return uhci_map_status(status, uhci_packetout(tmp->info));
 }
 
 /*
@@ -431,9 +435,8 @@
 
 	td->link = UHCI_PTR_TERM;		/* Terminate */
 	td->status = status;			/* In */
-	td->info = destination | ((usb_maxpacket(usb_dev, pipe) - 1) << 21) |
-		(usb_gettoggle(usb_dev, usb_pipeendpoint(pipe),
-		usb_pipeout(pipe)) << 19);
+	td->info = destination | ((usb_maxpacket(usb_dev, pipe, usb_pipeout(pipe)) - 1) << 21) |
+  		(usb_gettoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) << TD_TOKEN_TOGGLE);
 	td->buffer = virt_to_bus(dev->data);
 	td->qh = qh;
 	td->dev = dev;
@@ -463,7 +466,7 @@
  *
  * This function can NOT be called from an interrupt.
  */
-int uhci_release_irq(void *handle)
+int uhci_release_irq(struct usb_device *usb, void *handle)
 {
 	struct uhci_td *td;
 	struct uhci_qh *qh;
@@ -506,14 +509,14 @@
 	for (i = 0; i < isodesc->num; i++) {
 		struct uhci_td *td = &isodesc->td[i];
 		char *cdata = uhci_ptr_to_virt(td->buffer);
-		int n = (td->status + 1) & 0x7FF;
+		int n = uhci_actual_length(td->status);
 
 		if ((cdata != data) && (n))
 			memmove(data, cdata, n);
 
 #ifdef UHCI_DEBUG
 		/* Debugging */
-		if ((td->status >> 16) & 0xFF)
+		if (uhci_status_bits(td->status))
 			printk(KERN_DEBUG "error: %d %X\n", i,
 				(td->status >> 16));
 #endif
@@ -782,15 +785,15 @@
 	struct uhci_td *first, *td, *prevtd;
 	unsigned long destination, status;
 	int ret, count;
-	int maxsze = usb_maxpacket(usb_dev, pipe);
+	int maxsze = usb_maxpacket(usb_dev, pipe, usb_pipeout(pipe));
 	__u32 nextlink;
 
 	first = td = uhci_td_alloc(dev);
 	if (!td)
 		return -ENOMEM;
 
-	/* The "pipe" thing contains the destination in bits 8--18, 0x2D is SETUP */
-	destination = (pipe & PIPE_DEVEP_MASK) | 0x2D;
+	/* The "pipe" thing contains the destination in bits 8--18. */
+	destination = (pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP;
 
 	/* 3 errors */
 	status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_SPD | (3 << 27);
@@ -804,11 +807,11 @@
 
 	/*
 	 * If direction is "send", change the frame from SETUP (0x2D)
-	 * to OUT (0xE1). Else change it from SETUP to IN (0x69)
+	 * to OUT (0xE1). Else change it from SETUP to IN (0x69).
 	 */
-	destination ^= (0x2D ^ 0x69);			/* SETUP -> IN */
+	destination ^= (USB_PID_SETUP ^ USB_PID_IN);		/* SETUP -> IN */
 	if (usb_pipeout(pipe))
-		destination ^= (0xE1 ^ 0x69);		/* IN -> OUT */
+		destination ^= (USB_PID_OUT ^ USB_PID_IN);	/* IN -> OUT */
 
 	prevtd = td;
 	td = uhci_td_alloc(dev);
@@ -828,7 +831,7 @@
 			pktsze = maxsze;
 
 		/* Alternate Data0/1 (start with Data1) */
-		destination ^= 1 << 19;
+		destination ^= 1 << TD_TOKEN_TOGGLE;
 	
 		td->status = status;					/* Status */
 		td->info = destination | ((pktsze - 1) << 21);		/* pktsze bytes of data */
@@ -848,8 +851,8 @@
 	/*
 	 * Build the final TD for control status 
 	 */
-	destination ^= (0xE1 ^ 0x69);			/* OUT -> IN */
-	destination |= 1 << 19;				/* End in Data1 */
+	destination ^= (USB_PID_OUT ^ USB_PID_IN);	/* OUT -> IN */
+	destination |= 1 << TD_TOKEN_TOGGLE;		/* End in Data1 */
 
 	td->status = status | TD_CTRL_IOC;			/* no limit on errors on final packet */
 	td->info = destination | (UHCI_NULL_DATA_SIZE << 21);	/* 0 bytes of data */
@@ -962,13 +965,13 @@
 	struct uhci_td *first, *td, *prevtd;
 	unsigned long destination, status;
 	int ret;
-	int maxsze = usb_maxpacket(usb_dev, pipe);
+	int maxsze = usb_maxpacket(usb_dev, pipe, usb_pipeout(pipe));
 
-	if (usb_endpoint_halted(usb_dev, usb_pipeendpoint(pipe)) &&
-	    usb_clear_halt(usb_dev, usb_pipeendpoint(pipe) | (pipe & 0x80)))
+	if (usb_endpoint_halted(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) &&
+	    usb_clear_halt(usb_dev, usb_pipeendpoint(pipe) | (pipe & USB_DIR_IN)))
 		return USB_ST_STALL;
 
-	/* The "pipe" thing contains the destination in bits 8--18 */
+	/* The "pipe" thing contains the destination in bits 8--18. */
 	destination = (pipe & PIPE_DEVEP_MASK) | usb_packetid (pipe);
 
 	/* 3 errors */
@@ -991,7 +994,8 @@
 
 		td->status = status;					/* Status */
 		td->info = destination | ((pktsze-1) << 21) |
-			 (usb_gettoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) << 19); /* pktsze bytes of data */
+			(usb_gettoggle(usb_dev, usb_pipeendpoint(pipe),
+				usb_pipeout(pipe)) << TD_TOKEN_TOGGLE); /* pktsze bytes of data */
 		td->buffer = virt_to_bus(data);
 		td->backptr = &prevtd->link;
 
@@ -1049,10 +1053,10 @@
 	struct uhci_td *first, *td, *prevtd;
 	struct uhci_qh *bulk_qh = uhci_qh_alloc(dev);
 	unsigned long destination, status;
-	int maxsze = usb_maxpacket(usb_dev, pipe);
+	int maxsze = usb_maxpacket(usb_dev, pipe, usb_pipeout(pipe));
 
-	/* The "pipe" thing contains the destination in bits 8--18, 0x69 is IN */
-	destination = (pipe & 0x0007ff00) | usb_packetid(pipe);
+	/* The "pipe" thing contains the destination in bits 8--18. */
+	destination = (pipe & PIPE_DEVEP_MASK) | usb_packetid(pipe);
 
 	/* Infinite errors is 0 */
 	status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_SPD;
@@ -1069,7 +1073,7 @@
 
 		td->status = status;                                    /* Status */
 		td->info = destination | ((pktsze-1) << 21) |
-			(usb_gettoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) << 19); /* pktsze bytes of data */
+			(usb_gettoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) << TD_TOKEN_TOGGLE); /* pktsze bytes of data */
 		td->buffer = virt_to_bus(data);
 		td->backptr = &prevtd->link;
 		td->qh = bulk_qh;
@@ -1336,7 +1340,7 @@
 		list_del(&td->irq_list);
 		INIT_LIST_HEAD(&td->irq_list);
 
-		if (td->completed(uhci_map_status(status, 0),
+		if (td->completed(uhci_map_status(uhci_status_bits(status), uhci_packetout(td->info)),
 		    bus_to_virt(td->buffer), -1, td->dev_id)) {
 			list_add(&td->irq_list, &uhci->interrupt_list);
 
@@ -1344,11 +1348,12 @@
 			if (!(td->status & TD_CTRL_IOS)) {
 				struct usb_device *usb_dev = td->dev->usb;
 
-				usb_dotoggle(usb_dev, usb_pipeendpoint(td->info), usb_pipeout(td->info));
-				td->info &= ~(1 << 19); /* clear data toggle */
-				td->info |= usb_gettoggle(usb_dev, usb_pipeendpoint(td->info), usb_pipeout(td->info)) << 19; /* toggle between data0 and data1 */
+				usb_dotoggle(usb_dev, uhci_endpoint(td->info), uhci_packetout(td->info));
+				td->info &= ~(1 << TD_TOKEN_TOGGLE); /* clear data toggle */
+				td->info |= usb_gettoggle(usb_dev, uhci_endpoint(td->info),
+					uhci_packetout(td->info)) << TD_TOKEN_TOGGLE; /* toggle between data0 and data1 */
 				td->status = (td->status & 0x2F000000) | TD_CTRL_ACTIVE | TD_CTRL_IOC;
-				/* The HC removes it, so readd it */
+				/* The HC removes it, so re-add it */
 				uhci_insert_td_in_qh(td->qh, td);
 			}
 		} else if (td->flags & UHCI_TD_REMOVE) {
@@ -1356,7 +1361,7 @@
 
 			/* marked for removal */
 			td->flags &= ~UHCI_TD_REMOVE;
-			usb_dotoggle(usb_dev, usb_pipeendpoint(td->info), usb_pipeout(td->info));
+			usb_dotoggle(usb_dev, uhci_endpoint(td->info), uhci_packetout(td->info));
 			uhci_remove_qh(td->qh->skel, td->qh);
 			uhci_qh_free(td->qh);
 			uhci_td_free(td);
@@ -1433,7 +1438,7 @@
 	/* Don't clobber the frame */
 	td->link = uhci->fl->frame[0];
 	td->status = TD_CTRL_IOC;
-	td->info = (15 << 21) | 0x7f69;				/* (ignored) input packet, 16 bytes, device 127 */
+	td->info = (15 << 21) | (0x7f << 8) | USB_PID_IN;	/* (ignored) input packet, 16 bytes, device 127 */
 	td->buffer = 0;
 	td->qh = NULL;
 
diff -u --recursive --new-file v2.3.13/linux/drivers/usb/uhci.h linux/drivers/usb/uhci.h
--- v2.3.13/linux/drivers/usb/uhci.h	Mon Aug  9 14:59:23 1999
+++ linux/drivers/usb/uhci.h	Tue Aug 17 16:47:26 1999
@@ -77,6 +77,9 @@
 	__u32 frame[1024];
 } __attribute__((aligned(4096)));
 
+/*
+ * for TD <status>:
+ */
 #define TD_CTRL_SPD		(1 << 29)	/* Short Packet Detect */
 #define TD_CTRL_LS		(1 << 26)	/* Low Speed Device */
 #define TD_CTRL_IOS		(1 << 25)	/* Isochronous Select */
@@ -88,10 +91,35 @@
 #define TD_CTRL_NAK		(1 << 19)	/* NAK Received */
 #define TD_CTRL_CRCTIME		(1 << 18)	/* CTC/Time Out Error */
 #define TD_CTRL_BITSTUFF	(1 << 17)	/* Bit Stuff Error */
+#define TD_CTRL_ACTLEN_MASK	0x7ff		/* actual length, encoded as n - 1 */
+
+#define TD_CTRL_ANY_ERROR	(TD_CTRL_STALLED | TD_CTRL_DBUFERR | \
+				 TD_CTRL_BABBLE | TD_CTRL_CRCTIME | TD_CTRL_BITSTUFF)
+
+#define uhci_status_bits(ctrl_sts)	((ctrl_sts >> 16) & 0xff)
+#define uhci_actual_length(ctrl_sts)	((ctrl_sts + 1) & TD_CTRL_ACTLEN_MASK) /* 1-based */
 
 #define uhci_ptr_to_virt(x)	bus_to_virt(x & ~UHCI_PTR_BITS)
 
+/*
+ * for TD <flags>:
+ */
 #define UHCI_TD_REMOVE		0x0001		/* Remove when done */
+
+/*
+ * for TD <info>: (a.k.a. Token)
+ */
+#define TD_TOKEN_TOGGLE		19
+
+#define uhci_maxlen(token)	((token) >> 21)
+#define uhci_toggle(token)	(((token) >> TD_TOKEN_TOGGLE) & 1)
+#define uhci_endpoint(token)	(((token) >> 15) & 0xf)
+#define uhci_devaddr(token)	(((token) >> 8) & 0x7f)
+#define uhci_devep(token)	(((token) >> 8) & 0x7ff)
+#define uhci_packetid(token)	((token) & 0xff)
+#define uhci_packetout(token)	(uhci_packetid(token) != USB_PID_IN)
+#define uhci_packetin(token)	(uhci_packetid(token) == USB_PID_IN)
+
 
 /*
  * The documentation says "4 words for hardware, 4 words for software".
diff -u --recursive --new-file v2.3.13/linux/drivers/usb/usb-debug.c linux/drivers/usb/usb-debug.c
--- v2.3.13/linux/drivers/usb/usb-debug.c	Wed Jul 21 15:46:48 1999
+++ linux/drivers/usb/usb-debug.c	Mon Aug 16 23:19:13 1999
@@ -13,28 +13,28 @@
 	usb_show_endpoint_descriptor(endpoint);
 }
 
-static void usb_show_interface(struct usb_interface_descriptor *interface)
+static void usb_show_interface(struct usb_interface_descriptor *altsetting)
 {
 	int i;
 
-	usb_show_interface_descriptor(interface);
-	for (i = 0 ; i < interface->bNumEndpoints; i++)
-		usb_show_endpoint(interface->endpoint + i);
+	usb_show_interface_descriptor(altsetting);
+	for (i = 0 ; i < altsetting->bNumEndpoints; i++)
+		usb_show_endpoint(altsetting->endpoint + i);
 }
 
 static void usb_show_config(struct usb_config_descriptor *config)
 {
   int i, j;
-  struct usb_alternate_setting *as;
+  struct usb_interface *intf;
 
   usb_show_config_descriptor(config);
-  for (i = 0; i < config->num_altsetting; i++) {
-    as = config->altsetting + i;
-    if ((as) == NULL)
+  for (i = 0; i < config->bNumInterfaces; i++) {
+    intf = config->interface + i;
+    if ((intf) == NULL)
       break;
-    printk("\n  Alternate Setting: %d\n", i);
-    for (j = 0 ; j < config->bNumInterfaces; j++)
-      usb_show_interface(as->interface + j);
+    printk("\n  Interface: %d\n", i);
+    for (j = 0 ; j < intf->num_altsetting; j++)
+      usb_show_interface(intf->altsetting + j);
   }
 }
 
@@ -99,7 +99,7 @@
 
 void usb_show_interface_descriptor(struct usb_interface_descriptor * desc)
 {
-	printk("  Interface:\n");
+	printk("  Alternate Setting: %2d\n", desc->bAlternateSetting);
 	printk("    bLength             = %4d%s\n", desc->bLength,
 		desc->bLength == USB_DT_INTERFACE_SIZE ? "" : " (!!!)");
 	printk("    bDescriptorType     =   %02x\n", desc->bDescriptorType);
@@ -113,10 +113,13 @@
 
 void usb_show_endpoint_descriptor(struct usb_endpoint_descriptor * desc)
 {
+	char *bLengthCommentString = (USB_DT_AUCLSTEP_SIZE == desc->bLength) ?
+		  " (!Audio)" : " (!!!)";
+
 	char *EndpointType[4] = { "Control", "Isochronous", "Bulk", "Interrupt" };
 	printk("    Endpoint:\n");
 	printk("      bLength             = %4d%s\n", desc->bLength,
-		desc->bLength == USB_DT_ENDPOINT_SIZE ? "" : " (!!!)");
+		desc->bLength == USB_DT_ENDPOINT_SIZE ? "" : bLengthCommentString);
 	printk("      bDescriptorType     =   %02x\n", desc->bDescriptorType);
 	printk("      bEndpointAddress    =   %02x (%s)\n", desc->bEndpointAddress,
 		(desc->bEndpointAddress & 0x80) ? "in" : "out");
@@ -124,6 +127,10 @@
 		EndpointType[3 & desc->bmAttributes]);
 	printk("      wMaxPacketSize      = %04x\n", desc->wMaxPacketSize);
 	printk("      bInterval           =   %02x\n", desc->bInterval);
+	if (USB_DT_AUCLSTEP_SIZE == desc->bLength) {
+		printk("      bRefresh            = %04x\n", desc->bRefresh);
+		printk("      bSynchAddress       =   %02x\n", desc->bSynchAddress);
+	}
 }
 
 void usb_show_hub_descriptor(struct usb_hub_descriptor * desc)
diff -u --recursive --new-file v2.3.13/linux/drivers/usb/usb.c linux/drivers/usb/usb.c
--- v2.3.13/linux/drivers/usb/usb.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/usb/usb.c	Wed Aug 18 16:22:23 1999
@@ -329,7 +329,7 @@
 	return parsed;// + ptr[parsed];
 }
 
-static int usb_parse_interface(struct usb_device *dev, struct usb_interface_descriptor *interface, unsigned char *ptr, int len)
+static int usb_parse_altsetting(struct usb_device *dev, struct usb_interface_descriptor *altsetting, unsigned char *ptr, int len)
 {
 	int i;
 	int parsed = usb_expect_descriptor(ptr, len, USB_DT_INTERFACE, USB_DT_INTERFACE_SIZE);
@@ -338,35 +338,35 @@
 	if (parsed < 0)
 		return parsed;
 
-	memcpy(interface, ptr + parsed, *ptr);
+	memcpy(altsetting, ptr + parsed, *ptr);
 	len -= ptr[parsed];
 	parsed += ptr[parsed];
 
 	while((i=usb_check_descriptor(ptr+parsed, len, 0x24)) >= 0) {
-		usb_audio_interface(interface, ptr+parsed+i);
+		usb_audio_interface(altsetting, ptr+parsed+i);
 		len -= ptr[parsed+i];
 		parsed += ptr[parsed+i];
 	}
 	
-	if (interface->bNumEndpoints > USB_MAXENDPOINTS) {
+	if (altsetting->bNumEndpoints > USB_MAXENDPOINTS) {
 		printk(KERN_WARNING "usb: too many endpoints.\n");
 		return -1;
 	}
 
-	interface->endpoint = (struct usb_endpoint_descriptor *)
-		kmalloc(interface->bNumEndpoints * sizeof(struct usb_endpoint_descriptor), GFP_KERNEL);
-	if (!interface->endpoint) {
+	altsetting->endpoint = (struct usb_endpoint_descriptor *)
+		kmalloc(altsetting->bNumEndpoints * sizeof(struct usb_endpoint_descriptor), GFP_KERNEL);
+	if (!altsetting->endpoint) {
 		printk(KERN_WARNING "usb: out of memory.\n");
 		return -1;	
 	}
-	memset(interface->endpoint, 0, interface->bNumEndpoints*sizeof(struct usb_endpoint_descriptor));
+	memset(altsetting->endpoint, 0, altsetting->bNumEndpoints*sizeof(struct usb_endpoint_descriptor));
 	
-	for (i = 0; i < interface->bNumEndpoints; i++) {
+	for (i = 0; i < altsetting->bNumEndpoints; i++) {
 //		if(((USB_DT_HID << 8) | 9) == *(unsigned short*)(ptr + parsed)) {
 //			parsed += 9;	/* skip over the HID descriptor for now */
 //			len -= 9;
 //		}
-		retval = usb_parse_endpoint(dev, interface->endpoint + i, ptr + parsed, len);
+		retval = usb_parse_endpoint(dev, altsetting->endpoint + i, ptr + parsed, len);
 		if (retval < 0)
 			return retval;
 		parsed += retval;
@@ -377,10 +377,13 @@
 
 static int usb_parse_config(struct usb_device *dev, struct usb_config_descriptor *config, unsigned char *ptr, int len)
 {
-	int i, j;
+	int i;
 	int retval;
-	struct usb_alternate_setting *as;
+	struct usb_interface *intf;
+	struct usb_interface_descriptor as;	/* This is needing for copying. */
 	int parsed = usb_expect_descriptor(ptr, len, USB_DT_CONFIG, 9);
+	unsigned short bNumInterfaces;
+	unsigned short bIntfaceNum = 0, bAltSetting = 0;
 
 	if (parsed < 0)
 		return parsed;
@@ -389,65 +392,65 @@
 	len -= *ptr;
 	parsed += *ptr;
 	le16_to_cpus(&config->wTotalLength);
+	bNumInterfaces = config->bNumInterfaces;
 
-	if (config->bNumInterfaces > USB_MAXINTERFACES) {
+	if (bNumInterfaces > USB_MAXINTERFACES) {
 		printk(KERN_WARNING "usb: too many interfaces.\n");
 		return -1;
-
 	}
 
-	config->altsetting = (struct usb_alternate_setting *)
-	        kmalloc(USB_MAXALTSETTING * sizeof(struct usb_alternate_setting), GFP_KERNEL);
-	if (!config->altsetting) {
+	config->interface = (struct usb_interface *)
+	        kmalloc(bNumInterfaces * sizeof(struct usb_interface), GFP_KERNEL);
+	if (!config->interface) {
 		printk(KERN_WARNING "usb: out of memory.\n");
 		return -1;
 	}
-	config->act_altsetting = 0;
-	config->num_altsetting = 1;
+	memset(config->interface, 
+		   0, (bNumInterfaces) * sizeof(struct usb_interface));
 
-	config->altsetting->interface = (struct usb_interface_descriptor *)
-		kmalloc(config->bNumInterfaces * sizeof(struct usb_interface_descriptor), GFP_KERNEL);
-	if (!config->altsetting->interface) {
-		printk(KERN_WARNING "usb: out of memory.\n");
-		return -1;	
+	for (i = 0; i < bNumInterfaces; i++) {
+		intf = (config->interface) +i;
+		/* We have at least one interface */
+		intf->num_altsetting = 1;
+		intf->altsetting = (struct usb_interface_descriptor*)
+			kmalloc((USB_MAXALTSETTING +1) * sizeof(struct usb_interface_descriptor), GFP_KERNEL);
+		if (!config->interface[i].altsetting) {
+			printk(KERN_WARNING "usb: out of memory.\n");
+			return -1;	
+		}
+		memset(intf->altsetting, 
+			   0, (USB_MAXALTSETTING+1) * sizeof(struct usb_interface_descriptor));
 	}
-	memset(config->altsetting->interface, 
-	       0, config->bNumInterfaces*sizeof(struct usb_interface_descriptor));
-	
-	for (i = 0; i < config->bNumInterfaces; i++) {
-		retval = usb_parse_interface(dev, config->altsetting->interface + i, ptr + parsed, len);
+		
+	/* Ok, we now have allocated the necessary structures, now decide
+     * where to put the parsed interface descriptors - sort by
+	 * bAltSetting and bInterfaceNumber.
+	 */
+	while (len > 0) {
+		retval = usb_parse_altsetting(dev, &as, ptr + parsed, len);
 		if (retval < 0)
 			return parsed; // HACK
-//			return retval;
+	//		return retval;
 		parsed += retval;
 		len -= retval;
-	}
-
-	printk("parsed = %d len = %d\n", parsed, len);
-
-	// now parse for additional alternate settings
-	for (j = 1; j < USB_MAXALTSETTING; j++) {
-		retval = usb_expect_descriptor(ptr + parsed, len, USB_DT_INTERFACE, 9);
-		if (retval) 
-			break;
-		config->num_altsetting++;
-		as = config->altsetting + j;
-		as->interface = (struct usb_interface_descriptor *)
-			kmalloc(config->bNumInterfaces * sizeof(struct usb_interface_descriptor), GFP_KERNEL);
-		if (!as->interface) {
-			printk(KERN_WARNING "usb: out of memory.\n");
+		bIntfaceNum = as.bInterfaceNumber;
+		if (bIntfaceNum > config->bNumInterfaces) {
+			printk(KERN_WARNING "usb: bInterfaceNumber %2u exceeding config->bNumINterfaces.\n", bIntfaceNum);
+			return -1;
+		}
+		bAltSetting = as.bAlternateSetting;
+		if (bAltSetting > USB_MAXALTSETTING) {
+			printk(KERN_WARNING "usb: illegal bAlternateSetting %2u.\n", bAltSetting);
 			return -1;
 		}
-		memset(as->interface, 0, config->bNumInterfaces * sizeof(struct usb_interface_descriptor));
-		for (i = 0; i < config->bNumInterfaces; i++) {
-			retval = usb_parse_interface(dev, as->interface + i, 
-					 ptr + parsed, len);
-			if (retval < 0)
-				return parsed;
-			parsed += retval;
-			len -= retval;
+		if (bAltSetting > config->interface[bIntfaceNum].num_altsetting) {
+			config->interface[bIntfaceNum].num_altsetting = bAltSetting +1;
 		}
+		memcpy( &(config->interface[bIntfaceNum].altsetting[bAltSetting]),
+		   		&as, sizeof(struct usb_interface_descriptor));
 	}
+
+	printk("parsed = %d len = %d\n", parsed, len);
 	return parsed;
 }
 
@@ -484,44 +487,36 @@
 {
 	int c, a, i;
 	struct usb_config_descriptor *cf;
-	struct usb_alternate_setting *as;
-	struct usb_interface_descriptor *ifp;
+	struct usb_interface *intf;
+	struct usb_interface_descriptor *as;
 	
 	if (!dev->config)
 		return;
 
 	for (c = 0; c < dev->descriptor.bNumConfigurations; c++) {
 		cf = &dev->config[c];
-		if (!cf->altsetting)
+		if (!cf->interface)
 		        break;
-		for (a = 0; a < cf->num_altsetting; a++) {
-		        as = &cf->altsetting[a];
-			if (as->interface == NULL)
+		for (a = 0; a < cf->bNumInterfaces; a++) {
+		        intf = &cf->interface[a];
+			if (intf->altsetting == NULL)
 			        break;
-			for(i=0;i<cf->bNumInterfaces;i++) {
-			        ifp = &as->interface[i];
-				if(ifp->endpoint==NULL)
+			for(i=0; i <= USB_MAXALTSETTING ;i++) {
+			        as = &intf->altsetting[i];
+				if(as->endpoint==NULL)
 				       break;
-				kfree(ifp->endpoint);
+				kfree(as->endpoint);
 			}
-			kfree(as->interface);
+			kfree(intf->altsetting);
 		}
-		kfree(cf->altsetting);
+		kfree(cf->interface);
 	}
 	kfree(dev->config);
 
-	for (i = 1; i < USB_MAXSTRINGS; ++i) {
-		if (dev->stringindex[i]) {
-			kfree(dev->stringindex[i]);
-			dev->stringindex[i] = 0;
-		}
-	}
-#if 0
-	if (dev->stringindex)
-		kfree(dev->stringindex);
-	if (dev->stringtable)
-		kfree(dev->stringtable);
-#endif
+	if (dev->string) {
+		kfree(dev->string);
+		dev->string = 0;
+ 	}
 }
 			
 void usb_init_root_hub(struct usb_device *dev)
@@ -708,29 +703,39 @@
 
 static void usb_set_maxpacket(struct usb_device *dev)
 {
-	int i;
-	int act_as = dev->actconfig->act_altsetting;
-	struct usb_alternate_setting *as = dev->actconfig->altsetting + act_as;
+	int i, j;
+	struct usb_interface *intf;
 
 	for (i=0; i<dev->actconfig->bNumInterfaces; i++) {
-		struct usb_interface_descriptor *ip = &as->interface[i];
-		struct usb_endpoint_descriptor *ep = ip->endpoint;
-		int e;
-
-		for (e=0; e<ip->bNumEndpoints; e++) {
-			dev->epmaxpacket[ep[e].bEndpointAddress & 0x0f] =
-				ep[e].wMaxPacketSize;
+		intf = (dev->actconfig->interface) +i;
+		for (j = 0; j < intf->num_altsetting; j++) {
+			struct usb_interface_descriptor *as = intf->altsetting +j;
+			struct usb_endpoint_descriptor *ep = as->endpoint;
+			int e;
+
+			for (e=0; e<as->bNumEndpoints; e++) {
+				if (usb_endpoint_out(ep[e].bEndpointAddress))
+					dev->epmaxpacketout[ep[e].bEndpointAddress & 0x0f] =
+						ep[e].wMaxPacketSize;
+				else
+					dev->epmaxpacketin[ep[e].bEndpointAddress & 0x0f] =
+						ep[e].wMaxPacketSize;
+			}
 		}
 	}
 }
 
+/*
+ * endp: endpoint number in bits 0-3;
+ *	direction flag in bit 7 (1 = IN, 0 = OUT)
+ */
 int usb_clear_halt(struct usb_device *dev, int endp)
 {
 	devrequest dr;
 	int result;
 	__u16 status;
 
-    	//if (!usb_endpoint_halted(dev, endp))
+    	//if (!usb_endpoint_halted(dev, endp & 0x0f, usb_endpoint_out(endp)))
 	//	return 0;
 
 	dr.requesttype = USB_RT_ENDPOINT;
@@ -741,11 +746,11 @@
 
 	result = dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev,0), &dr, NULL, 0);
 
-	/* dont clear if failed */
+	/* don't clear if failed */
 	if (result)
 	    return result;
 
-#if 1	/* lets be really tough */
+#if 1	/* let's be really tough */
 	dr.requesttype = 0x80 | USB_RT_ENDPOINT;
 	dr.request = USB_REQ_GET_STATUS;
 	dr.length = 2;
@@ -758,11 +763,11 @@
 	if (status & 1)
 	    return 1;		/* still halted */
 #endif
-	usb_endpoint_running(dev, endp & 0x0f);
+	usb_endpoint_running(dev, endp & 0x0f, usb_endpoint_out(endp));
 
 	/* toggle is reset on clear */
 
-	usb_settoggle(dev, endp & 0x0f, ((endp >> 7) & 1) ^ 1, 0);
+	usb_settoggle(dev, endp & 0x0f, usb_endpoint_out(endp), 0);
 
 	return 0;
 }
@@ -781,7 +786,7 @@
 		return -1;
 
 	dev->ifnum = interface;
-	dev->actconfig->act_altsetting = alternate;
+	dev->actconfig->interface[interface].act_altsetting = alternate;
 	usb_set_maxpacket(dev);
 	return 0;
 }
@@ -874,62 +879,6 @@
 	return parse;
 }
 
-#if 0
-int usb_get_stringtable(struct usb_device *dev)
-{
-	int i;
-	int maxindex;
-	int langid;
-	unsigned char buffer[256];
-	int totalchars;
-	struct usb_string_descriptor *sd = (struct usb_string_descriptor *)buffer;
-	char *string;
-	__u8 bLengths[USB_MAXSTRINGS+1];
-	int j;
-
-	dev->maxstring = 0;
-	if(usb_get_string(dev, 0, 0, buffer, 2) ||
-	   usb_get_string(dev, 0, 0, buffer, sd->bLength))
-		return -1;
-	/* we are going to assume that the first ID is good */
-	langid = le16_to_cpup(&sd->wData[0]);
-
-	/* whip through and find total length and max index */
-	for (maxindex = 1, totalchars = 0; maxindex<=USB_MAXSTRINGS; maxindex++) {
-		if(usb_get_string(dev, langid, maxindex, buffer, 2))
-			break;
-		totalchars += (sd->bLength - 2)/2 + 1;
-		bLengths[maxindex] = sd->bLength;
-	}
-	if (--maxindex <= 0)
-		return -1;
-
-	/* get space for strings and index */
-	dev->stringindex = kmalloc(sizeof(char *) * (maxindex+1), GFP_KERNEL);
-	if (!dev->stringindex)
-		return -1;
-	dev->stringtable = kmalloc(totalchars, GFP_KERNEL);
-	if (!dev->stringtable) {
-		kfree(dev->stringindex);
-		dev->stringindex = NULL;
-		return -1;
-	}
-
-	/* fill them in */
-	memset(dev->stringindex, 0, sizeof(char *) * (maxindex+1));
-	for (i=1, string = dev->stringtable; i <= maxindex; i++) {
-		if (usb_get_string(dev, langid, i, buffer, bLengths[i]))
-			continue;
-		dev->stringindex[i] = string;
-		for (j=0; j < (bLengths[i] - 2)/2; j++) {
-			*string++ = le16_to_cpup(&sd->wData[j]);
-		}
-		*string++ = '\0';
-	}
-	dev->maxstring = maxindex;
-	return 0;
-}
-#endif
 
 char *usb_string(struct usb_device *dev, int index)
 {
@@ -940,10 +889,10 @@
 		struct usb_string_descriptor desc;
 	} u;
 
-	if (index <= 0 || index >= USB_MAXSTRINGS)
+	if (index <= 0)
 		return 0;
-	if (dev->stringindex[index] != 0)
-		return dev->stringindex[index];
+	if (dev->string)
+		kfree (dev->string);
 
 	if (dev->string_langid == 0) {
 		/* read string descriptor 0 */
@@ -968,7 +917,7 @@
 		ptr[i] = le16_to_cpup(&u.desc.wData[i]);
 	ptr[i] = 0;
 
-	dev->stringindex[index] = ptr;
+	dev->string = ptr;
 	return ptr;
 }
 
@@ -985,7 +934,8 @@
 		dev->devnum);
 
 	dev->maxpacketsize = 0;		/* Default to 8 byte max packet size */
-        dev->epmaxpacket[0] = 8;
+	dev->epmaxpacketin [0] = 8;
+	dev->epmaxpacketout[0] = 8;
 
 	/* We still haven't set the Address yet */
 	addr = dev->devnum;
@@ -998,7 +948,8 @@
 		return 1;
 	}
 
-	dev->epmaxpacket[0] = dev->descriptor.bMaxPacketSize0;
+	dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0;
+	dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0;
 	switch (dev->descriptor.bMaxPacketSize0) {
 		case 8: dev->maxpacketsize = 0; break;
 		case 16: dev->maxpacketsize = 1; break;
@@ -1090,7 +1041,7 @@
 
 int usb_release_irq(struct usb_device *dev, void* handle)
 {
-	return dev->bus->op->release_irq(handle);
+	return dev->bus->op->release_irq(dev, handle);
 }
 
 #ifdef CONFIG_PROC_FS
diff -u --recursive --new-file v2.3.13/linux/drivers/usb/usb.h linux/drivers/usb/usb.h
--- v2.3.13/linux/drivers/usb/usb.h	Mon Aug  9 14:59:23 1999
+++ linux/drivers/usb/usb.h	Wed Aug 18 16:22:23 1999
@@ -61,6 +61,7 @@
 #define USB_DT_CONFIG_SIZE		9
 #define USB_DT_INTERFACE_SIZE		9
 #define USB_DT_ENDPOINT_SIZE		7
+#define USB_DT_AUCLSTEP_SIZE		9	/* Audio Classes are special */
 #define USB_DT_HUB_NONVAR_SIZE		7
 
 /*
@@ -167,10 +168,9 @@
  */
 
 #define USB_MAXCONFIG		8
-#define USB_MAXALTSETTING       5
+#define USB_MAXALTSETTING   6   
 #define USB_MAXINTERFACES	32
 #define USB_MAXENDPOINTS	32
-#define USB_MAXSTRINGS		32
 
 struct usb_device_descriptor {
 	__u8  bLength;
@@ -197,6 +197,8 @@
 	__u8  bmAttributes;
 	__u16 wMaxPacketSize;
 	__u8  bInterval;
+	__u8  bRefresh;
+	__u8  bSynchAddress;
 	void  *audio;
 };
 
@@ -216,9 +218,10 @@
 	void  *audio;
 };
 
-/* hack for alternate settings */
-struct usb_alternate_setting {
-        struct usb_interface_descriptor *interface;
+struct usb_interface {
+        struct usb_interface_descriptor *altsetting;
+        int act_altsetting;                /* active alternate setting */
+        int num_altsetting;                /* number of alternate settings */
 };
 
 /* Configuration descriptor information.. */
@@ -231,9 +234,7 @@
 	__u8  iConfiguration;
 	__u8  bmAttributes;
 	__u8  MaxPower;
-        int act_altsetting;                /* active alternate setting */
-        int num_altsetting;                /* number of alternate settings */
-	struct usb_alternate_setting *altsetting;
+	struct usb_interface *interface;
 };
 
 /* String descriptor */
@@ -289,7 +290,7 @@
 	int (*control_msg)(struct usb_device *, unsigned int, devrequest *, void *, int);
 	int (*bulk_msg)(struct usb_device *, unsigned int, void *, int,unsigned long *);
 	void* (*request_irq)(struct usb_device *, unsigned int, usb_device_irq, int, void *);
-	int (*release_irq)(void* handle);
+	int (*release_irq)(struct usb_device *, void* handle);
 	void *(*request_bulk)(struct usb_device *, unsigned int, usb_device_irq,
  void *, int, void *);
 	int (*terminate_bulk)(struct usb_device *, void *);
@@ -319,16 +320,18 @@
 	int slow;			/* Slow device? */
 	int maxpacketsize;		/* Maximum packet size; encoded as 0,1,2,3 = 8,16,32,64 */
 	unsigned int toggle[2];		/* one bit for each endpoint ([0] = IN, [1] = OUT) */
-	unsigned int halted;		/* endpoint halts */
+	unsigned int halted[2];		/* endpoint halts; one bit per endpoint # & direction; */
+					/* [0] = IN, [1] = OUT */
 	struct usb_config_descriptor *actconfig;/* the active configuration */
-	int epmaxpacket[16];		/* endpoint specific maximums */
+	int epmaxpacketin[16];		/* INput endpoint specific maximums */
+	int epmaxpacketout[16];		/* OUTput endpoint specific maximums */
 	int ifnum;			/* active interface number */
-	struct usb_bus *bus;		/* Bus we're apart of */
+	struct usb_bus *bus;		/* Bus we're part of */
 	struct usb_driver *driver;	/* Driver */
 	struct usb_device_descriptor descriptor;/* Descriptor */
 	struct usb_config_descriptor *config;	/* All of the configs */
 	struct usb_device *parent;
-	char *stringindex[USB_MAXSTRINGS];	/* pointers to strings */
+	char *string;			/* pointer to the last string read from the device */
 	int string_langid;		/* language ID for strings */
   
 	/*
@@ -397,7 +400,7 @@
  * unsigned int. The encoding is:
  *
  *  - max size:		bits 0-1	(00 = 8, 01 = 16, 10 = 32, 11 = 64)
- *  - direction:	bit 7		(0 = Host-to-Device, 1 = Device-to-Host)
+ *  - direction:	bit 7		(0 = Host-to-Device [Out], 1 = Device-to-Host [In])
  *  - device:		bits 8-14
  *  - endpoint:		bits 15-18
  *  - Data0/1:		bit 19
@@ -410,8 +413,10 @@
  * appropriately.
  */
 
-#define usb_maxpacket(dev,pipe)	((dev)->epmaxpacket[usb_pipeendpoint(pipe)])
-#define usb_packetid(pipe)	(((pipe) & 0x80) ? 0x69 : 0xE1)
+#define usb_maxpacket(dev, pipe, out)	(out \
+				? (dev)->epmaxpacketout[usb_pipeendpoint(pipe)] \
+				: (dev)->epmaxpacketin [usb_pipeendpoint(pipe)] )
+#define usb_packetid(pipe)	(((pipe) & USB_DIR_IN) ? USB_PID_IN : USB_PID_OUT)
 
 #define usb_pipeout(pipe)	((((pipe) >> 7) & 1) ^ 1)
 #define usb_pipein(pipe)	(((pipe) >> 7) & 1)
@@ -433,10 +438,11 @@
 #define	usb_dotoggle(dev, ep, out)  ((dev)->toggle[out] ^= (1 << ep))
 #define usb_settoggle(dev, ep, out, bit) ((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << ep)) | ((bit) << ep))
 
-/* Endpoint halt */
-#define usb_endpoint_halt(dev, ep) ((dev)->halted |= (1 << (ep)))
-#define usb_endpoint_running(dev, ep) ((dev)->halted &= ~(1 << (ep)))
-#define usb_endpoint_halted(dev, ep) ((dev)->halted & (1 << (ep)))
+/* Endpoint halt control/status */
+#define usb_endpoint_out(ep_dir)	(((ep_dir >> 7) & 1) ^ 1)
+#define usb_endpoint_halt(dev, ep, out) ((dev)->halted[out] |= (1 << (ep)))
+#define usb_endpoint_running(dev, ep, out) ((dev)->halted[out] &= ~(1 << (ep)))
+#define usb_endpoint_halted(dev, ep, out) ((dev)->halted[out] & (1 << (ep)))
 
 static inline unsigned int __create_pipe(struct usb_device *dev, unsigned int endpoint)
 {
@@ -450,13 +456,13 @@
 
 /* Create various pipes... */
 #define usb_sndctrlpipe(dev,endpoint)	((2 << 30) | __create_pipe(dev,endpoint))
-#define usb_rcvctrlpipe(dev,endpoint)	((2 << 30) | __create_pipe(dev,endpoint) | 0x80)
+#define usb_rcvctrlpipe(dev,endpoint)	((2 << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
 #define usb_sndisocpipe(dev,endpoint)	((0 << 30) | __create_pipe(dev,endpoint))
-#define usb_rcvisocpipe(dev,endpoint)	((0 << 30) | __create_pipe(dev,endpoint) | 0x80)
+#define usb_rcvisocpipe(dev,endpoint)	((0 << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
 #define usb_sndbulkpipe(dev,endpoint)	((3 << 30) | __create_pipe(dev,endpoint))
-#define usb_rcvbulkpipe(dev,endpoint)	((3 << 30) | __create_pipe(dev,endpoint) | 0x80)
+#define usb_rcvbulkpipe(dev,endpoint)	((3 << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
 #define usb_snddefctrl(dev)		((2 << 30) | __default_pipe(dev))
-#define usb_rcvdefctrl(dev)		((2 << 30) | __default_pipe(dev) | 0x80)
+#define usb_rcvdefctrl(dev)		((2 << 30) | __default_pipe(dev) | USB_DIR_IN)
 
 /*
  * Send and receive control messages..
diff -u --recursive --new-file v2.3.13/linux/drivers/usb/usb_scsi.c linux/drivers/usb/usb_scsi.c
--- v2.3.13/linux/drivers/usb/usb_scsi.c	Wed Jul 28 14:47:42 1999
+++ linux/drivers/usb/usb_scsi.c	Mon Aug  9 20:38:13 1999
@@ -130,7 +130,7 @@
 
 static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
 {
-    int max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
+    int max_size = usb_maxpacket(us->pusb_dev, pipe, usb_pipeout(pipe)) * 16;
     int this_xfer;
     int result;
     unsigned long partial;
diff -u --recursive --new-file v2.3.13/linux/drivers/usb/uss720.c linux/drivers/usb/uss720.c
--- v2.3.13/linux/drivers/usb/uss720.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/usb/uss720.c	Thu Aug 12 11:50:15 1999
@@ -29,12 +29,12 @@
  *                  usb_request_irq crashes somewhere within ohci.c
  *                  for no apparent reason (that is for me, anyway)
  *                  ECP currently untested
+ *   0.3  10.08.99  fixing merge errors
  *
  */
 
 /*****************************************************************************/
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/socket.h>
 #include <linux/parport.h>
@@ -187,10 +187,6 @@
  * Access functions.
  */
 
-static void parport_uss720_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-}
-
 static int uss720_irq(int usbstatus, void *buffer, int len, void *dev_id)
 {
 	struct parport *pp = (struct parport *)dev_id;
@@ -653,16 +649,13 @@
 
 /* --------------------------------------------------------------------- */
 
-#define __exit
-#define module_exit(x) void cleanup_module(void) { x(); }
-#define module_init(x) int init_module(void) { return x(); }
-
-/* --------------------------------------------------------------------- */
+MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch");
+MODULE_DESCRIPTION("USB Parport Cable driver for Cables using the Lucent Technologies USS720 Chip");
 
 static int __init uss720_init(void)
 {
 	usb_register(&uss720_driver);
-        printk(KERN_INFO "uss720: USB<->IEEE1284 cable driver v0.2 registered.\n"
+        printk(KERN_INFO "uss720: USB<->IEEE1284 cable driver v0.3 registered.\n"
 	       KERN_INFO "uss720: (C) 1999 by Thomas Sailer, <sailer@ife.ee.ethz.ch>\n");
 	return 0;
 }
diff -u --recursive --new-file v2.3.13/linux/drivers/video/Config.in linux/drivers/video/Config.in
--- v2.3.13/linux/drivers/video/Config.in	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/Config.in	Wed Aug 18 10:10:06 1999
@@ -6,6 +6,7 @@
   define_bool CONFIG_DUMMY_CONSOLE y
   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
     if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_PCI" = "y" ]; then
+      tristate 'Cirrus Logic suport (experimental)' CONFIG_FB_CLGEN
       bool 'Permedia2 support (experimental)' CONFIG_FB_PM2
       if [ "$CONFIG_FB_PM2" = "y" ]; then
         if [ "$CONFIG_PCI" = "y" ]; then
@@ -43,7 +44,6 @@
     if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
       bool 'Amiga CyberVision3D support (experimental)' CONFIG_FB_VIRGE
       tristate 'Amiga RetinaZ3 support' CONFIG_FB_RETINAZ3
-      tristate 'Amiga CLgen driver' CONFIG_FB_CLGEN
       bool 'Amiga FrameMaster II/Rainbow II support (experimental)' CONFIG_FB_FM2
     fi
   fi
diff -u --recursive --new-file v2.3.13/linux/drivers/video/Makefile linux/drivers/video/Makefile
--- v2.3.13/linux/drivers/video/Makefile	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/Makefile	Wed Aug 18 10:10:06 1999
@@ -37,7 +37,7 @@
 
 ifeq ($(CONFIG_FB),y)
   L_OBJS += fonts.o
-  OX_OBJS += fbcon.o fbcmap.o fbmem.o
+  OX_OBJS += fbcon.o fbcmap.o fbmem.o modedb.o
   ifeq ($(CONFIG_FONT_8x8),y)
     L_OBJS += font_8x8.o
   endif
diff -u --recursive --new-file v2.3.13/linux/drivers/video/S3triofb.c linux/drivers/video/S3triofb.c
--- v2.3.13/linux/drivers/video/S3triofb.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/S3triofb.c	Thu Aug 12 10:22:33 1999
@@ -99,7 +99,7 @@
      *  Interface to the low level console driver
      */
 
-void s3triofb_init(void);
+int s3triofb_init(void);
 static int s3triofbcon_switch(int con, struct fb_info *info);
 static int s3triofbcon_updatevar(int con, struct fb_info *info);
 static void s3triofbcon_blank(int blank, struct fb_info *info);
@@ -288,7 +288,7 @@
     return -EINVAL;
 }
 
-void __init s3triofb_init(void)
+int __init s3triofb_init(void)
 {
 #ifdef __powerpc__
     /* We don't want to be called like this. */
@@ -296,6 +296,7 @@
 #else /* !__powerpc__ */
     /* To be merged with cybervision */
 #endif /* !__powerpc__ */
+	return 0;
 }
 
 void __init s3trio_resetaccel(void){
@@ -721,9 +722,9 @@
 		    s3trio_setcolreg, &fb_info);
 }
 
-void s3triofb_setup(char *options, int *ints) {
+int s3triofb_setup(char *options) {
 
-        return;
+        return 0;
 
 }
 
diff -u --recursive --new-file v2.3.13/linux/drivers/video/acornfb.c linux/drivers/video/acornfb.c
--- v2.3.13/linux/drivers/video/acornfb.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/acornfb.c	Thu Aug 12 10:22:33 1999
@@ -1728,14 +1728,14 @@
 	{ NULL, NULL }
 };
 
-void __init 
-acornfb_setup(char *options, int *ints)
+int __init 
+acornfb_setup(char *options)
 {
 	struct options *optp;
 	char *opt;
 
 	if (!options || !*options)
-		return;
+		return 0;
 
 	acornfb_init_fbinfo();
 
@@ -1759,6 +1759,7 @@
 			printk(KERN_ERR "acornfb: unknown parameter: %s\n",
 			       opt);
 	}
+	return 0;
 }
 
 /*
@@ -1802,7 +1803,7 @@
 	printk("acornfb: freed %dK memory\n", mb_freed);
 }
 
-void __init 
+int __init 
 acornfb_init(void)
 {
 	unsigned long size;
@@ -1904,5 +1905,7 @@
 		VIDC_NAME, init_var.xres, init_var.yres,
 		h_sync / 1000, h_sync % 1000, v_sync);
 
-	register_framebuffer(&fb_info);
+	if (register_framebuffer(&fb_info) < 0)
+		return -EINVAL;
+	return 0;
 }
diff -u --recursive --new-file v2.3.13/linux/drivers/video/amifb.c linux/drivers/video/amifb.c
--- v2.3.13/linux/drivers/video/amifb.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/amifb.c	Wed Aug 18 10:10:29 1999
@@ -805,138 +805,86 @@
 	 *
 	 */
 
-static struct fb_videomode amifb_predefined[] __initdata = {
+static struct fb_videomode ami_modedb[] __initdata = {
 
     /*
      *  AmigaOS Video Modes
+     *
+     *  If you change these, make sure to update DEFMODE_* as well!
      */
 
     {
-	"ntsc", {		/* 640x200, 15 kHz, 60 Hz (NTSC) */
-	    640, 200, 640, 200, 0, 0, 4, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, 0, TAG_HIRES, 106, 86, 44, 16, 76, 2,
-	    FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	}
+	/* 640x200, 15 kHz, 60 Hz (NTSC) */
+	"ntsc", 60, 640, 200, TAG_HIRES, 106, 86, 44, 16, 76, 2,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
     }, {
-	"ntsc-lace", {		/* 640x400, 15 kHz, 60 Hz interlaced (NTSC) */
-	    640, 400, 640, 400, 0, 0, 4, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, 0, TAG_HIRES, 106, 86, 88, 33, 76, 4,
-	    FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
-	}
+	/* 640x400, 15 kHz, 60 Hz interlaced (NTSC) */
+	"ntsc-lace", 60, 640, TAG_HIRES, 106, 86, 88, 33, 76, 4,
+	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
     }, {
-	"pal", {		/* 640x256, 15 kHz, 50 Hz (PAL) */
-	    640, 256, 640, 256, 0, 0, 4, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, 0, TAG_HIRES, 106, 86, 40, 14, 76, 2,
-	    FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	}
+	/* 640x256, 15 kHz, 50 Hz (PAL) */
+	"pal", 50, 640, 256, TAG_HIRES, 106, 86, 40, 14, 76, 2,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
     }, {
-	"pal-lace", {		/* 640x512, 15 kHz, 50 Hz interlaced (PAL) */
-	    640, 512, 640, 512, 0, 0, 4, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, 0, TAG_HIRES, 106, 86, 80, 29, 76, 4,
-	    FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
-	}
+	/* 640x512, 15 kHz, 50 Hz interlaced (PAL) */
+	"pal-lace", 50, 640, 512, TAG_HIRES, 106, 86, 80, 29, 76, 4,
+	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
     }, {
-	"multiscan", {		/* 640x480, 29 kHz, 57 Hz */
-	    640, 480, 640, 480, 0, 0, 4, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, 0, TAG_SHRES, 96, 112, 29, 8, 72, 8,
-	    0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	}
+	/* 640x480, 29 kHz, 57 Hz */
+	"multiscan", 57, 640, 480, TAG_SHRES, 96, 112, 29, 8, 72, 8,
+	0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
     }, {
-	"multiscan-lace", {	/* 640x960, 29 kHz, 57 Hz interlaced */
-	    640, 960, 640, 960, 0, 0, 4, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, 0, TAG_SHRES, 96, 112, 58, 16, 72, 16,
-	    0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
-	}
+	/* 640x960, 29 kHz, 57 Hz interlaced */
+	"multiscan-lace", 57, 640, 960, TAG_SHRES, 96, 112, 58, 16, 72, 16,
+	0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
     }, {
-	"euro36", {		/* 640x200, 15 kHz, 72 Hz */
-	    640, 200, 640, 200, 0, 0, 4, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, 0, TAG_HIRES, 92, 124, 6, 6, 52, 5,
-	    0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	}
+	/* 640x200, 15 kHz, 72 Hz */
+	"euro36", 72, 640, 200, TAG_HIRES, 92, 124, 6, 6, 52, 5,
+	0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
     }, {
-	"euro36-lace", {	/* 640x400, 15 kHz, 72 Hz interlaced */
-	    640, 400, 640, 400, 0, 0, 4, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, 0, TAG_HIRES, 92, 124, 12, 12, 52, 10,
-	    0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
-	}
+	/* 640x400, 15 kHz, 72 Hz interlaced */
+	"euro36-lace", 72, 640, 400, TAG_HIRES, 92, 124, 12, 12, 52, 10,
+	0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
     }, {
-	"euro72", {		/* 640x400, 29 kHz, 68 Hz */
-	    640, 400, 640, 400, 0, 0, 4, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, 0, TAG_SHRES, 164, 92, 9, 9, 80, 8,
-	    0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	}
+	/* 640x400, 29 kHz, 68 Hz */
+	"euro72", 68, 640, 400, TAG_SHRES, 164, 92, 9, 9, 80, 8,
+	0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
     }, {
-	"euro72-lace", {	/* 640x800, 29 kHz, 68 Hz interlaced */
-	    640, 800, 640, 800, 0, 0, 4, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, 0, TAG_SHRES, 164, 92, 18, 18, 80, 16,
-	    0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
-	}
+	/* 640x800, 29 kHz, 68 Hz interlaced */
+	"euro72-lace", 68, 640, 800, TAG_SHRES, 164, 92, 18, 18, 80, 16,
+	0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
     }, {
-	"super72", {		/* 800x300, 23 kHz, 70 Hz */
-	    800, 300, 800, 300, 0, 0, 4, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, 0, TAG_SHRES, 212, 140, 10, 11, 80, 7,
-	    0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	}
+	/* 800x300, 23 kHz, 70 Hz */
+	"super72", 70, 800, 300, TAG_SHRES, 212, 140, 10, 11, 80, 7,
+	0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
     }, {
-	"super72-lace", {	/* 800x600, 23 kHz, 70 Hz interlaced */
-	    800, 600, 800, 600, 0, 0, 4, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, 0, TAG_SHRES, 212, 140, 20, 22, 80, 14,
-	    0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
-	}
+	/* 800x600, 23 kHz, 70 Hz interlaced */
+	"super72-lace", 70, 800, 600, TAG_SHRES, 212, 140, 20, 22, 80, 14,
+	0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
     }, {
-	"dblntsc", {		/* 640x200, 27 kHz, 57 Hz doublescan */
-	    640, 200, 640, 200, 0, 0, 4, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, 0, TAG_SHRES, 196, 124, 18, 17, 80, 4,
-	    0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
-	}
+	/* 640x200, 27 kHz, 57 Hz doublescan */
+	"dblntsc", 57, 640, 200, TAG_SHRES, 196, 124, 18, 17, 80, 4,
+	0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
     }, {
-	"dblntsc-ff", {		/* 640x400, 27 kHz, 57 Hz */
-	    640, 400, 640, 400, 0, 0, 4, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, 0, TAG_SHRES, 196, 124, 36, 35, 80, 7,
-	    0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	}
+	/* 640x400, 27 kHz, 57 Hz */
+	"dblntsc-ff", 57, 640, 400, TAG_SHRES, 196, 124, 36, 35, 80, 7,
+	0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
     }, {
-	"dblntsc-lace", {	/* 640x800, 27 kHz, 57 Hz interlaced */
-	    640, 800, 640, 800, 0, 0, 4, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, 0, TAG_SHRES, 196, 124, 72, 70, 80, 14,
-	    0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
-	}
+	/* 640x800, 27 kHz, 57 Hz interlaced */
+	"dblntsc-lace", 57, 640, 800, TAG_SHRES, 196, 124, 72, 70, 80, 14,
+	0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
     }, {
-	"dblpal", {		/* 640x256, 27 kHz, 47 Hz doublescan */
-	    640, 256, 640, 256, 0, 0, 4, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, 0, TAG_SHRES, 196, 124, 14, 13, 80, 4,
-	    0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
-	}
+	/* 640x256, 27 kHz, 47 Hz doublescan */
+	"dblpal", 47, 640, 256, TAG_SHRES, 196, 124, 14, 13, 80, 4,
+	0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
     }, {
-	"dblpal-ff", {		/* 640x512, 27 kHz, 47 Hz */
-	    640, 512, 640, 512, 0, 0, 4, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, 0, TAG_SHRES, 196, 124, 28, 27, 80, 7,
-	    0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	}
+	/* 640x512, 27 kHz, 47 Hz */
+	"dblpal-ff", 47, 640, 512, TAG_SHRES, 196, 124, 28, 27, 80, 7,
+	0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
     }, {
-	"dblpal-lace", {	/* 640x1024, 27 kHz, 47 Hz interlaced */
-	    640, 1024, 640, 1024, 0, 0, 4, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, 0, TAG_SHRES, 196, 124, 56, 54, 80, 14,
-	    0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
-	}
+	/* 640x1024, 27 kHz, 47 Hz interlaced */
+	"dblpal-lace", 47, 640, 1024, TAG_SHRES, 196, 124, 56, 54, 80, 14,
+	0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
     },
 
     /*
@@ -944,19 +892,13 @@
      */
 
     {
-	"vga", {		/* 640x480, 31 kHz, 60 Hz (VGA) */
-	    640, 480, 640, 480, 0, 0, 4, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, 0, TAG_SHRES, 64, 96, 30, 9, 112, 2,
-	    0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	}
+	/* 640x480, 31 kHz, 60 Hz (VGA) */
+	"vga", 60, 640, 480, TAG_SHRES, 64, 96, 30, 9, 112, 2,
+	0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
     }, {
-	"vga70", {		/* 640x400, 31 kHz, 70 Hz (VGA) */
-	    640, 400, 640, 400, 0, 0, 4, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, 0, TAG_SHRES, 64, 96, 35, 12, 112, 2,
-	    FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	}
+	/* 640x400, 31 kHz, 70 Hz (VGA) */
+	"vga70", 70, 640, 400, TAG_SHRES, 64, 96, 35, 12, 112, 2,
+	FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
     },
 
 #if 0
@@ -967,41 +909,36 @@
      */
 
     {
-	"a2024-10", {		/* 1024x800, 10 Hz */
-	    1024, 800, 1024, 800, 0, 0, 2, 0,
-	    {0, 2, 0}, {0, 2, 0}, {0, 2, 0}, {0, 0, 0},
-	    0, 0, -1, -1, 0, TAG_HIRES, 0, 0, 0, 0, 0, 0,
-	    0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	}
+	/* 1024x800, 10 Hz */
+	"a2024-10", 10, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
+	0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
     }, {
-	"a2024-15", {		/* 1024x800, 15 Hz */
-	    1024, 800, 1024, 800, 0, 0, 2, 0,
-	    {0, 2, 0}, {0, 2, 0}, {0, 2, 0}, {0, 0, 0},
-	    0, 0, -1, -1, 0, TAG_HIRES, 0, 0, 0, 0, 0, 0,
-	    0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	}
+	/* 1024x800, 15 Hz */
+	"a2024-15", 10, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
+	0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
     }
 #endif
 };
 
-#define NUM_TOTAL_MODES  arraysize(amifb_predefined)
+#define NUM_TOTAL_MODES  arraysize(ami_modedb)
 
-static int amifb_ilbm = 0;	/* interleaved or normal bitplanes */
-static int amifb_inverse = 0;
-static int amifb_usermode __initdata = 0;
-static int amifb_userdepth __initdata = -1;
+static const char *mode_option __initdata = NULL;
+static int round_down_bpp = 1;	/* for mode probing */
 
 	/*
 	 * Some default modes
 	 */
 
-#define DEFMODE_PAL        "pal"	/* for PAL OCS/ECS */
-#define DEFMODE_NTSC       "ntsc"	/* for NTSC OCS/ECS */
-#define DEFMODE_AMBER_PAL  "pal-lace"	/* for flicker fixed PAL (A3000) */
-#define DEFMODE_AMBER_NTSC "ntsc-lace"	/* for flicker fixed NTSC (A3000) */
-#define DEFMODE_AGA        "vga70"	/* for AGA */
 
-static struct fb_var_screeninfo amifb_default;
+#define DEFMODE_PAL	    2	/* "pal" for PAL OCS/ECS */
+#define DEFMODE_NTSC	    0	/* "ntsc" for NTSC OCS/ECS */
+#define DEFMODE_AMBER_PAL   3	/* "pal-lace" for flicker fixed PAL (A3000) */
+#define DEFMODE_AMBER_NTSC  1	/* "ntsc-lace" for flicker fixed NTSC (A3000) */
+#define DEFMODE_AGA	    19	/* "vga70" for AGA */
+
+
+static int amifb_ilbm = 0;	/* interleaved or normal bitplanes */
+static int amifb_inverse = 0;
 
 
 	/*
@@ -1162,7 +1099,7 @@
 	 * Interface used by the world
 	 */
 
-void amifb_setup(char *options, int *ints);
+int amifb_setup(char*);
 
 static int amifb_open(struct fb_info *info, int user);
 static int amifb_release(struct fb_info *info, int user);
@@ -1193,7 +1130,7 @@
 	 * Interface to the low level console driver
 	 */
 
-void amifb_init(void);
+int amifb_init(void);
 static int amifbcon_switch(int con, struct fb_info *info);
 static int amifbcon_updatevar(int con, struct fb_info *info);
 static void amifbcon_blank(int blank, struct fb_info *info);
@@ -1205,8 +1142,6 @@
 static void do_install_cmap(int con, struct fb_info *info);
 static int flash_cursor(void);
 static void amifb_interrupt(int irq, void *dev_id, struct pt_regs *fp);
-static void get_video_mode(const char *name);
-static void check_default_mode(void);
 static u_long chipalloc(u_long size);
 static char *strtoke(char *s,const char *ct);
 
@@ -1259,7 +1194,7 @@
 	amifb_pan_display, amifb_ioctl
 };
 
-void __init amifb_setup(char *options, int *ints)
+int __init amifb_setup(char *options)
 {
 	char *this_opt;
 	char mcap_spec[80];
@@ -1268,11 +1203,9 @@
 	fb_info.fontname[0] = '\0';
 
 	if (!options || !*options)
-		return;
+		return 0;
 
 	for (this_opt = strtok(options, ","); this_opt; this_opt = strtok(NULL, ",")) {
-		char *p;
-
 		if (!strcmp(this_opt, "inverse")) {
 			amifb_inverse = 1;
 			fb_invert_cmaps();
@@ -1284,54 +1217,8 @@
 			strcpy(fb_info.fontname, this_opt+5);
 		else if (!strncmp(this_opt, "fstart:", 7))
 			min_fstrt = simple_strtoul(this_opt+7, NULL, 0);
-		else if (!strncmp(this_opt, "depth:", 6))
-			amifb_userdepth = simple_strtoul(this_opt+6, NULL, 0);
-		else if (!strncmp(this_opt, "size:", 5)) {
-			p = this_opt + 5;
-			if (*p != ';')
-				amifb_default.xres = simple_strtoul(p, NULL, 0);
-			if (!(p = strchr(p, ';')))
-				continue;
-			if (*++p != ';')
-				amifb_default.yres = simple_strtoul(p, NULL, 0);
-			if (!(p = strchr(p, ';')))
-				continue;
-			if (*++p != ';')
-				amifb_default.xres_virtual = simple_strtoul(p, NULL, 0);
-			if (!(p = strchr(p, ';')))
-				continue;
-			if (*++p != ';')
-				amifb_default.yres_virtual = simple_strtoul(p, NULL, 0);
-			if (!(p = strchr(p, ';')))
-				continue;
-			if (*++p)
-				amifb_default.bits_per_pixel = simple_strtoul(p, NULL, 0);
-		} else if (!strncmp(this_opt, "timing:", 7)) {
-			p = this_opt + 7;
-			if (*p != ';')
-				amifb_default.left_margin = simple_strtoul(p, NULL, 0);
-			if (!(p = strchr(p, ';')))
-				continue;
-			if (*++p != ';')
-				amifb_default.right_margin = simple_strtoul(p, NULL, 0);
-			if (!(p = strchr(p, ';')))
-				continue;
-			if (*++p != ';')
-				amifb_default.upper_margin = simple_strtoul(p, NULL, 0);
-			if (!(p = strchr(p, ';')))
-				continue;
-			if (*++p)
-				amifb_default.lower_margin = simple_strtoul(p, NULL, 0);
-		} else if (!strncmp(this_opt, "sync:", 5)) {
-			p = this_opt + 5;
-			if (*p != ';')
-				amifb_default.hsync_len = simple_strtoul(p, NULL, 0);
-			if (!(p = strchr(p, ';')))
-				continue;
-			if (*++p)
-				amifb_default.vsync_len = simple_strtoul(p, NULL, 0);
-		} else
-			get_video_mode(this_opt);
+		else
+			mode_option = this_opt;
 	}
 
 	if (min_fstrt < 48)
@@ -1374,6 +1261,7 @@
 cap_invalid:
 		;
 	}
+	return 0;
 }
 
 	/*
@@ -1714,13 +1602,15 @@
 	 * Initialisation
 	 */
 
-void __init amifb_init(void)
+int __init amifb_init(void)
 {
 	int tag, i;
 	u_long chipptr;
+	u_int defmode;
+	struct fb_var_screeninfo var;
 
 	if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_VIDEO))
-		return;
+		return -ENXIO;
 
 	/*
 	 * TODO: where should we put this? The DMI Resolver doesn't have a
@@ -1731,7 +1621,7 @@
 	if (amifb_resolver){
 		custom.dmacon = DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
 				DMAF_BLITTER | DMAF_SPRITE;
-		return;
+		return 0;
 	}
 #endif
 
@@ -1747,9 +1637,8 @@
 			maxdepth[TAG_HIRES] = 4;
 			maxdepth[TAG_LORES] = 6;
 			maxfmode = TAG_FMODE_1;
-			if (!amifb_usermode)		/* Set the Default Video Mode */
-				get_video_mode(amiga_vblank == 50 ?
-				               DEFMODE_PAL : DEFMODE_NTSC);
+			defmode = amiga_vblank == 50 ? DEFMODE_PAL
+						     : DEFMODE_NTSC;
 			videomemorysize = VIDEOMEMSIZE_OCS;
 			break;
 #endif /* CONFIG_FB_AMIGA_OCS */
@@ -1762,14 +1651,12 @@
 			maxdepth[TAG_HIRES] = 4;
 			maxdepth[TAG_LORES] = 6;
 			maxfmode = TAG_FMODE_1;
-			if (!amifb_usermode) {		/* Set the Default Video Mode */
-				if (AMIGAHW_PRESENT(AMBER_FF))
-					get_video_mode(amiga_vblank == 50 ?
-					               DEFMODE_AMBER_PAL : DEFMODE_AMBER_NTSC);
-				else
-					get_video_mode(amiga_vblank == 50 ?
-					               DEFMODE_PAL : DEFMODE_NTSC);
-			}
+			if (AMIGAHW_PRESENT(AMBER_FF))
+			    defmode = amiga_vblank == 50 ? DEFMODE_AMBER_PAL
+							 : DEFMODE_AMBER_NTSC;
+			else
+			    defmode = amiga_vblank == 50 ? DEFMODE_PAL
+							 : DEFMODE_NTSC;
 			if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT >
 			    VIDEOMEMSIZE_ECS_1M)
 				videomemorysize = VIDEOMEMSIZE_ECS_2M;
@@ -1786,8 +1673,7 @@
 			maxdepth[TAG_HIRES] = 8;
 			maxdepth[TAG_LORES] = 8;
 			maxfmode = TAG_FMODE_4;
-			if (!amifb_usermode)		/* Set the Default Video Mode */
-				get_video_mode(DEFMODE_AGA);
+			defmode = DEFMODE_AGA;
 			if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT >
 			    VIDEOMEMSIZE_AGA_1M)
 				videomemorysize = VIDEOMEMSIZE_AGA_2M;
@@ -1802,7 +1688,7 @@
 			strcat(amifb_name, "Unknown");
 			goto default_chipset;
 #else /* CONFIG_FB_AMIGA_OCS */
-			return;
+			return -ENXIO;
 #endif /* CONFIG_FB_AMIGA_OCS */
 			break;
 	}
@@ -1823,23 +1709,13 @@
 	 * Replace the Tag Values with the Real Pixel Clock Values
 	 */
 
-	if (amifb_userdepth != -1)
-		amifb_default.bits_per_pixel = amifb_userdepth;
 	for (i = 0; i < NUM_TOTAL_MODES; i++) {
-		struct fb_var_screeninfo *var = &amifb_predefined[i].var;
-		tag = var->pixclock;
+		struct fb_videomode *mode = &ami_modedb[i];
+		tag = mode->pixclock;
 		if (tag == TAG_SHRES || tag == TAG_HIRES || tag == TAG_LORES) {
-			var->pixclock = pixclock[tag];
-			if (var->bits_per_pixel > maxdepth[tag])
-				var->bits_per_pixel = maxdepth[tag];
+			mode->pixclock = pixclock[tag];
 		}
 	}
-	tag = amifb_default.pixclock;
-	if (tag == TAG_SHRES || tag == TAG_HIRES || tag == TAG_LORES) {
-		amifb_default.pixclock = pixclock[tag];
-		if (amifb_default.bits_per_pixel > maxdepth[tag])
-			amifb_default.bits_per_pixel = maxdepth[tag];
-	}
 
 	/*
 	 *  These monitor specs are for a typical Amiga monitor (e.g. A1960)
@@ -1861,6 +1737,11 @@
 	fb_info.blank = &amifbcon_blank;
 	fb_info.flags = FBINFO_FLAG_DEFAULT;
 
+	if (!fb_find_mode(&var, &fb_info, mode_option, ami_modedb,
+			  NUM_TOTAL_MODES, &ami_modedb[defmode], 4))
+	    panic("Can't find any usable video mode");
+
+	round_down_bpp = 0;
 	chipptr = chipalloc(videomemorysize+
 	                    SPRITEMEMSIZE+
 	                    DUMMYSPRITEMEMSIZE+
@@ -1903,9 +1784,7 @@
 
 	ami_init_copper();
 
-	check_default_mode();
-
-	if (request_irq(IRQ_AMIGA_AUTO_3, amifb_interrupt, IRQ_FLG_LOCK,
+	if (request_irq(IRQ_AMIGA_AUTO_3, amifb_interrupt, 0,
 	                "fb vertb handler", NULL))
 		panic("Couldn't add vblank interrupt\n");
 	ami_intena_vals[IRQ_AMIGA_VERTB] = IF_COPER;
@@ -1913,10 +1792,10 @@
 	custom.intena = IF_VERTB;
 	custom.intena = IF_SETCLR | IF_COPER;
 
-	amifb_set_var(&amifb_default, -1, &fb_info);
+	amifb_set_var(&var, -1, &fb_info);
 
 	if (register_framebuffer(&fb_info) < 0)
-		return;
+		return -EINVAL;
 
 	printk("fb%d: %s frame buffer device, using %ldK of video memory\n",
 	       GET_FB_IDX(fb_info.node), fb_info.modename,
@@ -1924,6 +1803,8 @@
 
 	/* TODO: This driver cannot be unloaded yet */
 	MOD_INC_USE_COUNT;
+
+	return 0;
 }
 
 static int amifbcon_switch(int con, struct fb_info *info)
@@ -2049,43 +1930,6 @@
 }
 
 	/*
-	 * Get a Video Mode
-	 */
-
-static void __init get_video_mode(const char *name)
-{
-	int i;
-
-	for (i = 0; i < NUM_TOTAL_MODES; i++) {
-		if (!strcmp(name, amifb_predefined[i].name)) {
-			amifb_default = amifb_predefined[i].var;
-			amifb_usermode = i;
-			return;
-		}
-	}
-}
-
-	/*
-	 *  Probe the Video Modes
-	 */
-
-static void __init check_default_mode(void)
-{
-	struct amifb_par par;
-	int mode;
-
-	if (!ami_decode_var(&amifb_default, &par))
-		return;
-	printk("Can't use default video mode. Probing video modes...\n");
-	for (mode = 0; mode < NUM_TOTAL_MODES; mode++)
-		if (!ami_decode_var(&amifb_predefined[mode].var, &par)) {
-			amifb_default = amifb_predefined[mode].var;
-			return;
-		}
-	panic("Can't find any usable video mode");
-}
-
-	/*
 	 * Allocate, Clear and Align a Block of Chip Memory
 	 */
 
@@ -2214,8 +2058,12 @@
 		if (par->bpp < 1)
 			par->bpp = 1;
 		if (par->bpp > maxdepth[clk_shift]) {
-			DPRINTK("invalid bpp\n");
-			return -EINVAL;
+			if (round_down_bpp && maxdepth[clk_shift])
+				par->bpp = maxdepth[clk_shift];
+			else {
+				DPRINTK("invalid bpp\n");
+				return -EINVAL;
+			}
 		}
 	} else if (var->nonstd == FB_NONSTD_HAM) {
 		if (par->bpp < 6)
@@ -3519,8 +3367,7 @@
 #ifdef MODULE
 int init_module(void)
 {
-	amifb_init();
-	return 0;
+	return amifb_init();
 }
 
 void cleanup_module(void)
diff -u --recursive --new-file v2.3.13/linux/drivers/video/atafb.c linux/drivers/video/atafb.c
--- v2.3.13/linux/drivers/video/atafb.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/atafb.c	Thu Aug 12 10:22:33 1999
@@ -2745,14 +2745,14 @@
 		do_install_cmap(currcon, info);
 }
 
-void __init atafb_init(void)
+int __init atafb_init(void)
 {
 	int pad;
 	int detected_mode;
 	unsigned long mem_req;
 
 	if (!MACH_IS_ATARI)
-	        return;
+	        return -ENXIO;
 
 	do {
 #ifdef ATAFB_EXT
@@ -2858,7 +2858,7 @@
 	do_install_cmap(0, &fb_info);
 
 	if (register_framebuffer(&fb_info) < 0)
-		return;
+		return -EINVAL;
 
 	printk("Determined %dx%d, depth %d\n",
 	       disp.var.xres, disp.var.yres, disp.var.bits_per_pixel);
@@ -2871,6 +2871,8 @@
 
 	/* TODO: This driver cannot be unloaded yet */
 	MOD_INC_USE_COUNT;
+
+	return 0;
 }
 
 /* a strtok which returns empty strings, too */
@@ -2895,7 +2897,7 @@
   return sbegin;
 }
 
-void __init atafb_setup( char *options, int *ints )
+int __init atafb_setup( char *options )
 {
     char *this_opt;
     int temp;
@@ -2910,7 +2912,7 @@
 	fb_info.fontname[0] = '\0';
 
     if (!options || !*options)
-		return;
+		return 0;
      
     for(this_opt=strtok(options,","); this_opt; this_opt=strtok(NULL,",")) {
 	if (!*this_opt) continue;
@@ -3146,13 +3148,13 @@
 	  user_invalid:
 		;
 	}
+	return 0;
 }
 
 #ifdef MODULE
 int init_module(void)
 {
-	atafb_init();
-	return 0;
+	return atafb_init();
 }
 
 void cleanup_module(void)
diff -u --recursive --new-file v2.3.13/linux/drivers/video/atyfb.c linux/drivers/video/atyfb.c
--- v2.3.13/linux/drivers/video/atyfb.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/atyfb.c	Wed Aug 18 10:10:06 1999
@@ -386,11 +386,11 @@
      *  Interface used by the world
      */
 
-void atyfb_init(void);
+int atyfb_init(void);
 #ifdef CONFIG_FB_OF
 void atyfb_of_init(struct device_node *dp);
 #endif
-void atyfb_setup(char *options, int *ints);
+int atyfb_setup(char*);
 
 static int currcon = 0;
 
@@ -411,6 +411,7 @@
 static u32 default_vram __initdata = 0;
 static int default_pll __initdata = 0;
 static int default_mclk __initdata = 0;
+static const char *mode_option __initdata = NULL;
 
 #if defined(CONFIG_PPC)
 static int default_vmode __initdata = VMODE_NVRAM;
@@ -479,10 +480,10 @@
 
 #if defined(__powerpc__)
     temp = info->ati_regbase;
-    asm("lwbrx %0,%1,%2" : "=r"(val) : "b" (regindex), "r" (temp));
+    asm volatile("lwbrx %0,%1,%2" : "=r"(val) : "b" (regindex), "r" (temp));
 #elif defined(__sparc_v9__)
     temp = info->ati_regbase + regindex;
-    asm("lduwa [%1] %2, %0" : "=r" (val) : "r" (temp), "i" (ASI_PL));
+    asm volatile("lduwa [%1] %2, %0" : "=r" (val) : "r" (temp), "i" (ASI_PL));
 #else
     temp = info->ati_regbase+regindex;
     val = le32_to_cpu(*((volatile u32 *)(temp)));
@@ -497,11 +498,11 @@
 
 #if defined(__powerpc__)
     temp = info->ati_regbase;
-    asm("stwbrx %0,%1,%2" : : "r" (val), "b" (regindex), "r" (temp) :
+    asm volatile("stwbrx %0,%1,%2" : : "r" (val), "b" (regindex), "r" (temp) :
 	"memory");
 #elif defined(__sparc_v9__)
     temp = info->ati_regbase + regindex;
-    asm("stwa %0, [%1] %2" : : "r" (val), "r" (temp), "i" (ASI_PL) : "memory");
+    asm volatile("stwa %0, [%1] %2" : : "r" (val), "r" (temp), "i" (ASI_PL) : "memory");
 #else
     temp = info->ati_regbase+regindex;
     *((volatile u32 *)(temp)) = cpu_to_le32(val);
@@ -2218,7 +2219,6 @@
 static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
 		       u_long arg, int con, struct fb_info *info2)
 {
-    struct fb_info_aty *info = (struct fb_info_aty *)info2;
 #ifdef __sparc__
     struct fbtype fbtyp;
     struct display *disp;
@@ -2734,32 +2734,55 @@
 	    info->total_vram -= GUI_RESERVE;
 	}
 
+    disp = &info->disp;
+
+    strcpy(info->fb_info.modename, atyfb_name);
+    info->fb_info.node = -1;
+    info->fb_info.fbops = &atyfb_ops;
+    info->fb_info.disp = disp;
+    strcpy(info->fb_info.fontname, fontname);
+    info->fb_info.changevar = NULL;
+    info->fb_info.switch_con = &atyfbcon_switch;
+    info->fb_info.updatevar = &atyfbcon_updatevar;
+    info->fb_info.blank = &atyfbcon_blank;
+    info->fb_info.flags = FBINFO_FLAG_DEFAULT;
+
+#ifdef MODULE
+    var = default_var;
+#else /* !MODULE */
 #if defined(CONFIG_PPC)
-    if (default_vmode == VMODE_NVRAM) {
-	default_vmode = nvram_read_byte(NV_VMODE);
+    if (mode_option) {
+	if (!mac_find_mode(&var, &info->fb_info, mode_option, 8))
+	    var = default_var;
+    } else {
+	if (default_vmode == VMODE_NVRAM) {
+	    default_vmode = nvram_read_byte(NV_VMODE);
+	    if (default_vmode <= 0 || default_vmode > VMODE_MAX)
+		default_vmode = VMODE_CHOOSE;
+	}
+	if (default_vmode == VMODE_CHOOSE) {
+	    if (Gx == LG_CHIP_ID)
+		/* G3 PowerBook with 1024x768 LCD */
+		default_vmode = VMODE_1024_768_60;
+	    else {
+		sense = read_aty_sense(info);
+		default_vmode = mac_map_monitor_sense(sense);
+	    }
+	}
 	if (default_vmode <= 0 || default_vmode > VMODE_MAX)
-	    default_vmode = VMODE_CHOOSE;
+	    default_vmode = VMODE_640_480_60;
+	if (default_cmode == CMODE_NVRAM)
+	    default_cmode = nvram_read_byte(NV_CMODE);
+	if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
+	    default_cmode = CMODE_8;
+	if (mac_vmode_to_var(default_vmode, default_cmode, &var))
+	    var = default_var;
     }
-    if (default_vmode == VMODE_CHOOSE) {
-	if (Gx == LG_CHIP_ID)
-	    /* G3 PowerBook with 1024x768 LCD */
-	    default_vmode = VMODE_1024_768_60;
-	else {
-	    sense = read_aty_sense(info);
-	    default_vmode = mac_map_monitor_sense(sense);
-	}
-    }
-    if (default_vmode <= 0 || default_vmode > VMODE_MAX)
-	default_vmode = VMODE_640_480_60;
-    if (default_cmode == CMODE_NVRAM)
-	default_cmode = nvram_read_byte(NV_CMODE);
-    if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
-	default_cmode = CMODE_8;
-    if (mac_vmode_to_var(default_vmode, default_cmode, &var))
-	var = default_var;
 #else /* !CONFIG_PPC */
-    var = default_var;
+    if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, NULL, 8))
+	var = default_var;
 #endif /* !CONFIG_PPC */
+#endif /* !MODULE */
     if (noaccel)
         var.accel_flags &= ~FB_ACCELF_TEXT;
     else
@@ -2777,19 +2800,6 @@
 	return 0;
     }
 
-    disp = &info->disp;
-
-    strcpy(info->fb_info.modename, atyfb_name);
-    info->fb_info.node = -1;
-    info->fb_info.fbops = &atyfb_ops;
-    info->fb_info.disp = disp;
-    strcpy(info->fb_info.fontname, fontname);
-    info->fb_info.changevar = NULL;
-    info->fb_info.switch_con = &atyfbcon_switch;
-    info->fb_info.updatevar = &atyfbcon_updatevar;
-    info->fb_info.blank = &atyfbcon_blank;
-    info->fb_info.flags = FBINFO_FLAG_DEFAULT;
-
 #ifdef __sparc__
     atyfb_save_palette(&info->fb_info, 0);
 #endif
@@ -2821,7 +2831,7 @@
     return 1;
 }
 
-void __init atyfb_init(void)
+int __init atyfb_init(void)
 {
 #if defined(CONFIG_FB_OF)
     /* We don't want to be called like this. */
@@ -2841,7 +2851,7 @@
 
     /* Do not attach when we have a serial console. */
     if (!con_is_present())
-	return;
+	return -ENXIO;
 #else
     u16 tmp;
 #endif
@@ -2854,7 +2864,7 @@
 	    info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
 	    if (!info) {
 		printk("atyfb_init: can't alloc fb_info_aty\n");
-		return;
+		return -ENXIO;
 	    }
 	    memset(info, 0, sizeof(struct fb_info_aty));
 
@@ -2890,7 +2900,7 @@
 	    if (!info->mmap_map) {
 		printk("atyfb_init: can't alloc mmap_map\n");
 		kfree(info);
-		return;
+		return -ENXIO;
 	    }
 	    memset(info->mmap_map, 0, j * sizeof(*info->mmap_map));
 
@@ -2904,14 +2914,12 @@
 
 		io = (rp->flags & IORESOURCE_IOPORT);
 
+		size = rp->end - base + 1;
+		
 		pci_read_config_dword(pdev, breg, &pbase);
-		pci_write_config_dword(pdev, breg, 0xffffffff);
-		pci_read_config_dword(pdev, breg, &size);
-		pci_write_config_dword(pdev, breg, pbase);
 
 		if (io)
 			size &= ~1;
-		size = ~(size) + 1;
 
 		/*
 		 * Map the framebuffer a second time, this time without
@@ -3071,7 +3079,7 @@
 
 	    if(!info->ati_regbase) {
 		    kfree(info);
-		    return;
+		    return -ENOMEM;
 	    }
 
 	    info->ati_regbase_phys += 0xc00;
@@ -3098,7 +3106,7 @@
 
 	    if(!info->frame_buffer) {
 		    kfree(info);
-		    return;
+		    return -ENXIO;
 	    }
 
 #endif /* __sparc__ */
@@ -3107,7 +3115,7 @@
 		if (info->mmap_map)
 		    kfree(info->mmap_map);
 		kfree(info);
-		return;
+		return -ENXIO;
 	    }
 
 #ifdef __sparc__
@@ -3145,7 +3153,7 @@
 	info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
 	if (!info) {
 	    printk("atyfb_init: can't alloc fb_info_aty\n");
-	    return;
+	    return -ENOMEM;
 	}
 	memset(info, 0, sizeof(struct fb_info_aty));
 
@@ -3161,10 +3169,11 @@
 	if (!aty_init(info, "ISA bus")) {
 	    kfree(info);
 	    /* This is insufficient! kernel_map has added two large chunks!! */
-	    return;
+	    return -ENXIO;
 	}
     }
 #endif
+    return 0;
 }
 
 #ifdef CONFIG_FB_OF
@@ -3252,12 +3261,12 @@
 #endif /* CONFIG_FB_OF */
 
 
-void __init atyfb_setup(char *options, int *ints)
+int __init atyfb_setup(char *options)
 {
     char *this_opt;
 
     if (!options || !*options)
-	return;
+	return 0;
 
     for (this_opt = strtok(options, ","); this_opt;
 	 this_opt = strtok(NULL, ",")) {
@@ -3320,6 +3329,7 @@
 	}
 #endif
     }
+    return 0;
 }
 
 #ifdef CONFIG_ATARI
diff -u --recursive --new-file v2.3.13/linux/drivers/video/chipsfb.c linux/drivers/video/chipsfb.c
--- v2.3.13/linux/drivers/video/chipsfb.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/chipsfb.c	Thu Aug 12 10:22:33 1999
@@ -112,7 +112,7 @@
 /*
  * Exported functions
  */
-void chips_init(void);
+int chips_init(void);
 void chips_of_init(struct device_node *dp);
 
 static int chips_open(struct fb_info *info, int user);
@@ -645,7 +645,7 @@
 	all_chips = p;
 }
 
-void __init chips_init(void)
+int __init chips_init(void)
 {
 #ifndef CONFIG_FB_OF
 	struct device_node *dp;
@@ -654,6 +654,7 @@
 	if (dp != 0)
 		chips_of_init(dp);
 #endif /* CONFIG_FB_OF */
+	return 0;
 }
 
 void __init chips_of_init(struct device_node *dp)
diff -u --recursive --new-file v2.3.13/linux/drivers/video/clgenfb.c linux/drivers/video/clgenfb.c
--- v2.3.13/linux/drivers/video/clgenfb.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/clgenfb.c	Wed Aug 18 10:10:06 1999
@@ -1,7 +1,38 @@
 /*
- * Based on retz3fb.c and clgen.c
+ * drivers/video/clgenfb.c - driver for Cirrus Logic chipsets
+ *
+ * Copyright 1999 Jeff Garzik <jgarzik@pobox.com>
+ *
+ * Contributors (thanks, all!)
+ *
+ *      Jeff Rugen:
+ *      Major contributions;  Motorola PowerStack (PPC and PCI) support,
+ *      GD54xx, 1280x1024 mode support, change MCLK based on VCLK.
+ *
+ *	Geert Uytterhoeven:
+ *	Excellent code review.
+ *
+ *	Lars Hecking:
+ *	Amiga updates and testing.
+ *
+ * Original clgenfb author:  Frank Neumann
+ *
+ * Based on retz3fb.c and clgen.c:
+ *      Copyright (C) 1997 Jes Sorensen
+ *      Copyright (C) 1996 Frank Neumann
+ *
+ ***************************************************************
+ *
+ * Format this code with GNU indent '-kr -i8 -pcs' options.
+ *
+ * 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.
+ *
  */
- 
+
+#define CLGEN_VERSION "1.9.4.1"
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -11,12 +42,22 @@
 #include <linux/malloc.h>
 #include <linux/delay.h>
 #include <linux/fb.h>
-#include <linux/zorro.h>
 #include <linux/init.h>
-#include <asm/amigahw.h>
 #include <asm/pgtable.h>
 #include <asm/delay.h>
 #include <asm/io.h>
+#ifdef CONFIG_ZORRO
+#include <linux/zorro.h>
+#endif
+#ifdef CONFIG_PCI
+#include <linux/pci.h>
+#endif
+#ifdef CONFIG_AMIGA
+#include <asm/amigahw.h>
+#endif
+#ifdef CONFIG_FB_OF
+#include <asm/prom.h>
+#endif
 
 #include <video/fbcon.h>
 #include <video/fbcon-mfb.h>
@@ -26,125 +67,322 @@
 #include <video/fbcon-cfb32.h>
 
 #include "clgenfb.h"
+#include "vga.h"
 
-#define CLGEN_VERSION "1.4 ?"
-/* #define DEBUG if(1) */
-#define DEBUG if(0)
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif
+
+#ifndef KERNEL_VERSION
+#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
+#endif
+
+
+/* enable debug output? */
+/* #define CLGEN_DEBUG 1 */
+
+/* disable runtime assertions? */
+/* #define CLGEN_NDEBUG */
+
+
+/* debug output */
+#ifdef CLGEN_DEBUG
+#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+/* debugging assertions */
+#ifndef CLGEN_NDEBUG
+#define assert(expr) \
+        if(!(expr)) { \
+        printk( "Assertion failed! %s,%s,%s,line=%d\n",\
+        #expr,__FILE__,__FUNCTION__,__LINE__); \
+        *(int*)0 = 0;\
+        }
+#else
+#define assert(expr)
+#endif
 
 #define arraysize(x)    (sizeof(x)/sizeof(*(x)))
 
-/* board types */
-#define BT_NONE     0
-#define BT_SD64     1
-#define BT_PICCOLO  2
-#define BT_PICASSO  3
-#define BT_SPECTRUM 4
-#define BT_PICASSO4 5
+#ifdef TRUE
+#undef TRUE
+#endif
+#ifdef FALSE
+#undef FALSE
+#endif
+#define TRUE  1
+#define FALSE 0
+
+#define MB_ (1024*1024)
 
 #define MAX_NUM_BOARDS 7
 
-#define TRUE  1
-#define FALSE 0 
 
-struct clgenfb_par
-{
-    struct fb_var_screeninfo var;
+/* board types */
+typedef enum {
+	BT_NONE = 0,
+	BT_SD64,
+	BT_PICCOLO,
+	BT_PICASSO,
+	BT_SPECTRUM,
+	BT_PICASSO4,	/* GD5446 */
+	BT_ALPINE,	/* GD543x/4x */
+	BT_GD5480,
+} clgen_board_t;
+
+
+
+/*
+ * per-board-type information, used for enumerating and abstracting
+ * chip-specific information
+ * NOTE: MUST be in the same order as clgen_board_t in order to
+ * use direct indexing on this array
+ * NOTE: '__initdata' cannot be used as some of this info
+ * is required at runtime.  Maybe separate into an init-only and
+ * a run-time table?
+ */
+static const struct clgen_board_info_rec {
+	clgen_board_t btype;	/* chipset enum, not strictly necessary, as
+				 * clgen_board_info[] is directly indexed
+				 * by this value */
+	char *name;		/* ASCII name of chipset */
+	long maxclock;		/* maximum video clock */
+	unsigned write_sr1f : 1; /* write SR1F during init_vgachip() */
+	unsigned scrn_start_bit19 : 1; /* construct bit 19 of screen start address */
+	unsigned char sr07;	/* SR07 VGA register value */
+	unsigned char sr1f;	/* SR1F VGA register value */
+} clgen_board_info[] = {
+	{ BT_NONE, }, /* dummy record */
+	{ BT_SD64,
+		"CL SD64",
+		140000,		/* the SD64/P4 have a higher max. videoclock */
+		TRUE,		
+		TRUE,		
+		0xf0,		
+		0x20 },		
+	{ BT_PICCOLO,
+		"CL Piccolo",
+		90000,		
+		TRUE,
+		FALSE,
+		0x80,
+		0x22 },
+	{ BT_PICASSO,
+		"CL Picasso",
+		90000,
+		TRUE,
+		FALSE,
+		0x20,
+		0x22 },
+	{ BT_SPECTRUM,
+		"CL Spectrum",
+		90000,
+		TRUE,
+		FALSE,
+		0x80,
+		0x22 },
+	{ BT_PICASSO4,
+		"CL Picasso4",
+		140000,		/* the SD64/P4 have a higher max. videoclock */
+		FALSE,
+		TRUE,
+		0x20,
+		0 },
+	{ BT_ALPINE,
+		"CL Alpine",
+		110000,		/* 135100 for some, 85500 for others */
+		TRUE,
+		TRUE,
+		0xA0,
+		0x1C },
+	{ BT_GD5480,
+		"CL GD5480",
+		90000,
+		TRUE,
+		TRUE,
+		0x10,
+		0x1C },
+};
+
 
-    __u32 line_length;  /* in BYTES! */
-    __u32 visual;
-    __u32 type;
-
-    long freq;
-    long nom;
-    long den;
-    long div;
-
-    long HorizRes;   /* The x resolution in pixel */
-    long HorizTotal;
-    long HorizDispEnd;
-    long HorizBlankStart;
-    long HorizBlankEnd;
-    long HorizSyncStart;
-    long HorizSyncEnd;
-
-    long VertRes;   /* the physical y resolution in scanlines */
-    long VertTotal;
-    long VertDispEnd;
-    long VertSyncStart;
-    long VertSyncEnd;
-    long VertBlankStart;
-    long VertBlankEnd;
+#ifdef CONFIG_PCI
+/* the list of PCI devices for which we probe, and the
+ * order in which we do it */
+static const struct {
+	clgen_board_t btype;
+	unsigned short device;
+} clgen_pci_probe_list[] __initdata = {
+	{ BT_ALPINE, PCI_DEVICE_ID_CIRRUS_5436 },
+	{ BT_ALPINE, PCI_DEVICE_ID_CIRRUS_5434_8 },
+	{ BT_ALPINE, PCI_DEVICE_ID_CIRRUS_5434_4 },
+	{ BT_ALPINE, PCI_DEVICE_ID_CIRRUS_5430 }, /* GD-5440 has identical id */
+	{ BT_GD5480, PCI_DEVICE_ID_CIRRUS_5480 }, /* MacPicasso probably */
+	{ BT_PICASSO4, PCI_DEVICE_ID_CIRRUS_5446 }, /* Picasso 4 is a GD5446 */
 };
+#endif /* CONFIG_PCI */
+
+
+
+#ifdef CONFIG_ZORRO
+static const struct {
+	clgen_board_t btype;
+	int key, key2;
+} clgen_zorro_probe_list[] __initdata = {
+	{ BT_SD64,
+		ZORRO_PROD_HELFRICH_SD64_RAM,
+		ZORRO_PROD_HELFRICH_SD64_REG },
+	{ BT_PICCOLO,
+		ZORRO_PROD_HELFRICH_PICCOLO_RAM,
+		ZORRO_PROD_HELFRICH_PICCOLO_REG },
+	{ BT_PICASSO,
+		ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
+		ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG },
+	{ BT_SPECTRUM,
+		ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
+		ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG },
+	{ BT_PICASSO4,
+		ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3,
+		0 },
+};
+#endif /* CONFIG_ZORRO */
+
+
+
+struct clgenfb_par {
+	struct fb_var_screeninfo var;
+
+	__u32 line_length;	/* in BYTES! */
+	__u32 visual;
+	__u32 type;
+
+	long freq;
+	long nom;
+	long den;
+	long div;
+	long multiplexing;
+	long mclk;
+	long divMCLK;
+
+	long HorizRes;		/* The x resolution in pixel */
+	long HorizTotal;
+	long HorizDispEnd;
+	long HorizBlankStart;
+	long HorizBlankEnd;
+	long HorizSyncStart;
+	long HorizSyncEnd;
+
+	long VertRes;		/* the physical y resolution in scanlines */
+	long VertTotal;
+	long VertDispEnd;
+	long VertSyncStart;
+	long VertSyncEnd;
+	long VertBlankStart;
+	long VertBlankEnd;
+};
+
+
+
+#ifdef CLGEN_DEBUG
+typedef enum {
+        CRT,
+        SEQ
+} clgen_dbg_reg_class_t;
+#endif                          /* CLGEN_DEBUG */
+
+
+
 
 /* info about board */
-struct clgenfb_info
-{
-    struct fb_info_gen gen;
+struct clgenfb_info {
+	struct fb_info_gen gen;
 
-    int keyRAM;  /* RAM, REG zorro board keys */
-    int keyREG;
-    unsigned long fbmem;
-    volatile unsigned char *regs;
-    unsigned long mem;
-    unsigned long size;
-    int btype;
-    int smallboard;
-    unsigned char SFR; /* Shadow of special function register */
-
-    unsigned long fbmem_phys;
-    unsigned long fbregs_phys;
-    
-    struct clgenfb_par currentmode;
-    union {
+	caddr_t fbmem;
+	caddr_t regs;
+	caddr_t mem;
+	unsigned long size;
+	clgen_board_t btype;
+	int smallboard;
+	unsigned char SFR;	/* Shadow of special function register */
+
+	unsigned long fbmem_phys;
+	unsigned long fbregs_phys;
+
+	struct clgenfb_par currentmode;
+	union {
 #ifdef FBCON_HAS_CFB16
-	u16 cfb16[16];
+		u16 cfb16[16];
 #endif
 #ifdef FBCON_HAS_CFB24
-	u32 cfb24[16];
+		u32 cfb24[16];
 #endif
 #ifdef FBCON_HAS_CFB32
-	u32 cfb32[16];
+		u32 cfb32[16];
+#endif
+	} fbcon_cmap;
+
+#ifdef CONFIG_ZORRO
+	int keyRAM;		/* RAM, REG zorro board keys */
+	int keyREG;
+#endif
+
+#ifdef CONFIG_PCI
+	struct pci_dev *pdev;
 #endif
-    } fbcon_cmap;
 };
 
+
+
+
 static struct display disp;
 
-static struct clgenfb_info boards[MAX_NUM_BOARDS];  /* the boards */
-static struct clgenfb_info *fb_info=NULL;  /* pointer to current board */
+static struct clgenfb_info boards[MAX_NUM_BOARDS];	/* the boards */
+
+static unsigned clgen_def_mode = 0;
+
+
 
 /*
  *    Predefined Video Modes
  */
 
-static struct fb_videomode clgenfb_predefined[] __initdata =
+static const struct {
+	const char *name;
+	struct fb_var_screeninfo var;
+} clgenfb_predefined[] __initdata =
+
 {
-	{   "Autodetect", /* autodetect mode */
-	    { 0 }
+	{"Autodetect",		/* autodetect mode */
+	 {0}
 	},
 
-	{   "640x480", /* 640x480, 31.25 kHz, 60 Hz, 25 MHz PixClock */
-	    { 
-		640, 480, 640, 480, 0, 0, 8, 0, 
-		{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, 
-		0, 0, -1, -1, FB_ACCEL_NONE, 40000, 32, 32, 33, 10, 96, 2,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	    }
+	{"640x480",		/* 640x480, 31.25 kHz, 60 Hz, 25 MHz PixClock */
+	 {
+		 640, 480, 640, 480, 0, 0, 8, 0,
+		 {0, 8, 0},
+		 {0, 8, 0},
+		 {0, 8, 0},
+		 {0, 0, 0},
+	       0, 0, -1, -1, FB_ACCEL_NONE, 40000, 32, 32, 33, 10, 96, 2,
+     FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+	 }
 	},
 
-	/* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */
 	/* 
-	    Modeline from XF86Config:
-	    Mode "1024x768" 80  1024 1136 1340 1432  768 770 774 805
-	*/
-	{
-	    "1024x768",
-	    { 
-		1024, 768, 1024, 768, 0, 0, 8, 0, 
-		{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, 
-		0, 0, -1, -1, FB_ACCEL_NONE, 12500, 92, 112, 31, 2, 204, 4,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	    }
+	   Modeline from XF86Config:
+	   Mode "1024x768" 80  1024 1136 1340 1432  768 770 774 805
+	 */
+	{"1024x768",		/* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */
+		{
+			1024, 768, 1024, 768, 0, 0, 8, 0,
+			{0, 8, 0},
+			{0, 8, 0},
+			{0, 8, 0},
+			{0, 0, 0},
+	      0, 0, -1, -1, FB_ACCEL_NONE, 12500, 92, 112, 31, 2, 204, 4,
+     FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+		}
 	}
 };
 
@@ -155,135 +393,187 @@
  *    Frame Buffer Name
  */
 
-static char clgenfb_name[16] = "CLgen";
+static const char *clgenfb_name = "CLgen";
 
 /****************************************************************************/
 /**** BEGIN PROTOTYPES ******************************************************/
 
+
 /*--- Interface used by the world ------------------------------------------*/
-void clgenfb_init(void);
-void clgenfb_setup(char *options, int *ints);
-int clgenfb_open(struct fb_info *info, int user);
-int clgenfb_release(struct fb_info *info, int user);
-int clgenfb_ioctl(struct inode *inode, struct file *file, 
-		  unsigned int cmd, unsigned long arg, int con, 
-		  struct fb_info *info);
+int clgenfb_init (void);
+int clgenfb_setup (char *options);
+
+#ifdef MODULE
+static void clgenfb_cleanup (struct clgenfb_info *info);
+#endif
+
+static int clgenfb_open (struct fb_info *info, int user);
+static int clgenfb_release (struct fb_info *info, int user);
+static int clgenfb_ioctl (struct inode *inode, struct file *file,
+		   unsigned int cmd, unsigned long arg, int con,
+		   struct fb_info *info);
+#if defined(CONFIG_FB_OF)
+int clgen_of_init (struct device_node *dp);
+#endif
 
 /* function table of the above functions */
 static struct fb_ops clgenfb_ops =
 {
-    clgenfb_open,
-    clgenfb_release,
-    fbgen_get_fix,   /* using the generic functions */
-    fbgen_get_var,   /* makes things much easier... */
-    fbgen_set_var,
-    fbgen_get_cmap,
-    fbgen_set_cmap,
-    fbgen_pan_display,
-    clgenfb_ioctl,
-    NULL
+	clgenfb_open,
+	clgenfb_release,
+	fbgen_get_fix,		/* using the generic functions */
+	fbgen_get_var,		/* makes things much easier... */
+	fbgen_set_var,
+	fbgen_get_cmap,
+	fbgen_set_cmap,
+	fbgen_pan_display,
+	clgenfb_ioctl,
+	NULL
 };
 
 /*--- Hardware Specific Routines -------------------------------------------*/
-static void clgen_detect(void);
-static int  clgen_encode_fix(struct fb_fix_screeninfo *fix, const void *par,
+static void clgen_detect (void);
+static int clgen_encode_fix (struct fb_fix_screeninfo *fix, const void *par,
 			     struct fb_info_gen *info);
-static int  clgen_decode_var(const struct fb_var_screeninfo *var, void *par,
+static int clgen_decode_var (const struct fb_var_screeninfo *var, void *par,
 			     struct fb_info_gen *info);
-static int  clgen_encode_var(struct fb_var_screeninfo *var, const void *par,
+static int clgen_encode_var (struct fb_var_screeninfo *var, const void *par,
 			     struct fb_info_gen *info);
-static void clgen_get_par(void *par, struct fb_info_gen *info);
-static void clgen_set_par(const void *par, struct fb_info_gen *info);
-static int  clgen_getcolreg(unsigned regno, unsigned *red, unsigned *green,
-			   unsigned *blue, unsigned *transp,
-			   struct fb_info *info);
-static int  clgen_setcolreg(unsigned regno, unsigned red, unsigned green,
+static void clgen_get_par (void *par, struct fb_info_gen *info);
+static void clgen_set_par (const void *par, struct fb_info_gen *info);
+static int clgen_getcolreg (unsigned regno, unsigned *red, unsigned *green,
+			    unsigned *blue, unsigned *transp,
+			    struct fb_info *info);
+static int clgen_setcolreg (unsigned regno, unsigned red, unsigned green,
 			    unsigned blue, unsigned transp,
 			    struct fb_info *info);
-static int  clgen_pan_display(const struct fb_var_screeninfo *var,
+static int clgen_pan_display (const struct fb_var_screeninfo *var,
 			      struct fb_info_gen *info);
-static int  clgen_blank(int blank_mode, struct fb_info_gen *info);
+static int clgen_blank (int blank_mode, struct fb_info_gen *info);
 
-static void clgen_set_disp(const void *par, struct display *disp,
-			   struct fb_info_gen *info);
+static void clgen_set_disp (const void *par, struct display *disp,
+			    struct fb_info_gen *info);
 
 /* function table of the above functions */
-static struct fbgen_hwswitch clgen_hwswitch = 
+static struct fbgen_hwswitch clgen_hwswitch =
 {
-    clgen_detect,
-    clgen_encode_fix,
-    clgen_decode_var,
-    clgen_encode_var,
-    clgen_get_par,
-    clgen_set_par,
-    clgen_getcolreg, 
-    clgen_setcolreg,
-    clgen_pan_display,
-    clgen_blank,
-    clgen_set_disp
+	clgen_detect,
+	clgen_encode_fix,
+	clgen_decode_var,
+	clgen_encode_var,
+	clgen_get_par,
+	clgen_set_par,
+	clgen_getcolreg,
+	clgen_setcolreg,
+	clgen_pan_display,
+	clgen_blank,
+	clgen_set_disp
 };
 
 /* Text console acceleration */
 
 #ifdef FBCON_HAS_CFB8
-static void fbcon_clgen8_bmove(struct display *p, int sy, int sx, 
+static void fbcon_clgen8_bmove (struct display *p, int sy, int sx,
 				int dy, int dx, int height, int width);
-static void fbcon_clgen8_clear(struct vc_data *conp, struct display *p, 
+static void fbcon_clgen8_clear (struct vc_data *conp, struct display *p,
 				int sy, int sx, int height, int width);
 
-static struct display_switch fbcon_clgen_8 = {
-    fbcon_cfb8_setup,
-    fbcon_clgen8_bmove,
-    fbcon_clgen8_clear,
-    fbcon_cfb8_putc,
-    fbcon_cfb8_putcs,
-    fbcon_cfb8_revc,
-    NULL,
-    NULL,
-    fbcon_cfb8_clear_margins,
-    FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+static struct display_switch fbcon_clgen_8 =
+{
+	fbcon_cfb8_setup,
+	fbcon_clgen8_bmove,
+	fbcon_clgen8_clear,
+	fbcon_cfb8_putc,
+	fbcon_cfb8_putcs,
+	fbcon_cfb8_revc,
+	NULL,
+	NULL,
+	fbcon_cfb8_clear_margins,
+	FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16)
+};
+#endif
+#ifdef FBCON_HAS_CFB16
+static void fbcon_clgen16_bmove (struct display *p, int sy, int sx,
+				 int dy, int dx, int height, int width);
+static void fbcon_clgen16_clear (struct vc_data *conp, struct display *p,
+				 int sy, int sx, int height, int width);
+static struct display_switch fbcon_clgen_16 =
+{
+	fbcon_cfb16_setup,
+	fbcon_clgen16_bmove,
+	fbcon_clgen16_clear,
+	fbcon_cfb16_putc,
+	fbcon_cfb16_putcs,
+	fbcon_cfb16_revc,
+	NULL,
+	NULL,
+	fbcon_cfb16_clear_margins,
+	FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16)
+};
+#endif
+#ifdef FBCON_HAS_CFB32
+static void fbcon_clgen32_bmove (struct display *p, int sy, int sx,
+				 int dy, int dx, int height, int width);
+static void fbcon_clgen32_clear (struct vc_data *conp, struct display *p,
+				 int sy, int sx, int height, int width);
+static struct display_switch fbcon_clgen_32 =
+{
+	fbcon_cfb32_setup,
+	fbcon_clgen32_bmove,
+	fbcon_clgen32_clear,
+	fbcon_cfb32_putc,
+	fbcon_cfb32_putcs,
+	fbcon_cfb32_revc,
+	NULL,
+	NULL,
+	fbcon_cfb32_clear_margins,
+	FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16)
 };
 #endif
 
 
 
 /*--- Internal routines ----------------------------------------------------*/
-static void init_vgachip(void);
-static void switch_monitor(int on);
-
-static void		WGen( int regnum, unsigned char val );
-static unsigned char	RGen( int regnum );
-static void		WSeq( unsigned char regnum, unsigned char val );
-static unsigned char	RSeq( unsigned char regnum );
-static void		WCrt( unsigned char regnum, unsigned char val );
-static unsigned char	RCrt( unsigned char regnum );
-static void		WGfx( unsigned char regnum, unsigned char val );
-static unsigned char	RGfx( unsigned char regnum );
-static void		WAttr( unsigned char regnum, unsigned char val );
-static void		AttrOn( void );
-static unsigned char	RAttr( unsigned char regnum );
-static void		WHDR( unsigned char val );
-static unsigned char	RHDR( void );
-static void		WSFR( unsigned char val );
-static void		WSFR2( unsigned char val );
-static void		WClut( unsigned char regnum, unsigned char red, 
-						     unsigned char green, 
-						     unsigned char blue );
-static void		RClut( unsigned char regnum, unsigned char *red, 
-						     unsigned char *green, 
-						     unsigned char *blue );
-static void		clgen_WaitBLT( void );
-static void		clgen_BitBLT (u_short curx, u_short cury,
-				      u_short destx, u_short desty,
-				      u_short width, u_short height, 
-				      u_short line_length);
-static void		clgen_RectFill (u_short x, u_short y,
-					u_short width, u_short height,
-					u_char color, u_short line_length);
-
-static void		bestclock(long freq, long *best, 
-				  long *nom, long *den, 
-				  long *div, long maxfreq);
+static void init_vgachip (struct clgenfb_info *fb_info);
+static void switch_monitor (struct clgenfb_info *fb_info, int on);
+static void WGen (const struct clgenfb_info *fb_info,
+		  int regnum, unsigned char val);
+static unsigned char RGen (const struct clgenfb_info *fb_info, int regnum);
+static void AttrOn (const struct clgenfb_info *fb_info);
+static void WHDR (const struct clgenfb_info *fb_info, unsigned char val);
+static void WSFR (struct clgenfb_info *fb_info, unsigned char val);
+static void WSFR2 (struct clgenfb_info *fb_info, unsigned char val);
+static void WClut (struct clgenfb_info *fb_info, unsigned char regnum, unsigned char red,
+		   unsigned char green,
+		   unsigned char blue);
+static void RClut (struct clgenfb_info *fb_info, unsigned char regnum, unsigned char *red,
+		   unsigned char *green,
+		   unsigned char *blue);
+static void clgen_WaitBLT (caddr_t regbase);
+static void clgen_BitBLT (caddr_t regbase, u_short curx, u_short cury,
+			  u_short destx, u_short desty,
+			  u_short width, u_short height,
+			  u_short line_length);
+static void clgen_RectFill (struct clgenfb_info *fb_info, u_short x, u_short y,
+			    u_short width, u_short height,
+			    u_char color, u_short line_length);
+
+static void bestclock (long freq, long *best,
+		       long *nom, long *den,
+		       long *div, long maxfreq);
+
+#ifdef CONFIG_PCI
+static struct pci_dev *clgen_pci_dev_get (clgen_board_t *btype);
+static unsigned int clgen_get_memsize (caddr_t regbase);
+static int clgen_pci_setup (struct clgenfb_info *fb_info, clgen_board_t *btype);
+#endif				/* CONFIG_PCI */
+
+#ifdef CLGEN_DEBUG
+static void clgen_dump (void);
+static void clgen_dbg_reg_dump (caddr_t regbase);
+static void clgen_dbg_print_regs (caddr_t regbase, clgen_dbg_reg_class_t reg_class,...);
+static void clgen_dbg_print_byte (const char *name, unsigned char val);
+#endif /* CLGEN_DEBUG */
 
 /*** END   PROTOTYPES ********************************************************/
 /*****************************************************************************/
@@ -292,302 +582,477 @@
 static int opencount = 0;
 
 /*--- Open /dev/fbx ---------------------------------------------------------*/
-int clgenfb_open(struct fb_info *info, int user)
+static int clgenfb_open (struct fb_info *info, int user)
 {
-    MOD_INC_USE_COUNT;
-    if (opencount++ == 0) switch_monitor(1);
-    return 0;
+	MOD_INC_USE_COUNT;
+	if (opencount++ == 0)
+		switch_monitor ((struct clgenfb_info *) info, 1);
+	return 0;
 }
 
 /*--- Close /dev/fbx --------------------------------------------------------*/
-int clgenfb_release(struct fb_info *info, int user)
+static int clgenfb_release (struct fb_info *info, int user)
 {
-    if (--opencount == 0) switch_monitor(0);
-    MOD_DEC_USE_COUNT;
-    return 0;
+	if (--opencount == 0)
+		switch_monitor ((struct clgenfb_info *) info, 0);
+	MOD_DEC_USE_COUNT;
+	return 0;
 }
 
 /*--- handle /dev/fbx ioctl calls ------------------------------------------*/
-int clgenfb_ioctl(struct inode *inode, struct file *file,
-                  unsigned int cmd, unsigned long arg, int con,
-                  struct fb_info *info)
-{
-    printk(">clgenfb_ioctl()\n");
-    /* Nothing exciting here... */
-    printk("<clgenfb_ioctl()\n");
-    return -EINVAL;
+static int clgenfb_ioctl (struct inode *inode, struct file *file,
+		   unsigned int cmd, unsigned long arg, int con,
+		   struct fb_info *info)
+{
+	DPRINTK ("ENTER\n");
+	/* Nothing exciting here... */
+	DPRINTK ("EXIT\n");
+	return -EINVAL;
 }
-
 /**** END   Interface used by the World *************************************/
 /****************************************************************************/
 /**** BEGIN Hardware specific Routines **************************************/
 
-static void clgen_detect(void)
+static void clgen_detect (void)
 {
-    printk(">clgen_detect()\n");
-    printk("<clgen_detect()\n");
+	DPRINTK ("ENTER\n");
+	DPRINTK ("EXIT\n");
 }
 
-static int clgen_encode_fix(struct fb_fix_screeninfo *fix, const void *par,
-			    struct fb_info_gen *info)
+static int clgen_encode_fix (struct fb_fix_screeninfo *fix, const void *par,
+			     struct fb_info_gen *info)
 {
-    struct clgenfb_par  *_par  = (struct clgenfb_par*) par;
-    struct clgenfb_info *_info = (struct clgenfb_info*)info;
-    
-    memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-    strcpy(fix->id, clgenfb_name);
-	
-    fix->smem_start	= (char*)_info->fbmem_phys;
-    
-    /* monochrome: only 1 memory plane */
-    /* 8 bit and above: Use whole memory area */
-    fix->smem_len       = _par->var.bits_per_pixel == 1 ? _info->size / 4 
-							: _info->size;
-    fix->type		= _par->type;
-    fix->type_aux	= 0;
-    fix->visual		= _par->visual;
-    fix->xpanstep	= 1;
-    fix->ypanstep	= 1;
-    fix->ywrapstep	= 0;
-    fix->line_length	= _par->line_length;
-    fix->mmio_start	= (char *)_info->fbregs_phys;
-    fix->mmio_len	= 0x10000;
-    fix->accel		= FB_ACCEL_NONE;
+	struct clgenfb_par *_par = (struct clgenfb_par *) par;
+	struct clgenfb_info *_info = (struct clgenfb_info *) info;
+
+	DPRINTK ("ENTER\n");
+
+	memset (fix, 0, sizeof (struct fb_fix_screeninfo));
+	strcpy (fix->id, clgenfb_name);
+
+	if (_info->btype == BT_GD5480) {
+		/* Select proper byte-swapping aperture */
+		switch (_par->var.bits_per_pixel) {
+		case 1:
+		case 8:
+			fix->smem_start = (char *) _info->fbmem_phys;
+			break;
+		case 16:
+			fix->smem_start = (char *) _info->fbmem_phys + 1 * MB_;
+			break;
+		case 24:
+		case 32:
+			fix->smem_start = (char *) _info->fbmem_phys + 2 * MB_;
+			break;
+		}
+	} else {
+		fix->smem_start = (char *) _info->fbmem_phys;
+	}
 
-    return 0;
+	/* monochrome: only 1 memory plane */
+	/* 8 bit and above: Use whole memory area */
+	fix->smem_len = _par->var.bits_per_pixel == 1 ? _info->size / 4
+	    : _info->size;
+	fix->type = _par->type;
+	fix->type_aux = 0;
+	fix->visual = _par->visual;
+	fix->xpanstep = 1;
+	fix->ypanstep = 1;
+	fix->ywrapstep = 0;
+	fix->line_length = _par->line_length;
+
+	/* FIXME: map region at 0xB8000 if available, fill in here */
+	fix->mmio_start = (char *) NULL;
+	fix->mmio_len = 0;
+	fix->accel = FB_ACCEL_NONE;
+
+	DPRINTK ("EXIT\n");
+	return 0;
 }
 
-static int clgen_decode_var(const struct fb_var_screeninfo *var, void *par,
-			    struct fb_info_gen *info)
-{
-    long freq;
-    int  xres, hfront, hsync, hback;
-    int  yres, vfront, vsync, vback;
-    int  nom,den; /* translyting from pixels->bytes */
-    int  i;
-    static struct
-    {
-	int xres,yres;
-    }
-    modes[] = { {1600,1280}, {1280,1024}, {1024,768}, 
-		{800,600}, {640,480}, {-1,-1} };
-
-    struct clgenfb_par *_par = (struct clgenfb_par *)par;
-
-    fb_info = (struct clgenfb_info*)info;
-    printk("clgen_decode_var()\n");
-
-    printk("Requested: %dx%dx%d\n", var->xres,var->yres,var->bits_per_pixel);
-    printk("  virtual: %dx%d\n", var->xres_virtual,var->yres_virtual);
-    printk("   offset: (%d,%d)\n", var->xoffset, var->yoffset);
-    printk("grayscale: %d\n", var->grayscale);
-#if 0
-    printk(" activate: 0x%x\n", var->activate);
-    printk(" pixclock: %d\n", var->pixclock);
-    printk("  htiming: %d;%d  %d\n", var->left_margin,var->right_margin,var->hsync_len);
-    printk("  vtiming: %d;%d  %d\n", var->upper_margin,var->lower_margin,var->vsync_len);
-    printk("     sync: 0x%x\n", var->sync);
-    printk("    vmode: 0x%x\n", var->vmode);
-#endif
-
-    _par->var = *var;
-
-    switch (var->bits_per_pixel)
-    {
-    case 1:  nom = 4; den = 8; break;   /* 8 pixel per byte, only 1/4th of mem usable */
-    case 8:  nom = 1; den = 1; break;   /* 1 pixel == 1 byte */
-    case 16: nom = 2; den = 1; break;   /* 2 bytes per pixel */
-    case 24: nom = 3; den = 1; break;   /* 3 bytes per pixel */
-    case 32: nom = 4; den = 1; break;	/* 4 bytes per pixel */
-    default:
-	printk("clgen: mode %dx%dx%d rejected...color depth not supported.\n",
-		var->xres, var->yres, var->bits_per_pixel);
-	return -EINVAL;
-    }
 
-    if (_par->var.xres*nom/den * _par->var.yres > fb_info->size)
-    {
-	printk("clgen: mode %dx%dx%d rejected...resolution too high to fit into video memory!\n",
-		var->xres, var->yres, var->bits_per_pixel);
-	return -EINVAL;
-    }
-    
-    /* use highest possible virtual resolution */
-    if (_par->var.xres_virtual == -1 &&
-	_par->var.yres_virtual == -1)
-    {
-	printk("clgen: using maximum available virtual resolution\n");
-	for (i=0; modes[i].xres != -1; i++)
-	{
-	    if (modes[i].xres*nom/den * modes[i].yres < fb_info->size/2)
+
+/* Get a good MCLK value */
+static long clgen_get_mclk (long freq, int bpp, long *div)
+{
+	long mclk;
+
+	assert (div != NULL);
+
+	/* Calculate MCLK, in case VCLK is high enough to require > 50MHz.
+	 * Assume a 64-bit data path for now.  The formula is: 
+	 * ((B * PCLK * 2)/W) * 1.2
+	 * B = bytes per pixel, PCLK = pixclock, W = data width in bytes */
+	mclk = ((bpp / 8) * freq * 2) / 4;
+	mclk = (mclk * 12) / 10;
+	if (mclk < 50000)
+		mclk = 50000;
+	DPRINTK ("Use MCLK of %ld kHz\n", mclk);
+
+	/* Calculate value for SR1F.  Multiply by 2 so we can round up. */
+	mclk = ((mclk * 16) / 14318);
+	mclk = (mclk + 1) / 2;
+	DPRINTK ("Set SR1F[5:0] to 0x%lx\n", mclk);
+
+	/* Determine if we should use MCLK instead of VCLK, and if so, what we
+	   * should divide it by to get VCLK */
+	switch (freq) {
+	case 24751 ... 25249:
+		*div = 2;
+		DPRINTK ("Using VCLK = MCLK/2\n");
+		break;
+	case 49501 ... 50499:
+		*div = 1;
+		DPRINTK ("Using VCLK = MCLK\n");
+		break;
+	default:
+		*div = 0;
 		break;
 	}
-	if (modes[i].xres == -1)
+
+	return mclk;
+}
+
+static int clgen_decode_var (const struct fb_var_screeninfo *var, void *par,
+			     struct fb_info_gen *info)
+{
+	long freq;
+	long maxclock;
+	int xres, hfront, hsync, hback;
+	int yres, vfront, vsync, vback;
+	int nom, den;		/* translyting from pixels->bytes */
+	int i;
+	static struct {
+		int xres, yres;
+	} modes[] = { {
+			1600, 1280
+	}, {
+		1280, 1024
+	}, {
+		1024, 768
+	},
 	{
-	    printk("clgen: could not find a virtual resolution that fits into video memory!!\n");
-	    return -EINVAL;
-	}
-	_par->var.xres_virtual = modes[i].xres;
-	_par->var.yres_virtual = modes[i].yres;
+		800, 600
+	}, {
+		640, 480
+	}, {
+		-1, -1
+	}
+	};
+
+	struct clgenfb_par *_par = (struct clgenfb_par *) par;
+	struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
+
+	assert (var != NULL);
+	assert (par != NULL);
+	assert (info != NULL);
+
+	DPRINTK ("ENTER\n");
+
+	DPRINTK ("Requested: %dx%dx%d\n", var->xres, var->yres, var->bits_per_pixel);
+	DPRINTK ("  virtual: %dx%d\n", var->xres_virtual, var->yres_virtual);
+	DPRINTK ("   offset: (%d,%d)\n", var->xoffset, var->yoffset);
+	DPRINTK ("grayscale: %d\n", var->grayscale);
+
+	memset (par, 0, sizeof (struct clgenfb_par));
+
+	_par->var = *var;
+
+	switch (var->bits_per_pixel) {
+	case 1:
+		nom = 4;
+		den = 8;
+		break;		/* 8 pixel per byte, only 1/4th of mem usable */
+	case 2 ... 8:
+		_par->var.bits_per_pixel = 8;
+		nom = 1;
+		den = 1;
+		break;		/* 1 pixel == 1 byte */
+	case 9 ... 16:
+		_par->var.bits_per_pixel = 16;
+		nom = 2;
+		den = 1;
+		break;		/* 2 bytes per pixel */
+	case 17 ... 24:
+		_par->var.bits_per_pixel = 24;
+		nom = 3;
+		den = 1;
+		break;		/* 3 bytes per pixel */
+	case 25 ... 32:
+		_par->var.bits_per_pixel = 32;
+		nom = 4;
+		den = 1;
+		break;		/* 4 bytes per pixel */
+	default:
+		printk ("clgen: mode %dx%dx%d rejected...color depth not supported.\n",
+			var->xres, var->yres, var->bits_per_pixel);
+		DPRINTK ("EXIT - EINVAL error\n");
+		return -EINVAL;
+	}
+
+	if (_par->var.xres * nom / den * _par->var.yres > fb_info->size) {
+		printk ("clgen: mode %dx%dx%d rejected...resolution too high to fit into video memory!\n",
+			var->xres, var->yres, var->bits_per_pixel);
+		DPRINTK ("EXIT - EINVAL error\n");
+		return -EINVAL;
+	}
+	/* use highest possible virtual resolution */
+	if (_par->var.xres_virtual == -1 &&
+	    _par->var.yres_virtual == -1) {
+		printk ("clgen: using maximum available virtual resolution\n");
+		for (i = 0; modes[i].xres != -1; i++) {
+			if (modes[i].xres * nom / den * modes[i].yres < fb_info->size / 2)
+				break;
+		}
+		if (modes[i].xres == -1) {
+			printk ("clgen: could not find a virtual resolution that fits into video memory!!\n");
+			DPRINTK ("EXIT - EINVAL error\n");
+			return -EINVAL;
+		}
+		_par->var.xres_virtual = modes[i].xres;
+		_par->var.yres_virtual = modes[i].yres;
 
-	printk("clgen: virtual resolution set to maximum of %dx%d\n",
-		_par->var.xres_virtual, _par->var.yres_virtual);
-    }
-    else if (_par->var.xres_virtual == -1)
-    {
-    }
-    else if (_par->var.yres_virtual == -1)
-    {
-    }
+		printk ("clgen: virtual resolution set to maximum of %dx%d\n",
+			_par->var.xres_virtual, _par->var.yres_virtual);
+	} else if (_par->var.xres_virtual == -1) {
+		/* FIXME: maximize X virtual resolution only */
+	} else if (_par->var.yres_virtual == -1) {
+		/* FIXME: maximize Y virtual resolution only */
+	}
+	if (_par->var.xoffset < 0)
+		_par->var.xoffset = 0;
+	if (_par->var.yoffset < 0)
+		_par->var.yoffset = 0;
+
+	/* truncate xoffset and yoffset to maximum if too high */
+	if (_par->var.xoffset > _par->var.xres_virtual - _par->var.xres)
+		_par->var.xoffset = _par->var.xres_virtual - _par->var.xres - 1;
+
+	if (_par->var.yoffset > _par->var.yres_virtual - _par->var.yres)
+		_par->var.yoffset = _par->var.yres_virtual - _par->var.yres - 1;
+
+	switch (var->bits_per_pixel) {
+	case 1:
+		_par->line_length = _par->var.xres_virtual / 8;
+		_par->visual = FB_VISUAL_MONO10;
+		break;
 
-    if (_par->var.xoffset < 0) _par->var.xoffset = 0;
-    if (_par->var.yoffset < 0) _par->var.yoffset = 0;
-	
-    /* truncate xoffset and yoffset to maximum if too high */
-    if (_par->var.xoffset > _par->var.xres_virtual-_par->var.xres)
-	_par->var.xoffset = _par->var.xres_virtual-_par->var.xres -1;
-
-    if (_par->var.yoffset > _par->var.yres_virtual-_par->var.yres)
-	_par->var.yoffset = _par->var.yres_virtual-_par->var.yres -1;
-
-    switch (var->bits_per_pixel)
-    {
-    case 1:
-	_par->line_length	= _par->var.xres_virtual / 8;
-	_par->visual		= FB_VISUAL_MONO10;
-	break;
-
-    case 8:
-	_par->line_length 	= _par->var.xres_virtual;
-	_par->visual		= FB_VISUAL_PSEUDOCOLOR;
-	_par->var.red.offset    = 0;
-	_par->var.red.length    = 6;
-	_par->var.green.offset  = 0;
-	_par->var.green.length  = 6;
-	_par->var.blue.offset   = 0;
-	_par->var.blue.length   = 6;
-	break;
-
-    case 16:
-	_par->line_length	= _par->var.xres_virtual * 2;
-	_par->visual		= FB_VISUAL_DIRECTCOLOR;
-	_par->var.red.offset    = 10;
-	_par->var.red.length    = 5;
-	_par->var.green.offset  = 5;
-	_par->var.green.length  = 5;
-	_par->var.blue.offset   = 0;
-	_par->var.blue.length   = 5;
-	break;
-
-    case 24:
-	_par->line_length	= _par->var.xres_virtual * 3;
-	_par->visual		= FB_VISUAL_DIRECTCOLOR;
-	_par->var.red.offset    = 16;
-	_par->var.red.length    = 8;
-	_par->var.green.offset  = 8;
-	_par->var.green.length  = 8;
-	_par->var.blue.offset   = 0;
-	_par->var.blue.length   = 8;
-	break;
-
-    case 32:
-	_par->line_length	= _par->var.xres_virtual * 4;
-	_par->visual		= FB_VISUAL_DIRECTCOLOR;
-	_par->var.red.offset    = 16;
-	_par->var.red.length    = 8;
-	_par->var.green.offset  = 8;
-	_par->var.green.length  = 8;
-	_par->var.blue.offset   = 0;
-	_par->var.blue.length   = 8;
-	break;
-    }
-    _par->var.red.msb_right = 0;
-    _par->var.green.msb_right = 0;
-    _par->var.blue.msb_right = 0;
-    _par->var.transp.offset = 0;
-    _par->var.transp.length = 0;
-    _par->var.transp.msb_right = 0;
-
-    _par->type		= FB_TYPE_PACKED_PIXELS;
-
-    /* convert from ps to kHz */
-    freq = 1000000000 / var->pixclock;
-
-    DEBUG printk("desired pixclock: %ld kHz\n", freq);	
-
-    /* the SD64/P4 have a higher max. videoclock */
-    bestclock(freq, &_par->freq, &_par->nom, &_par->den, &_par->div, 
-		fb_info->btype == BT_SD64 || fb_info->btype == BT_PICASSO4
-		? 140000 : 90000);
-
-    DEBUG printk("Best possible values for given frequency: best: %ld kHz  nom: %ld  den: %ld  div: %ld\n", 
-		 _par->freq, _par->nom, _par->den, _par->div);
-
-    xres   = _par->var.xres;
-    hfront = _par->var.right_margin;
-    hsync  = _par->var.hsync_len;
-    hback  = _par->var.left_margin;
-
-    yres   = _par->var.yres;
-    vfront = _par->var.lower_margin;
-    vsync  = _par->var.vsync_len;
-    vback  = _par->var.upper_margin;
-    
-    if (_par->var.vmode & FB_VMODE_DOUBLE)
-    {
-    	yres   *= 2;
-    	vfront *= 2;
-    	vsync  *= 2;
-    	vback  *= 2;
-    }
-    else if (_par->var.vmode & FB_VMODE_INTERLACED)
-    {
-    	yres   = ++yres   / 2;
-    	vfront = ++vfront / 2;
-    	vsync  = ++vsync  / 2;
-    	vback  = ++vback  / 2;
-    }
-
-    _par->HorizRes        = xres;
-    _par->HorizTotal      = (xres + hfront + hsync + hback)/8 - 5;
-    _par->HorizDispEnd    = xres/8 - 1;
-    _par->HorizBlankStart = xres/8;
-    _par->HorizBlankEnd   = _par->HorizTotal+5; /* does not count with "-5" */
-    _par->HorizSyncStart  = (xres + hfront)/8 + 1;
-    _par->HorizSyncEnd    = (xres + hfront + hsync)/8 + 1;
-
-    _par->VertRes         = yres;
-    _par->VertTotal       = yres + vfront + vsync + vback -2;
-    _par->VertDispEnd     = yres - 1;
-    _par->VertBlankStart  = yres;
-    _par->VertBlankEnd    = _par->VertTotal;
-    _par->VertSyncStart   = yres + vfront - 1;
-    _par->VertSyncEnd     = yres + vfront + vsync - 1;
-
-    if (_par->VertTotal >= 1024)
-    {
-	printk(KERN_WARNING "clgen: ERROR: VerticalTotal >= 1024; special treatment required! (TODO)\n");
-	return -EINVAL;
-    }
+	case 8:
+		_par->line_length = _par->var.xres_virtual;
+		_par->visual = FB_VISUAL_PSEUDOCOLOR;
+		_par->var.red.offset = 0;
+		_par->var.red.length = 6;
+		_par->var.green.offset = 0;
+		_par->var.green.length = 6;
+		_par->var.blue.offset = 0;
+		_par->var.blue.length = 6;
+		break;
+
+	case 16:
+		_par->line_length = _par->var.xres_virtual * 2;
+		_par->visual = FB_VISUAL_DIRECTCOLOR;
+#ifdef CONFIG_PREP
+		_par->var.red.offset = 2;
+		_par->var.green.offset = -3;
+		_par->var.blue.offset = 8;
+#else
+		_par->var.red.offset = 10;
+		_par->var.green.offset = 5;
+		_par->var.blue.offset = 0;
+#endif
+		_par->var.red.length = 5;
+		_par->var.green.length = 5;
+		_par->var.blue.length = 5;
+		break;
+
+	case 24:
+		_par->line_length = _par->var.xres_virtual * 3;
+		_par->visual = FB_VISUAL_DIRECTCOLOR;
+#ifdef CONFIG_PREP
+		_par->var.red.offset = 8;
+		_par->var.green.offset = 16;
+		_par->var.blue.offset = 24;
+#else
+		_par->var.red.offset = 16;
+		_par->var.green.offset = 8;
+		_par->var.blue.offset = 0;
+#endif
+		_par->var.red.length = 8;
+		_par->var.green.length = 8;
+		_par->var.blue.length = 8;
+		break;
+
+	case 32:
+		_par->line_length = _par->var.xres_virtual * 4;
+		_par->visual = FB_VISUAL_DIRECTCOLOR;
+#ifdef CONFIG_PREP
+		_par->var.red.offset = 8;
+		_par->var.green.offset = 16;
+		_par->var.blue.offset = 24;
+#else
+		_par->var.red.offset = 16;
+		_par->var.green.offset = 8;
+		_par->var.blue.offset = 0;
+#endif
+		_par->var.red.length = 8;
+		_par->var.green.length = 8;
+		_par->var.blue.length = 8;
+		break;
+
+	default:
+		assert (0);
+		/* should never occur */
+		break;
+	}
+
+	_par->var.red.msb_right =
+	    _par->var.green.msb_right =
+	    _par->var.blue.msb_right =
+	    _par->var.transp.offset =
+	    _par->var.transp.length =
+	    _par->var.transp.msb_right = 0;
+
+	_par->type = FB_TYPE_PACKED_PIXELS;
+
+	/* convert from ps to kHz */
+	freq = 1000000000 / var->pixclock;
+
+	DPRINTK ("desired pixclock: %ld kHz\n", freq);
+
+	maxclock = clgen_board_info[fb_info->btype].maxclock;
+	_par->multiplexing = 0;
+
+	/* If the frequency is greater than we can support, we might be able
+	 * to use multiplexing for the video mode */
+	if (freq > maxclock) {
+		switch (fb_info->btype) {
+		case BT_ALPINE:
+		case BT_GD5480:
+			_par->multiplexing = 1;
+			break;
+
+		default:
+			printk (KERN_WARNING "clgen: ERROR: Frequency greater than maxclock (%ld kHz)\n", maxclock);
+			DPRINTK ("EXIT - return -EINVAL\n");
+			return -EINVAL;
+		}
+	}
+#if 0
+	/* TODO: If we have a 1MB 5434, we need to put ourselves in a mode where
+	 * the VCLK is double the pixel clock. */
+	switch (var->bits_per_pixel) {
+	case 16:
+	case 32:
+		if (_par->HorizRes <= 800)
+			freq /= 2;	/* Xbh has this type of clock for 32-bit */
+		break;
+	}
+#endif
 
-    return 0;
+	bestclock (freq, &_par->freq, &_par->nom, &_par->den, &_par->div,
+		   maxclock);
+	_par->mclk = clgen_get_mclk (freq, var->bits_per_pixel, &_par->divMCLK);
+
+	xres = _par->var.xres;
+	hfront = _par->var.right_margin;
+	hsync = _par->var.hsync_len;
+	hback = _par->var.left_margin;
+
+	yres = _par->var.yres;
+	vfront = _par->var.lower_margin;
+	vsync = _par->var.vsync_len;
+	vback = _par->var.upper_margin;
+
+	if (_par->var.vmode & FB_VMODE_DOUBLE) {
+		yres *= 2;
+		vfront *= 2;
+		vsync *= 2;
+		vback *= 2;
+	} else if (_par->var.vmode & FB_VMODE_INTERLACED) {
+		yres = ++yres / 2;
+		vfront = ++vfront / 2;
+		vsync = ++vsync / 2;
+		vback = ++vback / 2;
+	}
+	_par->HorizRes = xres;
+	_par->HorizTotal = (xres + hfront + hsync + hback) / 8 - 5;
+	_par->HorizDispEnd = xres / 8 - 1;
+	_par->HorizBlankStart = xres / 8;
+	_par->HorizBlankEnd = _par->HorizTotal + 5;	/* does not count with "-5" */
+	_par->HorizSyncStart = (xres + hfront) / 8 + 1;
+	_par->HorizSyncEnd = (xres + hfront + hsync) / 8 + 1;
+
+	_par->VertRes = yres;
+	_par->VertTotal = yres + vfront + vsync + vback - 2;
+	_par->VertDispEnd = yres - 1;
+	_par->VertBlankStart = yres;
+	_par->VertBlankEnd = _par->VertTotal;
+	_par->VertSyncStart = yres + vfront - 1;
+	_par->VertSyncEnd = yres + vfront + vsync - 1;
+
+	if (_par->VertRes >= 1024) {
+		_par->VertTotal /= 2;
+		_par->VertSyncStart /= 2;
+		_par->VertSyncEnd /= 2;
+		_par->VertDispEnd /= 2;
+	}
+	if (_par->multiplexing) {
+		_par->HorizTotal /= 2;
+		_par->HorizSyncStart /= 2;
+		_par->HorizSyncEnd /= 2;
+		_par->HorizDispEnd /= 2;
+	}
+	if (_par->VertRes >= 1280) {
+		printk (KERN_WARNING "clgen: ERROR: VerticalTotal >= 1280; special treatment required! (TODO)\n");
+		DPRINTK ("EXIT - EINVAL error\n");
+		return -EINVAL;
+	}
+	DPRINTK ("EXIT\n");
+	return 0;
 }
 
 
-static int clgen_encode_var(struct fb_var_screeninfo *var, const void *par,
-			    struct fb_info_gen *info)
+static int clgen_encode_var (struct fb_var_screeninfo *var, const void *par,
+			     struct fb_info_gen *info)
 {
-    *var = ((struct clgenfb_par*)par)->var;
-    return 0;
+	DPRINTK ("ENTER\n");
+
+	*var = ((struct clgenfb_par *) par)->var;
+
+	DPRINTK ("EXIT\n");
+	return 0;
 }
 
 /* get current video mode */
-static void clgen_get_par(void *par, struct fb_info_gen *info)
+static void clgen_get_par (void *par, struct fb_info_gen *info)
 {
-    struct clgenfb_par *_par  = (struct clgenfb_par*)par;
-    struct clgenfb_info*_info = (struct clgenfb_info*)fb_info;
+	struct clgenfb_par *_par = (struct clgenfb_par *) par;
+	struct clgenfb_info *_info = (struct clgenfb_info *) info;
+
+	DPRINTK ("ENTER\n");
 
-    *_par = _info->currentmode;   
+	*_par = _info->currentmode;
+
+	DPRINTK ("EXIT\n");
+}
+
+static void clgen_set_mclk (const struct clgenfb_info *fb_info, int val, int div)
+{
+	assert (fb_info != NULL);
+
+	if (div == 2) {
+		/* VCLK = MCLK/2 */
+		unsigned char old = vga_rseq (fb_info->regs, CL_SEQR1E);
+		vga_wseq (fb_info->regs, CL_SEQR1E, old | 0x1);
+		vga_wseq (fb_info->regs, CL_SEQR1F, 0x40 | (val & 0x3f));
+	} else if (div == 1) {
+		/* VCLK = MCLK */
+		unsigned char old = vga_rseq (fb_info->regs, CL_SEQR1E);
+		vga_wseq (fb_info->regs, CL_SEQR1E, old & ~0x1);
+		vga_wseq (fb_info->regs, CL_SEQR1F, 0x40 | (val & 0x3f));
+	} else {
+		vga_wseq (fb_info->regs, CL_SEQR1F, val & 0x3f);
+	}
 }
 
 /*************************************************************************
@@ -595,1072 +1060,1672 @@
 
 	actually writes the values for a new video mode into the hardware,
 **************************************************************************/
-static void clgen_set_par(const void *par, struct fb_info_gen *info)
+static void clgen_set_par (const void *par, struct fb_info_gen *info)
 {
-    unsigned char tmp;
-    int offset = 0;
-    struct clgenfb_par *_par = (struct clgenfb_par*)par;
-
-    printk(KERN_INFO">clgen_set_par()\n");
-    printk(KERN_INFO"Requested mode: %dx%dx%d\n",
-		    _par->var.xres, _par->var.yres, _par->var.bits_per_pixel);
-    printk(KERN_INFO"pixclock: %d\n", _par->var.pixclock);
-    
-    fb_info = (struct clgenfb_info *)info;
-
-    /* unlock register CRT0..CRT7 */
-    WCrt(CRT11, 0x20); /* previously: 0x00) */
-
-    /* if DEBUG is set, all parameters get output before writing */
-    DEBUG printk("CRT0: %ld\n", _par->HorizTotal); 
-    WCrt(CRT0, _par->HorizTotal);
-
-    DEBUG printk("CRT1: %ld\n", _par->HorizDispEnd); 
-    WCrt(CRT1, _par->HorizDispEnd);
-
-    DEBUG printk("CRT2: %ld\n", _par->HorizBlankStart); 
-    WCrt(CRT2, _par->HorizBlankStart);
-
-    DEBUG printk("CRT3: 128+%ld\n", _par->HorizBlankEnd % 32); /*  + 128: Compatible read */
-    WCrt(CRT3, 128 + (_par->HorizBlankEnd % 32));
-
-    DEBUG printk("CRT4: %ld\n", _par->HorizSyncStart);
-    WCrt(CRT4, _par->HorizSyncStart);
-
-    tmp = _par->HorizSyncEnd % 32;
-    if (_par->HorizBlankEnd & 32)	
-    	tmp += 128;
-    DEBUG printk("CRT5: %d\n", tmp); 
-    WCrt(CRT5, tmp);
-
-    DEBUG printk("CRT6: %ld\n", _par->VertTotal & 0xff); 
-    WCrt(CRT6, (_par->VertTotal & 0xff));
-
-    tmp = 16;  /* LineCompare bit #9 */
-    if (_par->VertTotal      & 256) tmp |= 1;
-    if (_par->VertDispEnd    & 256) tmp |= 2;
-    if (_par->VertSyncStart  & 256) tmp |= 4;
-    if (_par->VertBlankStart & 256) tmp |= 8;
-    if (_par->VertTotal      & 512) tmp |= 32;
-    if (_par->VertDispEnd    & 512) tmp |= 64;
-    if (_par->VertSyncStart  & 512) tmp |= 128;
-    DEBUG printk("CRT7: %d\n", tmp);
-    WCrt(CRT7, tmp);
-
-    tmp = 0x40; /* LineCompare bit #8 */
-    if (_par->VertBlankStart & 512)		tmp |= 0x20;
-    if (_par->var.vmode & FB_VMODE_DOUBLE)	tmp |= 0x80;
-    DEBUG printk("CRT9: %d\n", tmp);
-    WCrt(CRT9, tmp);
-
-    DEBUG printk("CRT10: %ld\n", _par->VertSyncStart & 0xff);
-    WCrt(CRT10, (_par->VertSyncStart & 0xff));
-
-    DEBUG printk("CRT11: 64+32+%ld\n", _par->VertSyncEnd % 16);
-    WCrt(CRT11, (_par->VertSyncEnd % 16 + 64 + 32));
-
-    DEBUG printk("CRT12: %ld\n", _par->VertDispEnd & 0xff);
-    WCrt(CRT12, (_par->VertDispEnd & 0xff));
-
-    DEBUG printk("CRT15: %ld\n", _par->VertBlankStart & 0xff);
-    WCrt(CRT15, (_par->VertBlankStart & 0xff));
-
-    DEBUG printk("CRT16: %ld\n", _par->VertBlankEnd & 0xff);
-    WCrt(CRT16, (_par->VertBlankEnd & 0xff));
-
-    DEBUG printk("CRT18: 0xff\n");
-    WCrt(CRT18, 0xff);
-
-    tmp = 0;
-    if (_par->var.vmode & FB_VMODE_INTERLACED)	tmp |= 1;
-    if (_par->HorizBlankEnd & 64)		tmp |= 16;
-    if (_par->HorizBlankEnd & 128)		tmp |= 32;
-    if (_par->VertBlankEnd  & 256)		tmp |= 64;
-    if (_par->VertBlankEnd  & 512)		tmp |= 128;
-    
-    DEBUG printk("CRT1a: %d\n", tmp);
-    WCrt(CRT1A, tmp);
-
-    /* set VCLK0 */
-    /* hardware RefClock: 14.31818 MHz */
-    /* formula: VClk = (OSC * N) / (D * (1+P)) */
-    /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */
-
-    WSeq(SEQRB, _par->nom);
-    tmp = _par->den<<1; 
-    if (_par->div != 0) tmp |= 1;
-
-    if (fb_info->btype == BT_SD64)
-    	tmp |= 0x80; /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
-    
-    WSeq(SEQR1B, tmp);
-
-    WCrt(CRT17, 0xc3); /* mode control: CRTC enable, ROTATE(?), 16bit address wrap, no compat. */
-
-/* HAEH?	WCrt(CRT11, 0x20);  * previously: 0x00  unlock CRT0..CRT7 */
-
-    /* don't know if it would hurt to also program this if no interlaced */
-    /* mode is used, but I feel better this way.. :-) */
-    if (_par->var.vmode & FB_VMODE_INTERLACED)
-    	WCrt(CRT19, _par->HorizTotal / 2);
-    else
-    	WCrt(CRT19, 0x00);	/* interlace control */
-
-    WSeq(SEQR3, 0);
-
-    /* adjust horizontal/vertical sync type (low/high) */
-    tmp = 0x03; /* enable display memory & CRTC I/O address for color mode */
-    if (_par->var.sync & FB_SYNC_HOR_HIGH_ACT)  tmp |= 0x40;
-    if (_par->var.sync & FB_SYNC_VERT_HIGH_ACT) tmp |= 0x80;
-    WGen(MISC_W, tmp);
-
-    WCrt(CRT8,    0);      /* Screen A Preset Row-Scan register */
-    WCrt(CRTA,    0);      /* text cursor on and start line */
-    WCrt(CRTB,   31);      /* text cursor end line */
-
-    /* programming for different color depths */
-    if (_par->var.bits_per_pixel == 1)
-    {
-	DEBUG printk(KERN_INFO "clgen: preparing for 1 bit deep display\n");
-#if 0
-    	/* restore first 2 color registers for mono mode */
-    	WClut( 0, 0x00, 0x00, 0x00);  /* background: black */
-	WClut( 1, 0x3f, 0x3f, 0x3f);  /* foreground: white */
+	unsigned char tmp;
+	int offset = 0;
+	struct clgenfb_par *_par = (struct clgenfb_par *) par;
+	struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
+
+	DPRINTK ("ENTER\n");
+	DPRINTK ("Requested mode: %dx%dx%d\n",
+	       _par->var.xres, _par->var.yres, _par->var.bits_per_pixel);
+	DPRINTK ("pixclock: %d\n", _par->var.pixclock);
+
+
+	/* unlock register VGA_CRTC_H_TOTAL..CRT7 */
+	vga_wcrt (fb_info->regs, VGA_CRTC_V_SYNC_END, 0x20);	/* previously: 0x00) */
+
+	/* if debugging is enabled, all parameters get output before writing */
+	DPRINTK ("CRT0: %ld\n", _par->HorizTotal);
+	vga_wcrt (fb_info->regs, VGA_CRTC_H_TOTAL, _par->HorizTotal);
+
+	DPRINTK ("CRT1: %ld\n", _par->HorizDispEnd);
+	vga_wcrt (fb_info->regs, VGA_CRTC_H_DISP, _par->HorizDispEnd);
+
+	DPRINTK ("CRT2: %ld\n", _par->HorizBlankStart);
+	vga_wcrt (fb_info->regs, VGA_CRTC_H_BLANK_START, _par->HorizBlankStart);
+
+	DPRINTK ("CRT3: 128+%ld\n", _par->HorizBlankEnd % 32);	/*  + 128: Compatible read */
+	vga_wcrt (fb_info->regs, VGA_CRTC_H_BLANK_END, 128 + (_par->HorizBlankEnd % 32));
+
+	DPRINTK ("CRT4: %ld\n", _par->HorizSyncStart);
+	vga_wcrt (fb_info->regs, VGA_CRTC_H_SYNC_START, _par->HorizSyncStart);
+
+	tmp = _par->HorizSyncEnd % 32;
+	if (_par->HorizBlankEnd & 32)
+		tmp += 128;
+	DPRINTK ("CRT5: %d\n", tmp);
+	vga_wcrt (fb_info->regs, VGA_CRTC_H_SYNC_END, tmp);
+
+	DPRINTK ("CRT6: %ld\n", _par->VertTotal & 0xff);
+	vga_wcrt (fb_info->regs, VGA_CRTC_V_TOTAL, (_par->VertTotal & 0xff));
+
+	tmp = 16;		/* LineCompare bit #9 */
+	if (_par->VertTotal & 256)
+		tmp |= 1;
+	if (_par->VertDispEnd & 256)
+		tmp |= 2;
+	if (_par->VertSyncStart & 256)
+		tmp |= 4;
+	if (_par->VertBlankStart & 256)
+		tmp |= 8;
+	if (_par->VertTotal & 512)
+		tmp |= 32;
+	if (_par->VertDispEnd & 512)
+		tmp |= 64;
+	if (_par->VertSyncStart & 512)
+		tmp |= 128;
+	DPRINTK ("CRT7: %d\n", tmp);
+	vga_wcrt (fb_info->regs, VGA_CRTC_OVERFLOW, tmp);
+
+	tmp = 0x40;		/* LineCompare bit #8 */
+	if (_par->VertBlankStart & 512)
+		tmp |= 0x20;
+	if (_par->var.vmode & FB_VMODE_DOUBLE)
+		tmp |= 0x80;
+	DPRINTK ("CRT9: %d\n", tmp);
+	vga_wcrt (fb_info->regs, VGA_CRTC_MAX_SCAN, tmp);
+
+	DPRINTK ("CRT10: %ld\n", _par->VertSyncStart & 0xff);
+	vga_wcrt (fb_info->regs, VGA_CRTC_V_SYNC_START, (_par->VertSyncStart & 0xff));
+
+	DPRINTK ("CRT11: 64+32+%ld\n", _par->VertSyncEnd % 16);
+	vga_wcrt (fb_info->regs, VGA_CRTC_V_SYNC_END, (_par->VertSyncEnd % 16 + 64 + 32));
+
+	DPRINTK ("CRT12: %ld\n", _par->VertDispEnd & 0xff);
+	vga_wcrt (fb_info->regs, VGA_CRTC_V_DISP_END, (_par->VertDispEnd & 0xff));
+
+	DPRINTK ("CRT15: %ld\n", _par->VertBlankStart & 0xff);
+	vga_wcrt (fb_info->regs, VGA_CRTC_V_BLANK_START, (_par->VertBlankStart & 0xff));
+
+	DPRINTK ("CRT16: %ld\n", _par->VertBlankEnd & 0xff);
+	vga_wcrt (fb_info->regs, VGA_CRTC_V_BLANK_END, (_par->VertBlankEnd & 0xff));
+
+	DPRINTK ("CRT18: 0xff\n");
+	vga_wcrt (fb_info->regs, VGA_CRTC_LINE_COMPARE, 0xff);
+
+	tmp = 0;
+	if (_par->var.vmode & FB_VMODE_INTERLACED)
+		tmp |= 1;
+	if (_par->HorizBlankEnd & 64)
+		tmp |= 16;
+	if (_par->HorizBlankEnd & 128)
+		tmp |= 32;
+	if (_par->VertBlankEnd & 256)
+		tmp |= 64;
+	if (_par->VertBlankEnd & 512)
+		tmp |= 128;
+
+	DPRINTK ("CRT1a: %d\n", tmp);
+	vga_wcrt (fb_info->regs, CL_CRT1A, tmp);
+
+	/* set VCLK0 */
+	/* hardware RefClock: 14.31818 MHz */
+	/* formula: VClk = (OSC * N) / (D * (1+P)) */
+	/* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */
+
+	vga_wseq (fb_info->regs, CL_SEQRB, _par->nom);
+	tmp = _par->den << 1;
+	if (_par->div != 0)
+		tmp |= 1;
+
+	if ((fb_info->btype == BT_SD64) ||
+	    (fb_info->btype == BT_ALPINE) ||
+	    (fb_info->btype == BT_GD5480))
+		tmp |= 0x80;	/* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
+
+	DPRINTK ("CL_SEQR1B: %ld\n", (long) tmp);
+	vga_wseq (fb_info->regs, CL_SEQR1B, tmp);
+
+	if (_par->VertRes >= 1024)
+		/* 1280x1024 */
+		vga_wcrt (fb_info->regs, VGA_CRTC_MODE, 0xc7);
+	else
+		/* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit 
+		 * address wrap, no compat. */
+		vga_wcrt (fb_info->regs, VGA_CRTC_MODE, 0xc3);
+
+/* HAEH?        vga_wcrt (fb_info->regs, VGA_CRTC_V_SYNC_END, 0x20);  * previously: 0x00  unlock VGA_CRTC_H_TOTAL..CRT7 */
+
+	/* don't know if it would hurt to also program this if no interlaced */
+	/* mode is used, but I feel better this way.. :-) */
+	if (_par->var.vmode & FB_VMODE_INTERLACED)
+		vga_wcrt (fb_info->regs, VGA_CRTC_REGS, _par->HorizTotal / 2);
+	else
+		vga_wcrt (fb_info->regs, VGA_CRTC_REGS, 0x00);	/* interlace control */
+
+	vga_wseq (fb_info->regs, VGA_SEQ_CHARACTER_MAP, 0);
+
+	/* adjust horizontal/vertical sync type (low/high) */
+	tmp = 0x03;		/* enable display memory & CRTC I/O address for color mode */
+	if (_par->var.sync & FB_SYNC_HOR_HIGH_ACT)
+		tmp |= 0x40;
+	if (_par->var.sync & FB_SYNC_VERT_HIGH_ACT)
+		tmp |= 0x80;
+	WGen (fb_info, VGA_MIS_W, tmp);
+
+	vga_wcrt (fb_info->regs, VGA_CRTC_PRESET_ROW, 0);	/* Screen A Preset Row-Scan register */
+	vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_START, 0);	/* text cursor on and start line */
+	vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_END, 31);	/* text cursor end line */
+
+	/* programming for different color depths */
+	if (_par->var.bits_per_pixel == 1) {
+		DPRINTK ("clgen: preparing for 1 bit deep display\n");
+		vga_wgfx (fb_info->regs, VGA_GFX_MODE, 0);	/* mode register */
+
+		/* Extended Sequencer Mode */
+		switch (fb_info->btype) {
+		case BT_SD64:
+			/* setting the SEQRF on SD64 is not necessary (only during init) */
+			DPRINTK ("(for SD64)\n");
+			vga_wseq (fb_info->regs, CL_SEQR7, 0xf0);
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x1a);		/*  MCLK select */
+			break;
+
+		case BT_PICCOLO:
+			DPRINTK ("(for Piccolo)\n");
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x80);
+/* ### ueberall 0x22? */
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* ##vorher 1c MCLK select */
+			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* evtl d0 bei 1 bit? avoid FIFO underruns..? */
+			break;
+
+		case BT_PICASSO:
+			DPRINTK ("(for Picasso)\n");
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x20);
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* ##vorher 22 MCLK select */
+			vga_wseq (fb_info->regs, CL_SEQRF, 0xd0);	/* ## vorher d0 avoid FIFO underruns..? */
+			break;
+
+		case BT_SPECTRUM:
+			DPRINTK ("(for Spectrum)\n");
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x80);
+/* ### ueberall 0x22? */
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* ##vorher 1c MCLK select */
+			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* evtl d0? avoid FIFO underruns..? */
+			break;
+
+		case BT_PICASSO4:
+			DPRINTK ("(for Picasso 4)\n");
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x20);
+/*                      vga_wseq(fb_info->regs, CL_SEQR1F, 0x1c); */
+/* SEQRF not being set here...  vga_wseq(fb_info->regs, CL_SEQRF, 0xd0); */
+			break;
+
+		case BT_ALPINE:
+			DPRINTK (" (for GD543x)\n");
+			if (_par->multiplexing)
+				vga_wseq (fb_info->regs, CL_SEQR7, 0xa7);
+			else
+				vga_wseq (fb_info->regs, CL_SEQR7, 0xa1);
+			/* We already set SRF and SR1F */
+			break;
+
+		case BT_GD5480:
+			DPRINTK (" (for GD5480)\n");
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x11);
+			/* We already set SRF and SR1F */
+			break;
+
+		default:
+			printk (KERN_WARNING "clgen: unknown Board\n");
+			break;
+		}
+
+		WGen (fb_info, VGA_PEL_MSK, 0x01);	/* pixel mask: pass-through for first plane */
+		if (_par->multiplexing)
+			WHDR (fb_info, 0x4a);	/* hidden dac reg: 1280x1024 */
+		else
+			WHDR (fb_info, 0);	/* hidden dac: nothing */
+		vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x06);	/* memory mode: odd/even, ext. memory */
+		vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0x01);	/* plane mask: only write to first plane */
+		offset = _par->var.xres_virtual / 16;
+	} else if (_par->var.bits_per_pixel == 8) {
+		DPRINTK ("clgen: preparing for 8 bit deep display\n");
+		switch (fb_info->btype) {
+		case BT_SD64:
+			vga_wseq (fb_info->regs, CL_SEQR7, 0xf1);	/* Extended Sequencer Mode: 256c col. mode */
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x1d);		/* MCLK select */
+			break;
+
+		case BT_PICCOLO:
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x81);
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* ### vorher 1c MCLK select */
+			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* Fast Page-Mode writes */
+			break;
+
+		case BT_PICASSO:
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x21);
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* ### vorher 1c MCLK select */
+			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* Fast Page-Mode writes */
+			break;
+
+		case BT_SPECTRUM:
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x81);
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* ### vorher 1c MCLK select */
+			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* Fast Page-Mode writes */
+			break;
+
+		case BT_PICASSO4:
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x21);
+			vga_wseq (fb_info->regs, CL_SEQRF, 0xb8);	/* ### INCOMPLETE!! */
+/*          vga_wseq (fb_info->regs, CL_SEQR1F, 0x1c); */
+			break;
+
+		case BT_ALPINE:
+			DPRINTK (" (for GD543x)\n");
+			if (_par->multiplexing)
+				vga_wseq (fb_info->regs, CL_SEQR7, 0xa7);
+			else
+				vga_wseq (fb_info->regs, CL_SEQR7, 0xa1);
+			clgen_set_mclk (fb_info, _par->mclk, _par->divMCLK);
+			/* We already set SRF and SR1F */
+			break;
+
+		case BT_GD5480:
+			DPRINTK (" (for GD5480)\n");
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x11);
+			/* We already set SRF and SR1F */
+			break;
+
+		default:
+			printk (KERN_WARNING "clgen: unknown Board\n");
+			break;
+		}
+
+		vga_wgfx (fb_info->regs, VGA_GFX_MODE, 64);	/* mode register: 256 color mode */
+		WGen (fb_info, VGA_PEL_MSK, 0xff);	/* pixel mask: pass-through all planes */
+		if (_par->multiplexing)
+			WHDR (fb_info, 0x4a);	/* hidden dac reg: 1280x1024 */
+		else
+			WHDR (fb_info, 0);	/* hidden dac: nothing */
+		vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x0a);	/* memory mode: chain4, ext. memory */
+		vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0xff);	/* plane mask: enable writing to all 4 planes */
+		offset = _par->var.xres_virtual / 8;
+	} else if (_par->var.bits_per_pixel == 16) {
+		DPRINTK ("clgen: preparing for 16 bit deep display\n");
+		switch (fb_info->btype) {
+		case BT_SD64:
+			vga_wseq (fb_info->regs, CL_SEQR7, 0xf7);	/* Extended Sequencer Mode: 256c col. mode */
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x1e);		/* MCLK select */
+			break;
+
+		case BT_PICCOLO:
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x87);
+			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* Fast Page-Mode writes */
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* MCLK select */
+			break;
+
+		case BT_PICASSO:
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x27);
+			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* Fast Page-Mode writes */
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* MCLK select */
+			break;
+
+		case BT_SPECTRUM:
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x87);
+			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* Fast Page-Mode writes */
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* MCLK select */
+			break;
+
+		case BT_PICASSO4:
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x27);
+/*          vga_wseq (fb_info->regs, CL_SEQR1F, 0x1c);  */
+			break;
+
+		case BT_ALPINE:
+			DPRINTK (" (for GD543x)\n");
+			if (_par->HorizRes >= 1024)
+				vga_wseq (fb_info->regs, CL_SEQR7, 0xa7);
+			else
+				vga_wseq (fb_info->regs, CL_SEQR7, 0xa3);
+			clgen_set_mclk (fb_info, _par->mclk, _par->divMCLK);
+			break;
+
+		case BT_GD5480:
+			DPRINTK (" (for GD5480)\n");
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x17);
+			/* We already set SRF and SR1F */
+			break;
+
+		default:
+			printk (KERN_WARNING "CLGEN: unknown Board\n");
+			break;
+		}
+
+		vga_wgfx (fb_info->regs, VGA_GFX_MODE, 64);	/* mode register: 256 color mode */
+		WGen (fb_info, VGA_PEL_MSK, 0xff);	/* pixel mask: pass-through all planes */
+#ifdef CONFIG_PCI
+		WHDR (fb_info, 0xc0);	/* Copy Xbh */
+#elif CONFIG_ZORRO
+		WHDR (fb_info, 0xa0);	/* hidden dac reg: nothing special */
 #endif
-	WGfx(GR5,     0);      /* mode register */
+		vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x0a);	/* memory mode: chain4, ext. memory */
+		vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0xff);	/* plane mask: enable writing to all 4 planes */
+		offset = _par->var.xres_virtual / 4;
+	} else if (_par->var.bits_per_pixel == 32) {
+		DPRINTK ("clgen: preparing for 24/32 bit deep display\n");
+		switch (fb_info->btype) {
+		case BT_SD64:
+			vga_wseq (fb_info->regs, CL_SEQR7, 0xf9);	/* Extended Sequencer Mode: 256c col. mode */
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x1e);		/* MCLK select */
+			break;
+
+		case BT_PICCOLO:
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x85);
+			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* Fast Page-Mode writes */
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* MCLK select */
+			break;
+
+		case BT_PICASSO:
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x25);
+			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* Fast Page-Mode writes */
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* MCLK select */
+			break;
+
+		case BT_SPECTRUM:
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x85);
+			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* Fast Page-Mode writes */
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* MCLK select */
+			break;
+
+		case BT_PICASSO4:
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x25);
+/*          vga_wseq (fb_info->regs, CL_SEQR1F, 0x1c);  */
+			break;
+
+		case BT_ALPINE:
+			DPRINTK (" (for GD543x)\n");
+			vga_wseq (fb_info->regs, CL_SEQR7, 0xa9);
+			clgen_set_mclk (fb_info, _par->mclk, _par->divMCLK);
+			break;
+
+		case BT_GD5480:
+			DPRINTK (" (for GD5480)\n");
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x19);
+			/* We already set SRF and SR1F */
+			break;
+
+		default:
+			printk (KERN_WARNING "clgen: unknown Board\n");
+			break;
+		}
+
+		vga_wgfx (fb_info->regs, VGA_GFX_MODE, 64);	/* mode register: 256 color mode */
+		WGen (fb_info, VGA_PEL_MSK, 0xff);	/* pixel mask: pass-through all planes */
+		WHDR (fb_info, 0xc5);	/* hidden dac reg: 8-8-8 mode (24 or 32) */
+		vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x0a);	/* memory mode: chain4, ext. memory */
+		vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0xff);	/* plane mask: enable writing to all 4 planes */
+		offset = _par->var.xres_virtual / 4;
+	} else
+		printk (KERN_ERR "clgen: What's this?? requested color depth == %d.\n",
+			_par->var.bits_per_pixel);
+
+	vga_wcrt (fb_info->regs, VGA_CRTC_OFFSET, offset & 0xff);
+	tmp = 0x22;
+	if (offset & 0x100)
+		tmp |= 0x10;	/* offset overflow bit */
+
+	vga_wcrt (fb_info->regs, CL_CRT1B, tmp);	/* screen start addr #16-18, fastpagemode cycles */
+
+	if (fb_info->btype == BT_SD64 ||
+	    fb_info->btype == BT_PICASSO4 ||
+	    fb_info->btype == BT_ALPINE ||
+	    fb_info->btype == BT_GD5480)
+		vga_wcrt (fb_info->regs, CL_CRT1D, 0x00);	/* screen start address bit 19 */
+
+	vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_HI, 0);	/* text cursor location high */
+	vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_LO, 0);	/* text cursor location low */
+	vga_wcrt (fb_info->regs, VGA_CRTC_UNDERLINE, 0);	/* underline row scanline = at very bottom */
+
+	vga_wattr (fb_info->regs, VGA_ATC_MODE, 1);	/* controller mode */
+	vga_wattr (fb_info->regs, VGA_ATC_OVERSCAN, 0);		/* overscan (border) color */
+	vga_wattr (fb_info->regs, VGA_ATC_PLANE_ENABLE, 15);	/* color plane enable */
+	vga_wattr (fb_info->regs, CL_AR33, 0);	/* pixel panning */
+	vga_wattr (fb_info->regs, VGA_ATC_COLOR_PAGE, 0);	/* color select */
+
+	/* [ EGS: SetOffset(); ] */
+	/* From SetOffset(): Turn on VideoEnable bit in Attribute controller */
+	AttrOn (fb_info);
+
+	vga_wgfx (fb_info->regs, VGA_GFX_SR_VALUE, 0);	/* set/reset register */
+	vga_wgfx (fb_info->regs, VGA_GFX_SR_ENABLE, 0);		/* set/reset enable */
+	vga_wgfx (fb_info->regs, VGA_GFX_COMPARE_VALUE, 0);	/* color compare */
+	vga_wgfx (fb_info->regs, VGA_GFX_DATA_ROTATE, 0);	/* data rotate */
+	vga_wgfx (fb_info->regs, VGA_GFX_PLANE_READ, 0);	/* read map select */
+	vga_wgfx (fb_info->regs, VGA_GFX_MISC, 1);	/* miscellaneous register */
+	vga_wgfx (fb_info->regs, VGA_GFX_COMPARE_MASK, 15);	/* color don't care */
+	vga_wgfx (fb_info->regs, VGA_GFX_BIT_MASK, 255);	/* bit mask */
+
+	vga_wseq (fb_info->regs, CL_SEQR12, 0x0);	/* graphics cursor attributes: nothing special */
+
+	/* finally, turn on everything - turn off "FullBandwidth" bit */
+	/* also, set "DotClock%2" bit where requested */
+	tmp = 0x01;
+
+/*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ?
+    if (var->vmode & FB_VMODE_CLOCK_HALVE)
+	tmp |= 0x08;
+*/
+
+	vga_wseq (fb_info->regs, VGA_SEQ_CLOCK_MODE, tmp);
+	DPRINTK ("CL_SEQR1: %d\n", tmp);
+
+	fb_info->currentmode = *_par;
+
+	DPRINTK ("virtual offset: (%d,%d)\n", _par->var.xoffset, _par->var.yoffset);
+	/* pan to requested offset */
+	clgen_pan_display (&fb_info->currentmode.var, (struct fb_info_gen *) fb_info);
+
+#ifdef CLGEN_DEBUG
+	clgen_dump ();
+#endif
+
+	DPRINTK ("EXIT\n");
+	return;
+}
+
+static int clgen_getcolreg (unsigned regno, unsigned *red, unsigned *green,
+			    unsigned *blue, unsigned *transp,
+			    struct fb_info *info)
+{
+	unsigned char bred, bgreen, bblue;
+	struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
+
+	if (regno > 255)
+		return -EINVAL;
+
+	RClut (fb_info, regno, &bred, &bgreen, &bblue);
+
+	*red = (bred << 10) | (bred << 4) | (bred >> 2);
+	*green = (bgreen << 10) | (bgreen << 4) | (bgreen >> 2);
+	*blue = (bblue << 10) | (bblue << 4) | (bblue >> 2);
+	*transp = 0;
+
+	return 0;
+}
+
+static int clgen_setcolreg (unsigned regno, unsigned red, unsigned green,
+			    unsigned blue, unsigned transp,
+			    struct fb_info *info)
+{
+	struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
+
+	if (regno > 255)
+		return -EINVAL;
+
+	switch (fb_info->currentmode.var.bits_per_pixel) {
+#ifdef FBCON_HAS_CFB8
+	case 8:
+		/* "transparent" stuff is completely ignored. */
+		WClut (fb_info, regno, red >> 10, green >> 10, blue >> 10);
+		break;
+#endif
+#ifdef FBCON_HAS_CFB16
+	case 16:
+		assert (regno < 16);
+#ifdef CONFIG_PREP
+		fb_info->fbcon_cmap.cfb16[regno] =
+		    ((red & 0xf800) >> 9) |
+		    ((green & 0xf800) >> 14) |
+		    ((green & 0xf800) << 2) |
+		    ((blue & 0xf800) >> 3);
+#else
+		fb_info->fbcon_cmap.cfb16[regno] =
+		    ((red & 0xf800) >> 1) |
+		    ((green & 0xf800) >> 6) |
+		    ((blue & 0xf800) >> 11);
+#endif
+#endif
+#ifdef FBCON_HAS_CFB32
+	case 32:
+		assert (regno < 16);
+#ifdef CONFIG_PREP
+		fb_info->fbcon_cmap.cfb32[regno] =
+		    ((red & 0xff00)) |
+		    ((green & 0xff00) << 8) |
+		    ((blue & 0xff00) << 16);
+#endif
+		fb_info->fbcon_cmap.cfb32[regno] =
+		    ((red & 0xff00) << 8) |
+		    ((green & 0xff00)) |
+		    ((blue & 0xff00) >> 8);
+#endif
+	}
+
+	return 0;
+}
+
+/*************************************************************************
+	clgen_pan_display()
+
+	performs display panning - provided hardware permits this
+**************************************************************************/
+static int clgen_pan_display (const struct fb_var_screeninfo *var,
+			      struct fb_info_gen *info)
+{
+	int xoffset = 0;
+	int yoffset = 0;
+	unsigned long base;
+	unsigned char tmp = 0, tmp2 = 0, xpix;
+	struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
+
+	DPRINTK ("ENTER\n");
+
+	/* no range checks for xoffset and yoffset,   */
+	/* as fbgen_pan_display has already done this */
+
+	fb_info->currentmode.var.xoffset = var->xoffset;
+	fb_info->currentmode.var.yoffset = var->yoffset;
+
+	xoffset = var->xoffset * fb_info->currentmode.var.bits_per_pixel / 8;
+	yoffset = var->yoffset;
+
+	base = yoffset * fb_info->currentmode.line_length + xoffset;
+
+	if (fb_info->currentmode.var.bits_per_pixel == 1) {
+		/* base is already correct */
+		xpix = (unsigned char) (var->xoffset % 8);
+	} else {
+		base /= 4;
+		xpix = (unsigned char) ((xoffset % 4) * 2);
+	}
+
+	/* lower 8 + 8 bits of screen start address */
+	vga_wcrt (fb_info->regs, VGA_CRTC_START_LO, (unsigned char) (base & 0xff));
+	vga_wcrt (fb_info->regs, VGA_CRTC_START_HI, (unsigned char) (base >> 8));
+
+	/* construct bits 16, 17 and 18 of screen start address */
+	if (base & 0x10000)
+		tmp |= 0x01;
+	if (base & 0x20000)
+		tmp |= 0x04;
+	if (base & 0x40000)
+		tmp |= 0x08;
+
+	tmp2 = (vga_rcrt (fb_info->regs, CL_CRT1B) & 0xf2) | tmp;	/* 0xf2 is %11110010, exclude tmp bits */
+	vga_wcrt (fb_info->regs, CL_CRT1B, tmp2);
+
+	/* construct bit 19 of screen start address */
+	if (clgen_board_info[fb_info->btype].scrn_start_bit19) {
+		tmp2 = 0;
+		if (base & 0x80000)
+			tmp2 = 0x80;
+		vga_wcrt (fb_info->regs, CL_CRT1D, tmp2);
+	}
+
+	/* write pixel panning value to AR33; this does not quite work in 8bpp */
+	/* ### Piccolo..? Will this work? */
+	if (fb_info->currentmode.var.bits_per_pixel == 1)
+		vga_wattr (fb_info->regs, CL_AR33, xpix);
+
+
+	DPRINTK ("EXIT\n");
+	return (0);
+}
+
+
+static int clgen_blank (int blank_mode, struct fb_info_gen *info)
+{
+	/*
+	 *  Blank the screen if blank_mode != 0, else unblank. If blank == NULL
+	 *  then the caller blanks by setting the CLUT (Color Look Up Table) to all
+	 *  black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due
+	 *  to e.g. a video mode which doesn't support it. Implements VESA suspend
+	 *  and powerdown modes on hardware that supports disabling hsync/vsync:
+	 *    blank_mode == 2: suspend vsync
+	 *    blank_mode == 3: suspend hsync
+	 *    blank_mode == 4: powerdown
+	 */
+	unsigned char val;
+	static int current_mode = 0;
+	struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
+
+	DPRINTK ("ENTER, blank mode = %d\n", blank_mode);
+
+	if (current_mode == blank_mode) {
+		DPRINTK ("EXIT, returning 0\n");
+		return 0;
+	}
+
+	/* Undo current */
+	switch (current_mode) {
+	case 0:		/* Screen is normal */
+		break;
+	case 1:		/* Screen is blanked */
+		val = vga_rseq (fb_info->regs, VGA_SEQ_CLOCK_MODE);
+		vga_wseq (fb_info->regs, VGA_SEQ_CLOCK_MODE, val & 0xdf);	/* clear "FullBandwidth" bit */
+		break;
+	case 2:		/* vsync suspended */
+	case 3:		/* hsync suspended */
+	case 4:		/* sceen is powered down */
+		vga_wgfx (fb_info->regs, CL_GRE, 0x00);
+		break;
+	default:
+		DPRINTK ("EXIT, returning 1\n");
+		return 1;
+	}
+
+	/* set new */
+	switch (blank_mode) {
+	case 0:		/* Unblank screen */
+		break;
+	case 1:		/* Blank screen */
+		val = vga_rseq (fb_info->regs, VGA_SEQ_CLOCK_MODE);
+		vga_wseq (fb_info->regs, VGA_SEQ_CLOCK_MODE, val | 0x20);	/* set "FullBandwidth" bit */
+		break;
+	case 2:		/* suspend vsync */
+		vga_wgfx (fb_info->regs, CL_GRE, 0x04);
+		break;
+	case 3:		/* suspend hsync */
+		vga_wgfx (fb_info->regs, CL_GRE, 0x02);
+		break;
+	case 4:		/* powerdown */
+		vga_wgfx (fb_info->regs, CL_GRE, 0x06);
+		break;
+	default:
+		DPRINTK ("EXIT, returning 1\n");
+		return 1;
+	}
+
+	current_mode = blank_mode;
+	DPRINTK ("EXIT, returning 0\n");
+	return 0;
+}
+/**** END   Hardware specific Routines **************************************/
+/****************************************************************************/
+/**** BEGIN Internal Routines ***********************************************/
+
+static void __init init_vgachip (struct clgenfb_info *fb_info)
+{
+	const struct clgen_board_info_rec *bi;
 	
-	/* Extended Sequencer Mode */
-	switch(fb_info->btype)
-	{
-	case BT_SD64:
-	    /* setting the SEQRF on SD64 is not necessary (only during init) */
-	    DEBUG printk(KERN_INFO "(for SD64)\n");
-	    WSeq(SEQR7,  0xf0);
-	    WSeq(SEQR1F, 0x1a);     /*  MCLK select */
-	    break;
+	DPRINTK ("ENTER\n");
 
-	case BT_PICCOLO:
-	    DEBUG printk(KERN_INFO "(for Piccolo)\n");
-	    WSeq(SEQR7, 0x80);
-/* ### ueberall 0x22? */
-	    WSeq(SEQR1F, 0x22);     /* ##vorher 1c MCLK select */
-	    WSeq(SEQRF, 0xb0);    /* evtl d0 bei 1 bit? avoid FIFO underruns..? */
-	    break;
+	assert (fb_info != NULL);
+	
+	bi = &clgen_board_info[fb_info->btype];
 
+	/* reset board globally */
+	switch (fb_info->btype) {
+	case BT_PICCOLO:
+		WSFR (fb_info, 0x01);
+		udelay (500);
+		WSFR (fb_info, 0x51);
+		udelay (500);
+		break;
 	case BT_PICASSO:
-	    DEBUG printk(KERN_INFO "(for Picasso)\n");
-	    WSeq(SEQR7, 0x20);
-	    WSeq(SEQR1F, 0x22);     /* ##vorher 22 MCLK select */
-	    WSeq(SEQRF, 0xd0);    /* ## vorher d0 avoid FIFO underruns..? */
-	    break;
-
+		WSFR2 (fb_info, 0xff);
+		udelay (500);
+		break;
+	case BT_SD64:
 	case BT_SPECTRUM:
-	    DEBUG printk(KERN_INFO "(for Spectrum)\n");
-	    WSeq(SEQR7, 0x80);
-/* ### ueberall 0x22? */
-	    WSeq(SEQR1F, 0x22);     /* ##vorher 1c MCLK select */
-	    WSeq(SEQRF, 0xb0);    /* evtl d0? avoid FIFO underruns..? */
-	    break;
+		WSFR (fb_info, 0x1f);
+		udelay (500);
+		WSFR (fb_info, 0x4f);
+		udelay (500);
+		break;
+	case BT_PICASSO4:
+		vga_wcrt (fb_info->regs, CL_CRT51, 0x00);	/* disable flickerfixer */
+		udelay (100000);
+		vga_wgfx (fb_info->regs, CL_GR2F, 0x00);	/* from Klaus' NetBSD driver: */
+		vga_wgfx (fb_info->regs, CL_GR33, 0x00);	/* put blitter into 542x compat */
+		vga_wgfx (fb_info->regs, CL_GR31, 0x00);	/* mode */
+		break;
+
+	case BT_GD5480:
+		vga_wgfx (fb_info->regs, CL_GR2F, 0x00);	/* from Klaus' NetBSD driver: */
+		break;
+
+	case BT_ALPINE:
+		/* Nothing to do to reset the board. */
+		break;
+
+	default:
+		printk (KERN_ERR "clgen: Warning: Unknown board type\n");
+		break;
+	}
+
+	/* "pre-set" a RAMsize; if the test succeeds, double it */
+	if (fb_info->btype == BT_SD64 ||
+	    fb_info->btype == BT_PICASSO4)
+		fb_info->size = 0x400000;
+	else
+		fb_info->size = 0x200000;
+
+	/* assume it's a "large memory" board (2/4 MB) */
+	fb_info->smallboard = FALSE;
+
+	/* the P4 is not fully initialized here; I rely on it having been */
+	/* inited under AmigaOS already, which seems to work just fine    */
+	/* (Klaus advised to do it this way)                              */
+
+	if (fb_info->btype != BT_PICASSO4) {
+		WGen (fb_info, CL_VSSM, 0x10);	/* EGS: 0x16 */
+		WGen (fb_info, CL_POS102, 0x01);
+		WGen (fb_info, CL_VSSM, 0x08);	/* EGS: 0x0e */
+
+		if (fb_info->btype != BT_SD64)
+			WGen (fb_info, CL_VSSM2, 0x01);
+
+		vga_wseq (fb_info->regs, CL_SEQR0, 0x03);	/* reset sequencer logic */
+
+		vga_wseq (fb_info->regs, VGA_SEQ_CLOCK_MODE, 0x21);	/* FullBandwidth (video off) and 8/9 dot clock */
+		WGen (fb_info, VGA_MIS_W, 0xc1);	/* polarity (-/-), disable access to display memory, VGA_CRTC_START_HI base address: color */
+
+/*      vga_wgfx (fb_info->regs, CL_GRA, 0xce);    "magic cookie" - doesn't make any sense to me.. */
+		vga_wseq (fb_info->regs, CL_SEQR6, 0x12);	/* unlock all extension registers */
+
+		vga_wgfx (fb_info->regs, CL_GR31, 0x04);	/* reset blitter */
+
+		switch (fb_info->btype) {
+		case BT_GD5480:
+			vga_wseq (fb_info->regs, CL_SEQRF, 0x98);
+			break;
+		case BT_ALPINE:
+			break;
+		case BT_SD64:
+			vga_wseq (fb_info->regs, CL_SEQRF, 0xb8);
+			break;
+		default:
+			vga_wseq (fb_info->regs, CL_SEQR16, 0x0f);
+			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);
+			break;
+		}
+	}
+	vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0xff);	/* plane mask: nothing */
+	vga_wseq (fb_info->regs, VGA_SEQ_CHARACTER_MAP, 0x00);	/* character map select: doesn't even matter in gx mode */
+	vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x0e);	/* memory mode: chain-4, no odd/even, ext. memory */
+
+	/* controller-internal base address of video memory */
+	vga_wseq (fb_info->regs, CL_SEQR7, bi->sr07);
+
+	/*  vga_wseq (fb_info->regs, CL_SEQR8, 0x00); *//* EEPROM control: shouldn't be necessary to write to this at all.. */
+
+	vga_wseq (fb_info->regs, CL_SEQR10, 0x00);		/* graphics cursor X position (incomplete; position gives rem. 3 bits */
+	vga_wseq (fb_info->regs, CL_SEQR11, 0x00);		/* graphics cursor Y position (..."... ) */
+	vga_wseq (fb_info->regs, CL_SEQR12, 0x00);		/* graphics cursor attributes */
+	vga_wseq (fb_info->regs, CL_SEQR13, 0x00);		/* graphics cursor pattern address */
+
+	/* writing these on a P4 might give problems..  */
+	if (fb_info->btype != BT_PICASSO4) {
+		vga_wseq (fb_info->regs, CL_SEQR17, 0x00);		/* configuration readback and ext. color */
+		vga_wseq (fb_info->regs, CL_SEQR18, 0x02);		/* signature generator */
+	}
+
+	/* MCLK select etc. */
+	if (bi->write_sr1f)
+		vga_wseq (fb_info->regs, CL_SEQR1F, bi->sr1f);
+
+	vga_wcrt (fb_info->regs, VGA_CRTC_PRESET_ROW, 0x00);	/* Screen A preset row scan: none */
+	vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_START, 0x20);	/* Text cursor start: disable text cursor */
+	vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_END, 0x00);	/* Text cursor end: - */
+	vga_wcrt (fb_info->regs, VGA_CRTC_START_HI, 0x00);	/* Screen start address high: 0 */
+	vga_wcrt (fb_info->regs, VGA_CRTC_START_LO, 0x00);	/* Screen start address low: 0 */
+	vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_HI, 0x00);	/* text cursor location high: 0 */
+	vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_LO, 0x00);	/* text cursor location low: 0 */
+
+	vga_wcrt (fb_info->regs, VGA_CRTC_UNDERLINE, 0x00);	/* Underline Row scanline: - */
+	vga_wcrt (fb_info->regs, VGA_CRTC_MODE, 0xc3);	/* mode control: timing enable, byte mode, no compat modes */
+	vga_wcrt (fb_info->regs, VGA_CRTC_LINE_COMPARE, 0x00);	/* Line Compare: not needed */
+	/* ### add 0x40 for text modes with > 30 MHz pixclock */
+	vga_wcrt (fb_info->regs, CL_CRT1B, 0x02);	/* ext. display controls: ext.adr. wrap */
+
+	vga_wgfx (fb_info->regs, VGA_GFX_SR_VALUE, 0x00);	/* Set/Reset registes: - */
+	vga_wgfx (fb_info->regs, VGA_GFX_SR_ENABLE, 0x00);	/* Set/Reset enable: - */
+	vga_wgfx (fb_info->regs, VGA_GFX_COMPARE_VALUE, 0x00);	/* Color Compare: - */
+	vga_wgfx (fb_info->regs, VGA_GFX_DATA_ROTATE, 0x00);	/* Data Rotate: - */
+	vga_wgfx (fb_info->regs, VGA_GFX_PLANE_READ, 0x00);	/* Read Map Select: - */
+	vga_wgfx (fb_info->regs, VGA_GFX_MODE, 0x00);	/* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */
+	vga_wgfx (fb_info->regs, VGA_GFX_MISC, 0x01);	/* Miscellaneous: memory map base address, graphics mode */
+	vga_wgfx (fb_info->regs, VGA_GFX_COMPARE_MASK, 0x0f);	/* Color Don't care: involve all planes */
+	vga_wgfx (fb_info->regs, VGA_GFX_BIT_MASK, 0xff);	/* Bit Mask: no mask at all */
+	if (fb_info->btype == BT_ALPINE)
+		vga_wgfx (fb_info->regs, CL_GRB, 0x20);	/* (5434 can't have bit 3 set for bitblt) */
+	else
+		vga_wgfx (fb_info->regs, CL_GRB, 0x28);	/* Graphics controller mode extensions: finer granularity, 8byte data latches */
+
+	vga_wgfx (fb_info->regs, CL_GRC, 0xff);	/* Color Key compare: - */
+	vga_wgfx (fb_info->regs, CL_GRD, 0x00);	/* Color Key compare mask: - */
+	vga_wgfx (fb_info->regs, CL_GRE, 0x00);	/* Miscellaneous control: - */
+	/*  vga_wgfx (fb_info->regs, CL_GR10, 0x00); *//* Background color byte 1: - */
+/*  vga_wgfx (fb_info->regs, CL_GR11, 0x00); */
+
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTE0, 0x00);	/* Attribute Controller palette registers: "identity mapping" */
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTE1, 0x01);
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTE2, 0x02);
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTE3, 0x03);
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTE4, 0x04);
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTE5, 0x05);
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTE6, 0x06);
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTE7, 0x07);
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTE8, 0x08);
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTE9, 0x09);
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTEA, 0x0a);
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTEB, 0x0b);
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTEC, 0x0c);
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTED, 0x0d);
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTEE, 0x0e);
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTEF, 0x0f);
+
+	vga_wattr (fb_info->regs, VGA_ATC_MODE, 0x01);	/* Attribute Controller mode: graphics mode */
+	vga_wattr (fb_info->regs, VGA_ATC_OVERSCAN, 0x00);	/* Overscan color reg.: reg. 0 */
+	vga_wattr (fb_info->regs, VGA_ATC_PLANE_ENABLE, 0x0f);	/* Color Plane enable: Enable all 4 planes */
+/* ###  vga_wattr (fb_info->regs, CL_AR33, 0x00); * Pixel Panning: - */
+	vga_wattr (fb_info->regs, VGA_ATC_COLOR_PAGE, 0x00);	/* Color Select: - */
+
+	WGen (fb_info, VGA_PEL_MSK, 0xff);	/* Pixel mask: no mask */
+
+	if (fb_info->btype != BT_ALPINE && fb_info->btype != BT_GD5480)
+		WGen (fb_info, VGA_MIS_W, 0xc3);	/* polarity (-/-), enable display mem, VGA_CRTC_START_HI i/o base = color */
+
+	vga_wgfx (fb_info->regs, CL_GR31, 0x04);	/* BLT Start/status: Blitter reset */
+	vga_wgfx (fb_info->regs, CL_GR31, 0x00);	/* - " -           : "end-of-reset" */
+
+	/* CLUT setup */
+	WClut (fb_info, 0, 0x00, 0x00, 0x00);	/* background: black */
+	WClut (fb_info, 1, 0x3f, 0x3f, 0x3f);	/* foreground: white */
+	WClut (fb_info, 2, 0x00, 0x20, 0x00);
+	WClut (fb_info, 3, 0x00, 0x20, 0x20);
+	WClut (fb_info, 4, 0x20, 0x00, 0x00);
+	WClut (fb_info, 5, 0x20, 0x00, 0x20);
+	WClut (fb_info, 6, 0x20, 0x10, 0x00);
+	WClut (fb_info, 7, 0x20, 0x20, 0x20);
+	WClut (fb_info, 8, 0x10, 0x10, 0x10);
+	WClut (fb_info, 9, 0x10, 0x10, 0x30);
+	WClut (fb_info, 10, 0x10, 0x30, 0x10);
+	WClut (fb_info, 11, 0x10, 0x30, 0x30);
+	WClut (fb_info, 12, 0x30, 0x10, 0x10);
+	WClut (fb_info, 13, 0x30, 0x10, 0x30);
+	WClut (fb_info, 14, 0x30, 0x30, 0x10);
+	WClut (fb_info, 15, 0x30, 0x30, 0x30);
+
+	/* the rest a grey ramp */
+	{
+		int i;
+
+		for (i = 16; i < 256; i++)
+			WClut (fb_info, i, i >> 2, i >> 2, i >> 2);
+	}
+
+
+	/* misc... */
+	WHDR (fb_info, 0);	/* Hidden DAC register: - */
+
+	printk (KERN_INFO "clgen: This board has %ld bytes of DRAM memory\n", fb_info->size);
+	DPRINTK ("EXIT\n");
+	return;
+}
+
+static void switch_monitor (struct clgenfb_info *fb_info, int on)
+{
+#ifdef CONFIG_ZORRO /* only works on Zorro boards */
+	static int IsOn = 0;	/* XXX not ok for multiple boards */
+
+	DPRINTK ("ENTER\n");
+
+	if (fb_info->btype == BT_PICASSO4)
+		return;		/* nothing to switch */
+	if (fb_info->btype == BT_ALPINE)
+		return;		/* nothing to switch */
+	if (fb_info->btype == BT_GD5480)
+		return;		/* nothing to switch */
+	if (fb_info->btype == BT_PICASSO) {
+		if ((on && !IsOn) || (!on && IsOn))
+			WSFR (fb_info, 0xff);
+
+		DPRINTK ("EXIT\n");
+		return;
+	}
+	if (on) {
+		switch (fb_info->btype) {
+		case BT_SD64:
+			WSFR (fb_info, fb_info->SFR | 0x21);
+			break;
+		case BT_PICCOLO:
+			WSFR (fb_info, fb_info->SFR | 0x28);
+			break;
+		case BT_SPECTRUM:
+			WSFR (fb_info, 0x6f);
+			break;
+		default: /* do nothing */ break;
+		}
+	} else {
+		switch (fb_info->btype) {
+		case BT_SD64:
+			WSFR (fb_info, fb_info->SFR & 0xde);
+			break;
+		case BT_PICCOLO:
+			WSFR (fb_info, fb_info->SFR & 0xd7);
+			break;
+		case BT_SPECTRUM:
+			WSFR (fb_info, 0x4f);
+			break;
+		default: /* do nothing */ break;
+		}
+	}
+	
+	DPRINTK ("EXIT\n");
+#endif /* CONFIG_ZORRO */
+}
+
+static void clgen_set_disp (const void *par, struct display *disp,
+			    struct fb_info_gen *info)
+{
+	struct clgenfb_par *_par = (struct clgenfb_par *) par;
+	struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
+	int accel_text;
+
+	DPRINTK ("ENTER\n");
+	
+	assert (_par != NULL);
+	assert (fb_info != NULL);
+	
+	accel_text = _par->var.accel_flags & FB_ACCELF_TEXT;
+
+	printk ("Cirrus Logic video mode: ");
+	disp->screen_base = (char *) fb_info->fbmem;
+	switch (_par->var.bits_per_pixel) {
+#ifdef FBCON_HAS_MFB
+	case 1:
+		printk ("monochrome\n");
+		if (fb_info->btype == BT_GD5480)
+			disp->screen_base = (char *) fb_info->fbmem;
+		disp->dispsw = &fbcon_mfb;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB8
+	case 8:
+		printk ("8 bit color depth\n");
+		if (fb_info->btype == BT_GD5480)
+			disp->screen_base = (char *) fb_info->fbmem;
+		if (accel_text)
+			disp->dispsw = &fbcon_clgen_8;
+		else
+			disp->dispsw = &fbcon_cfb8;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB16
+	case 16:
+		printk ("16 bit color depth\n");
+		if (accel_text)
+			disp->dispsw = &fbcon_clgen_16;
+		else
+			disp->dispsw = &fbcon_cfb16;
+		if (fb_info->btype == BT_GD5480)
+			disp->screen_base = (char *) fb_info->fbmem + 1 * MB_;
+		disp->dispsw_data = fb_info->fbcon_cmap.cfb16;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB24
+	case 24:
+		printk ("24 bit color depth\n");
+		disp->dispsw = &fbcon_cfb24;
+		if (fb_info->btype == BT_GD5480)
+			disp->screen_base = (char *) fb_info->fbmem + 2 * MB_;
+		disp->dispsw_data = fb_info->fbcon_cmap.cfb24;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB32
+	case 32:
+		printk ("32 bit color depth\n");
+		if (accel_text)
+			disp->dispsw = &fbcon_clgen_32;
+		else
+			disp->dispsw = &fbcon_cfb32;
+		if (fb_info->btype == BT_GD5480)
+			disp->screen_base = (char *) fb_info->fbmem + 2 * MB_;
+		disp->dispsw_data = fb_info->fbcon_cmap.cfb32;
+		break;
+#endif
+
+	default:
+		printk ("unsupported color depth\n");
+		disp->dispsw = &fbcon_dummy;
+		disp->dispsw_data = NULL;
+		break;
+	}
+
+	DPRINTK ("EXIT\n");
+}
+
+#ifdef FBCON_HAS_CFB8
+static void fbcon_clgen8_bmove (struct display *p, int sy, int sx,
+				int dy, int dx, int height, int width)
+{
+	struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info;
+
+	DPRINTK ("ENTER\n");
+
+	sx *= fontwidth (p);
+	sy *= fontheight (p);
+	dx *= fontwidth (p);
+	dy *= fontheight (p);
+	width *= fontwidth (p);
+	height *= fontheight (p);
+
+	clgen_BitBLT (fb_info->regs, (unsigned short) sx, (unsigned short) sy,
+		      (unsigned short) dx, (unsigned short) dy,
+		      (unsigned short) width, (unsigned short) height,
+		      fb_info->currentmode.line_length);
+
+	DPRINTK ("EXIT\n");
+}
+
+static void fbcon_clgen8_clear (struct vc_data *conp, struct display *p,
+				int sy, int sx, int height, int width)
+{
+	struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info;
+	unsigned short col;
+
+	DPRINTK ("ENTER\n");
+
+	sx *= fontwidth (p);
+	sy *= fontheight (p);
+	width *= fontwidth (p);
+	height *= fontheight (p);
+
+	col = attr_bgcol_ec (p, conp);
+	col &= 0xff;
+
+	clgen_RectFill (fb_info, (unsigned short) sx, (unsigned short) sy,
+			(unsigned short) width, (unsigned short) height,
+			col, fb_info->currentmode.line_length);
+
+	DPRINTK ("EXIT\n");
+}
+
+#endif
+
+#ifdef FBCON_HAS_CFB16
+static void fbcon_clgen16_bmove (struct display *p, int sy, int sx,
+				 int dy, int dx, int height, int width)
+{
+	struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info;
+
+	DPRINTK ("ENTER\n");
+
+	sx *= fontwidth (p) * 2;	/* 2 bytes/pixel */
+	sy *= fontheight (p);
+	dx *= fontwidth (p) * 2;	/* 2 bytes/pixel */
+	dy *= fontheight (p);
+	width *= fontwidth (p) * 2;	/* 2 bytes/pixel */
+	height *= fontheight (p);
+
+	clgen_BitBLT (fb_info->regs, (unsigned short) sx, (unsigned short) sy,
+		      (unsigned short) dx, (unsigned short) dy,
+		      (unsigned short) width, (unsigned short) height,
+		      fb_info->currentmode.line_length);
+
+	DPRINTK ("EXIT\n");
+}
+
+static void fbcon_clgen16_clear (struct vc_data *conp, struct display *p,
+				 int sy, int sx, int height, int width)
+{
+	struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info;
+	unsigned short col;
+
+	DPRINTK ("ENTER\n");
+
+	sx *= fontwidth (p) * 2;	/* 2 bytes/pixel */
+	sy *= fontheight (p);
+	width *= fontwidth (p) * 2;	/* 2 bytes/pixel? */
+	height *= fontheight (p);
+
+	col = attr_bgcol_ec (p, conp);
+	col &= 0xff;
+
+	clgen_RectFill (fb_info, (unsigned short) sx, (unsigned short) sy,
+			(unsigned short) width, (unsigned short) height,
+			col, fb_info->currentmode.line_length);
+
+	DPRINTK ("EXIT\n");
+}
+
+#endif
+
+#ifdef FBCON_HAS_CFB32
+static void fbcon_clgen32_bmove (struct display *p, int sy, int sx,
+				 int dy, int dx, int height, int width)
+{
+	struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info;
+
+	DPRINTK ("ENTER\n");
+
+	sx *= fontwidth (p) * 4;	/* 4 bytes/pixel */
+	sy *= fontheight (p);
+	dx *= fontwidth (p) * 4;	/* 4 bytes/pixel */
+	dy *= fontheight (p);
+	width *= fontwidth (p) * 4;	/* 4 bytes/pixel */
+	height *= fontheight (p);
+
+	clgen_BitBLT (fb_info->regs, (unsigned short) sx, (unsigned short) sy,
+		      (unsigned short) dx, (unsigned short) dy,
+		      (unsigned short) width, (unsigned short) height,
+		      fb_info->currentmode.line_length);
+
+	DPRINTK ("EXIT\n");
+}
+
+static void fbcon_clgen32_clear (struct vc_data *conp, struct display *p,
+				 int sy, int sx, int height, int width)
+{
+	struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info;
+
+	unsigned short col;
+
+	DPRINTK ("ENTER\n");
+
+	sx *= fontwidth (p) * 4;	/* 4 bytes/pixel */
+	sy *= fontheight (p);
+	width *= fontwidth (p) * 4;	/* 4 bytes/pixel? */
+	height *= fontheight (p);
+
+	col = attr_bgcol_ec (p, conp);
+	col &= 0xff;
+
+	clgen_RectFill (fb_info, (unsigned short) sx, (unsigned short) sy,
+			(unsigned short) width, (unsigned short) height,
+			col, fb_info->currentmode.line_length);
+
+	DPRINTK ("EXIT\n");
+}
+
+#endif				/* FBCON_HAS_CFB32 */
+
+
+
+
+#ifdef CONFIG_PREP
+#define PREP_VIDEO_BASE ((volatile unsigned long) 0xC0000000)
+#define PREP_IO_BASE    ((volatile unsigned char *) 0x80000000)
+static void __init get_prep_addrs (unsigned long *display, unsigned long *registers)
+{
+	DPRINTK ("ENTER\n");
+
+	*display = PREP_VIDEO_BASE;
+	*registers = (unsigned long) PREP_IO_BASE;
+
+	DPRINTK ("EXIT\n");
+}
+
+#endif				/* CONFIG_PREP */
+
+
+
+
+#ifdef CONFIG_FB_OF
+static void __init get_of_addrs (const struct device_node *dp,
+			  unsigned long *display, unsigned long *registers)
+{
+	int i;
+
+	DPRINTK ("ENTER\n");
+
+	/* Map in frame buffer and registers */
+	for (i = 0; i < dp->n_addrs; ++i) {
+		unsigned long addr = dp->addrs[i].address;
+		unsigned long size = dp->addrs[i].size;
+		printk ("dp->addrs[%d].address = $lx, dp->addrs[%d].size = %lx\n",
+			i, addr, i, size);
+		if (size >= 0x800000) {
+			*display = addr;
+		} else {
+			*registers = addr;
+		}
+	}
+
+	DPRINTK ("EXIT\n");
+}
+#endif				/* CONFIG_FB_OF */
+
+
+
+
+#ifdef CONFIG_PCI
+/* Pulled the logic from XFree86 Cirrus driver to get the memory size,
+ * based on the DRAM bandwidth bit and DRAM bank switching bit.  This
+ * works with 1MB, 2MB and 4MB configurations (which the Motorola boards
+ * seem to have. */
+static unsigned int __init clgen_get_memsize (caddr_t regbase)
+{
+	unsigned long mem = 1 * MB_;
+	unsigned char SRF;
+
+	DPRINTK ("ENTER\n");
+
+	SRF = vga_rseq (regbase, CL_SEQRF);
+	if ((SRF & 0x18) == 0x18) {
+		/* 64-bit DRAM data bus width; assume 2MB. Also indicates 2MB memory
+		   * on the 5430. */
+		mem *= 2;
+	}
+	if (SRF & 0x80) {
+		/* If DRAM bank switching is enabled, there must be twice as much
+		   * memory installed. (4MB on the 5434) */
+		mem *= 2;
+	}
+	return mem;
+
+	DPRINTK ("EXIT\n");
+}
+
+
+
+static struct pci_dev * __init clgen_pci_dev_get (clgen_board_t *btype)
+{
+	struct pci_dev *pdev = NULL;
+	int i;
+
+	DPRINTK ("ENTER\n");
+	
+	for (i = 0; i < arraysize(clgen_pci_probe_list) && !pdev; i++)
+		pdev = pci_find_device (PCI_VENDOR_ID_CIRRUS,
+					clgen_pci_probe_list[i].device, NULL);
+	
+	if (pdev)
+		*btype = clgen_pci_probe_list[i].btype;
+
+	DPRINTK ("EXIT, returning %p\n", pdev);
+	return pdev;
+}
+
+
 
-	case BT_PICASSO4:
-	    DEBUG printk(KERN_INFO "(for Picasso 4)\n");
-	    WSeq(SEQR7, 0x20);
-/*	    WSeq(SEQR1F, 0x1c); */
-/* SEQRF not being set here...	WSeq(SEQRF, 0xd0); */
-	    break;
 
-	default:
-	    printk(KERN_WARNING "clgen: unknown Board\n");
-	    break;
-	}
+static void __init get_pci_addrs (const struct pci_dev *pdev,
+			   unsigned long *display, unsigned long *registers)
+{
+	assert (pdev != NULL);
+	assert (display != NULL);
+	assert (registers != NULL);
 
-	WGen(M_3C6,0x01);     /* pixel mask: pass-through for first plane */
-	WHDR(0);              /* hidden dac reg: nothing special */
-	WSeq(SEQR4,  0x06);     /* memory mode: odd/even, ext. memory */
-	WSeq(SEQR2, 0x01);      /* plane mask: only write to first plane */
-	offset 			= _par->var.xres_virtual / 16;
-    }
-    else if (_par->var.bits_per_pixel == 8)
-    {
-	DEBUG printk(KERN_INFO "clgen: preparing for 8 bit deep display\n");
-	switch(fb_info->btype)
-	{
-	case BT_SD64:
-	    WSeq(SEQR7,  0xf1); /* Extended Sequencer Mode: 256c col. mode */
-	    WSeq(SEQR1F, 0x1d);     /* MCLK select */
-	    break;
+	DPRINTK ("ENTER\n");
 
-	case BT_PICCOLO:
-	    WSeq(SEQR7, 0x81);
-	    WSeq(SEQR1F, 0x22);     /* ### vorher 1c MCLK select */
-	    WSeq(SEQRF, 0xb0);    /* Fast Page-Mode writes */
-	    break;
+	*display = 0;
+	*registers = 0;
 
-	case BT_PICASSO:
-	    WSeq(SEQR7, 0x21);
-	    WSeq(SEQR1F, 0x22);     /* ### vorher 1c MCLK select */
-	    WSeq(SEQRF, 0xb0);    /* Fast Page-Mode writes */
-	    break;
+	/* This is a best-guess for now */
 
-	case BT_SPECTRUM:
-	    WSeq(SEQR7, 0x81);
-	    WSeq(SEQR1F, 0x22);     /* ### vorher 1c MCLK select */
-	    WSeq(SEQRF, 0xb0);    /* Fast Page-Mode writes */
-	    break;
 
-	case BT_PICASSO4:
-	    WSeq(SEQR7, 0x21);
-	    WSeq(SEQRF, 0xb8); /* ### INCOMPLETE!! */
-/*	    WSeq(SEQR1F, 0x1c); */
-	    break;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13)
 
-	default:
-	    printk(KERN_WARNING "clgen: unknown Board\n");
-	    break;
+        *display = pdev->base_address[0];
+        if ((*display & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) {
+                *registers = *display;
+                *display = pdev->base_address[1];
+         } else {
+                *registers = pdev->base_address[1];
 	}
 
-	WGfx(GR5,    64);     /* mode register: 256 color mode */
-	WGen(M_3C6,0xff);     /* pixel mask: pass-through all planes */
-	WHDR(0);              /* hidden dac reg: nothing special */
-	WSeq(SEQR4,  0x0a);     /* memory mode: chain4, ext. memory */
-	WSeq(SEQR2,  0xff);     /* plane mask: enable writing to all 4 planes */
-	offset 			= _par->var.xres_virtual / 8;
-    }
-    else if (_par->var.bits_per_pixel == 16)
-    {
-	DEBUG printk(KERN_INFO "clgen: preparing for 16 bit deep display\n");
-	switch(fb_info->btype)
-	{
-	case BT_SD64:
-	    WSeq(SEQR7,  0xf7); /* Extended Sequencer Mode: 256c col. mode */
-	    WSeq(SEQR1F, 0x1e);     /* MCLK select */
-	    break;
-
-	case BT_PICCOLO:
-	    WSeq(SEQR7, 0x87);
-	    WSeq(SEQRF, 0xb0);    /* Fast Page-Mode writes */
-	    WSeq(SEQR1F, 0x22);     /* MCLK select */
-	    break;
+#else
 
-	case BT_PICASSO:
-	    WSeq(SEQR7, 0x27);
-	    WSeq(SEQRF, 0xb0);    /* Fast Page-Mode writes */
-	    WSeq(SEQR1F, 0x22);     /* MCLK select */
-	    break;
+	if (pdev->resource[0].flags & IORESOURCE_IOPORT) {
+		*display = pdev->resource[1].start;
+		*registers = pdev->resource[0].start;
+	} else {
+		*display = pdev->resource[0].start;
+		*registers = pdev->resource[1].start;
+	}
 
-	case BT_SPECTRUM:
-	    WSeq(SEQR7, 0x87);
-	    WSeq(SEQRF, 0xb0);    /* Fast Page-Mode writes */
-	    WSeq(SEQR1F, 0x22);     /* MCLK select */
-	    break;
+#endif		/* kernel older than 2.3.13 */
 
-	case BT_PICASSO4:
-	    WSeq(SEQR7, 0x27);
-/*	    WSeq(SEQR1F, 0x1c);  */
-	    break;
+	assert (*display != 0);
 
-	default:
-	    printk(KERN_WARNING "CLGEN: unknown Board\n");
-	    break;
-	}
+	DPRINTK ("EXIT\n");
+}
 
-	WGfx(GR5,    64);     /* mode register: 256 color mode */
-	WGen(M_3C6,0xff);     /* pixel mask: pass-through all planes */
-	WHDR(0xa0);           /* hidden dac reg: nothing special */
-	WSeq(SEQR4,  0x0a);     /* memory mode: chain4, ext. memory */
-	WSeq(SEQR2,  0xff);     /* plane mask: enable writing to all 4 planes */
-	offset 			= _par->var.xres_virtual / 4;
-    }
-    else if (_par->var.bits_per_pixel == 32)
-    {
-	DEBUG printk(KERN_INFO "clgen: preparing for 24/32 bit deep display\n");
-	switch(fb_info->btype)
-	{
-	case BT_SD64:
-	    WSeq(SEQR7,  0xf9); /* Extended Sequencer Mode: 256c col. mode */
-	    WSeq(SEQR1F, 0x1e);     /* MCLK select */
-	    break;
 
-	case BT_PICCOLO:
-	    WSeq(SEQR7, 0x85);
-	    WSeq(SEQRF, 0xb0);    /* Fast Page-Mode writes */
-	    WSeq(SEQR1F, 0x22);     /* MCLK select */
-	    break;
 
-	case BT_PICASSO:
-	    WSeq(SEQR7, 0x25);
-	    WSeq(SEQRF, 0xb0);    /* Fast Page-Mode writes */
-	    WSeq(SEQR1F, 0x22);     /* MCLK select */
-	    break;
 
-	case BT_SPECTRUM:
-	    WSeq(SEQR7, 0x85);
-	    WSeq(SEQRF, 0xb0);    /* Fast Page-Mode writes */
-	    WSeq(SEQR1F, 0x22);     /* MCLK select */
-	    break;
+static int __init clgen_pci_setup (struct clgenfb_info *info,
+				   clgen_board_t *btype)
+{
+#ifdef CONFIG_FB_OF
+	struct device_node *dp;
+#endif				/* CONFIG_FB_OF */
+	struct pci_dev *pdev;
+	unsigned long board_addr, board_size;
+	u16 tmp16;
 
-	case BT_PICASSO4:
-	    WSeq(SEQR7, 0x25);
-/*	    WSeq(SEQR1F, 0x1c);  */
-	    break;
+	DPRINTK ("ENTER\n");
 
-	default:
-	    printk(KERN_WARNING "clgen: unknown Board\n");
-	    break;
+	pdev = clgen_pci_dev_get (btype);
+	if (!pdev) {
+		printk (KERN_ERR " Couldn't find PCI device\n");
+		DPRINTK ("EXIT, returning 1\n");
+		return 1;
 	}
+	DPRINTK (" Found PCI device, base address 0 is 0x%lx, btype set to %d\n",
+		 pdev->resource[0].start, *btype);
+	DPRINTK (" base address 1 is 0x%lx\n", pdev->resource[1].start);
 
-	WGfx(GR5,    64);     /* mode register: 256 color mode */
-	WGen(M_3C6,0xff);     /* pixel mask: pass-through all planes */
-	WHDR(0xc5);           /* hidden dac reg: 8-8-8 mode (24 or 32) */
-	WSeq(SEQR4,  0x0a);     /* memory mode: chain4, ext. memory */
-	WSeq(SEQR2,  0xff);     /* plane mask: enable writing to all 4 planes */
-	offset			= _par->var.xres_virtual / 4;
-    }
-    else
-	printk(KERN_ERR "clgen: What's this?? requested color depth == %d.\n",
-		_par->var.bits_per_pixel);
-
-    WCrt(CRT13, offset & 0xff);
-    tmp = 0x22;
-    if (offset & 0x100) tmp |= 0x10; /* offset overflow bit */
-    	
-    WCrt(CRT1B,tmp);    /* screen start addr #16-18, fastpagemode cycles */
-
-    if (fb_info->btype == BT_SD64 || fb_info->btype == BT_PICASSO4)
-    	WCrt(CRT1D, 0x00);   /* screen start address bit 19 */
-
-    WCrt(CRTE,    0);      /* text cursor location high */
-    WCrt(CRTF,    0);      /* text cursor location low */
-    WCrt(CRT14,   0);      /* underline row scanline = at very bottom */
-
-    WAttr(AR10,  1);      /* controller mode */
-    WAttr(AR11,  0);      /* overscan (border) color */
-    WAttr(AR12, 15);      /* color plane enable */
-    WAttr(AR33,  0);      /* pixel panning */
-    WAttr(AR14,  0);      /* color select */
-
-    /* [ EGS: SetOffset(); ] */
-    /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */
-    AttrOn();
-
-    WGfx(GR0,    0);      /* set/reset register */
-    WGfx(GR1,    0);      /* set/reset enable */
-    WGfx(GR2,    0);      /* color compare */
-    WGfx(GR3,    0);      /* data rotate */
-    WGfx(GR4,    0);      /* read map select */
-    WGfx(GR6,    1);      /* miscellaneous register */
-    WGfx(GR7,   15);      /* color don't care */
-    WGfx(GR8,  255);      /* bit mask */
-
-    WSeq(SEQR12,  0x0);     /* graphics cursor attributes: nothing special */
-
-    /* finally, turn on everything - turn off "FullBandwidth" bit */
-    /* also, set "DotClock%2" bit where requested */
-    tmp = 0x01;
+	info->pdev = pdev;
 
-/*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ?
-    if (var->vmode & FB_VMODE_CLOCK_HALVE)
-	tmp |= 0x08;
-*/
+#ifdef CONFIG_PREP
+	/* Xbh does this, though 0 seems to be the init value */
+	pcibios_write_config_dword (0, pdev->devfn, PCI_BASE_ADDRESS_0, 0x00000000);
+#endif
 
-    WSeq(SEQR1, tmp);
-    DEBUG printk("SEQR1: %d\n", tmp);
+	pci_read_config_word (pdev, PCI_COMMAND, &tmp16);
+	if (!(tmp16 & (PCI_COMMAND_MEMORY | PCI_COMMAND_IO))) {
+		tmp16 |= PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
+		pci_write_config_word (pdev, PCI_COMMAND, tmp16);
+	}
+
+#ifdef CONFIG_FB_OF
+	/* Ok, so its an ugly hack, since we could have passed it down from
+	 * clgen_of_init() if we'd done it right. */
+	DPRINTK ("Attempt to get OF info for MacPicasso\n");
+	dp = find_devices ("MacPicasso");
+	if (dp != 0) {
+		if (dp->n_addrs != 2) {
+			printk (KERN_ERR "expecting 2 address for clgen (got %d)\n", dp->n_addrs);
+			DPRINTK ("EXIT, returning 1\n");
+			return 1;
+		}
+		get_of_addrs (dp, &board_addr, &info->fbregs_phys);
+	} else
+#endif
+	{
 
-#if 0
-    DEBUG printk(KERN_INFO "clgen: clearing display...");
-    clgen_RectFill(0, 0, _par->HorizRes, _par->VertRes, 0, _par->line_length);
-    clgen_WaitBLT();
-    DEBUG printk("done.\n");
+#ifdef CONFIG_PREP
+		get_prep_addrs (&board_addr, &info->fbregs_phys);
+#else				/* CONFIG_PREP */
+		DPRINTK ("Attempt to get PCI info for Cirrus Graphics Card\n");
+		get_pci_addrs (pdev, &board_addr, &info->fbregs_phys);
+#endif				/* CONFIG_PREP */
+	}
+
+	DPRINTK ("Board address: 0x%lx, register address: 0x%lx\n", board_addr, info->fbregs_phys);
+
+#ifdef CONFIG_PREP
+	/* PReP dies if we ioremap the IO registers, but it works w/out... */
+	info->regs = (char *) info->fbregs_phys;
+#else
+	info->regs = 0;		/* FIXME: this forces VGA.  alternatives? */
 #endif
 
-    fb_info->currentmode = *_par;
+	if (*btype == BT_GD5480) {
+		board_size = 32 * MB_;
+	} else {
+		board_size = clgen_get_memsize (info->regs);
+	}
+	info->fbmem = ioremap (board_addr, board_size);
+	info->fbmem_phys = board_addr;
+
+	printk (" RAM (%lu MB) at $%lx, ", board_size / 0x100000, board_addr);
 
-    printk("virtual offset: (%d,%d)\n", _par->var.xoffset,_par->var.yoffset);
-    /* pan to requested offset */
-    clgen_pan_display (&fb_info->currentmode.var, (struct fb_info_gen*)fb_info);
+	printk (KERN_INFO "Cirrus Logic chipset on PCI bus\n");
 
-    DEBUG printk("<clgen_set_par()\n");
-    return;
+	DPRINTK ("EXIT, returning 0\n");
+	return 0;
 }
+#endif				/* CONFIG_PCI */
 
-static int clgen_getcolreg(unsigned regno, unsigned *red, unsigned *green,
-			   unsigned *blue, unsigned *transp,
-			   struct fb_info *info)
-{
-    unsigned char bred, bgreen, bblue;
 
-    if (regno > 255)
-	return (1);
 
-    fb_info = (struct clgenfb_info *)info;
 
-    RClut(regno, &bred, &bgreen, &bblue);
+#ifdef CONFIG_ZORRO
+static int __init clgen_zorro_find (int *key_o, int *key2_o, clgen_board_t *btype)
+{
+	int i, key = 0;
+	
+	assert (key_o != NULL);
+	assert (btype != NULL);
 
-    *red = (bred<<10) | (bred<<4) | (bred>>2);
-    *green = (bgreen<<10) | (bgreen<<4) | (bgreen>>2);
-    *blue = (bblue<<10) | (bblue<<4) | (bblue>>2);
-    *transp = 0;
-    return (0);
+	for (i = 0; i < arraysize(clgen_zorro_probe_list) && !key; i++)
+		key = zorro_find (clgen_zorro_probe_list[i].key, 0, 0);
+
+	if (key) {
+		*key_o = key;
+		if (clgen_zorro_probe_list[i].key2)
+			*key2_o = zorro_find (clgen_zorro_probe_list[i].key2, 0, 0);
+		else
+			*key2_o = 0;
+		*btype = clgen_zorro_probe_list[i].btype;
+		
+		printk (KERN_INFO "clgen: %s board detected; ",
+			clgen_board_info[*btype].name);
+		
+		return 0;
+	}
+	
+	printk (KERN_NOTICE "clgen: no supported board found.\n");
+	return -1;
 }
 
-static int clgen_setcolreg(unsigned regno, unsigned red, unsigned green,
-			   unsigned blue, unsigned transp, 
-			   struct fb_info *info)
+
+
+static int __init clgen_zorro_setup (struct clgenfb_info *info,
+				     clgen_board_t *btype)
 {
-    if (regno > 255)
-	return (1);
+	int key = 0, key2 = 0;
+	const struct ConfigDev *cd = NULL;
+	const struct ConfigDev *cd2 = NULL;
+	unsigned long board_addr, board_size;
+	
+	assert (info != NULL);
+	assert (btype != NULL);
 
-    fb_info = (struct clgenfb_info *)info;
-    
-    /* "transparent" stuff is completely ignored. */
-    WClut(regno, red>>10, green>>10, blue>>10);
+	if (clgen_zorro_find (&key, &key2, btype))
+		return -1;
 
-    return (0);
-}
+	assert (key > 0);
+	assert (key2 >= 0);
+	assert (*btype != BT_NONE);
+	
+	info->keyRAM = key;
+	info->keyREG = key2;
+	cd = zorro_get_board (key);
+	board_addr = (unsigned long) cd->cd_BoardAddr;
+	board_size = (unsigned long) cd->cd_BoardSize;
+	printk (" RAM (%lu MB) at $%lx, ", board_size / 0x100000, board_addr);
+
+	if (*btype == BT_PICASSO4) {
+		printk (" REG at $%lx\n", board_addr + 0x600000);
+
+		/* To be precise, for the P4 this is not the */
+		/* begin of the board, but the begin of RAM. */
+		/* for P4, map in its address space in 2 chunks (### TEST! ) */
+		/* (note the ugly hardcoded 16M number) */
+		info->regs = ioremap (board_addr, 16777216);
+		DPRINTK ("clgen: Virtual address for board set to: $%p\n", info->regs);
+		info->regs += 0x600000;
+		info->fbregs_phys = board_addr + 0x600000;
+
+		info->fbmem_phys = board_addr + 16777216;
+		info->fbmem = ioremap (info->fbmem_phys, 16777216);
+	} else {
+		cd2 = zorro_get_board (key2);
+		printk (" REG at $%lx\n", (unsigned long) cd2->cd_BoardAddr);
+
+		info->fbmem_phys = board_addr;
+		if (board_addr > 0x01000000)
+			info->fbmem = ioremap (board_addr, board_size);
+		else
+			info->fbmem = (caddr_t) ZTWO_VADDR (board_addr);
 
-/*************************************************************************
-	clgen_pan_display()
+		/* set address for REG area of board */
+		info->regs = (caddr_t) ZTWO_VADDR (cd2->cd_BoardAddr);
+		info->fbregs_phys = (unsigned long) cd2->cd_BoardAddr;
 
-	performs display panning - provided hardware permits this
-**************************************************************************/
-static int clgen_pan_display(const struct fb_var_screeninfo *var,
-			     struct fb_info_gen *info)
-{
-    int xoffset = 0;
-    int yoffset = 0;
-    unsigned long base;
-    unsigned char tmp = 0, tmp2 = 0, xpix;
-
-    fb_info = (struct clgenfb_info*)fb_info;
-
-    /* no range checks for xoffset and yoffset,   */
-    /* as fbgen_pan_display has already done this */
-
-    fb_info->currentmode.var.xoffset = var->xoffset;
-    fb_info->currentmode.var.yoffset = var->yoffset;
-
-    xoffset = var->xoffset * fb_info->currentmode.var.bits_per_pixel / 8;
-    yoffset = var->yoffset;
-
-    base = yoffset * fb_info->currentmode.line_length + xoffset;
-
-    if (fb_info->currentmode.var.bits_per_pixel == 1)
-    {
-	/* base is already correct */
-	xpix = (unsigned char)(var->xoffset % 8);
-    }
-    else
-    {
-	base /= 4;
-	xpix = (unsigned char)((xoffset % 4) * 2);
-    }
-
-    /* lower 8 + 8 bits of screen start address */
-    WCrt(CRTD, (unsigned char)(base & 0xff));
-    WCrt(CRTC, (unsigned char)(base >> 8));
-
-    /* construct bits 16, 17 and 18 of screen start address */
-    if (base & 0x10000) tmp |= 0x01;
-    if (base & 0x20000) tmp |= 0x04;
-    if (base & 0x40000) tmp |= 0x08;
-
-    tmp2 = (RCrt(CRT1B) & 0xf2) | tmp; /* 0xf2 is %11110010, exclude tmp bits */
-    WCrt(CRT1B, tmp2);
-    /* construct bit 19 of screen start address (only on SD64) */
-    if (fb_info->btype == BT_SD64 ||
-	fb_info->btype == BT_PICASSO4)
-    {
-	tmp2 = 0;
-	if (base & 0x80000) tmp2 = 0x80;
-	WCrt(CRT1D, tmp2);
-    }
-
-    /* write pixel panning value to AR33; this does not quite work in 8bpp */
-    /* ### Piccolo..? Will this work? */
-    if (fb_info->currentmode.var.bits_per_pixel == 1)
-	WAttr(AR33, xpix);
-
-    return(0);
-}
-
-
-static int clgen_blank(int blank_mode, struct fb_info_gen *info)
-{
-    unsigned char val;
-    printk(">clgen_blank(%d)\n",blank_mode);
-
-    fb_info = (struct clgenfb_info *)info;
-
-    val = RSeq(SEQR1);
-    if (blank_mode)
-	WSeq(SEQR1, val | 0x20); /* set "FullBandwidth" bit */
-    else
-	WSeq(SEQR1, val & 0xdf); /* clear "FullBandwidth" bit */
+		DPRINTK ("clgen: Virtual address for board set to: $%p\n", info->regs);
+	}
+
+	/* mark this board as "autoconfigured" */
+	zorro_config_board (key, 0);
+	if (*btype != BT_PICASSO4)
+		zorro_config_board (key2, 0);
 
-    printk("<clgen_blank()\n");
-    return 0;
+	printk (KERN_INFO "Cirrus Logic chipset on Zorro bus\n");
+	
+	return 0;
 }
+#endif /* CONFIG_ZORRO */
 
-/**** END   Hardware specific Routines **************************************/
-/****************************************************************************/
-/**** BEGIN Internal Routines ***********************************************/
 
-static void init_vgachip(void)
+
+/********************************************************************/
+/* clgenfb_init() - master initialization function                  */
+/********************************************************************/
+int __init clgenfb_init(void)
 {
-    printk(">init_vgachip()\n");
+	int err;
 
-    /* reset board globally */
-    switch(fb_info->btype)
-    {
-    case BT_SD64:     WSFR(0x1f);  udelay(500); WSFR(0x4f); udelay(500); break;
-    case BT_PICCOLO:  WSFR(0x01);  udelay(500); WSFR(0x51); udelay(500); break;
-    case BT_PICASSO:  WSFR2(0xff); udelay(500);				 break;
-    case BT_SPECTRUM: WSFR(0x1f);  udelay(500); WSFR(0x4f); udelay(500); break;
-    case BT_PICASSO4: 
-	WCrt(CRT51, 0x00); /* disable flickerfixer */
-	udelay(100000);
-	WGfx(GR2F, 0x00); /* from Klaus' NetBSD driver: */
-	WGfx(GR33, 0x00); /* put blitter into 542x compat */
-	WGfx(GR31, 0x00); /* mode */
-	break;
-
-    default:
-	printk(KERN_ERR "clgen: Warning: Unknown board type\n");
-	break;
-    }
-
-    /* "pre-set" a RAMsize; if the test succeeds, double it */
-    if (fb_info->btype == BT_SD64 ||
-        fb_info->btype == BT_PICASSO4)
-        fb_info->size = 0x400000;
-    else
-        fb_info->size = 0x200000;
-
-    /* assume it's a "large memory" board (2/4 MB) */
-    fb_info->smallboard = FALSE;
-
-    /* the P4 is not fully initialized here; I rely on it having been */
-    /* inited under AmigaOS already, which seems to work just fine    */
-    /* (Klaus advised to do it this way)                              */
-
-    if (fb_info->btype != BT_PICASSO4)
-    {
-	WGen(VSSM, 0x10);  /* EGS: 0x16 */
-	WGen(POS102, 0x01);
-	WGen(VSSM, 0x08);  /* EGS: 0x0e */
-
-	if(fb_info->btype != BT_SD64)
-		WGen(VSSM2, 0x01);
-
-	WSeq(SEQR0, 0x03);  /* reset sequencer logic */
-
-	WSeq(SEQR1, 0x21);  /* FullBandwidth (video off) and 8/9 dot clock */
-	WGen(MISC_W, 0xc1);  /* polarity (-/-), disable access to display memory, CRTC base address: color */
+	clgen_board_t btype = BT_NONE;
+	struct clgenfb_info *fb_info = NULL;
 
-/*	WGfx(GRA, 0xce);    "magic cookie" - doesn't make any sense to me.. */
-	WSeq(SEQR6, 0x12);   /* unlock all extension registers */
+	DPRINTK ("ENTER\n");
 
-	WGfx(GR31, 0x04);  /* reset blitter */
+	printk (KERN_INFO "clgen: Driver for Cirrus Logic based graphic boards, v" CLGEN_VERSION "\n");
 
-	if (fb_info->btype == BT_SD64)
-	{
-	    WSeq(SEQRF, 0xb8);  /* 4 MB Ram SD64, disable CRT fifo(!), 64 bit bus */
+	fb_info = &boards[0];	/* FIXME support multiple boards ... */
+
+#ifdef CONFIG_PCI
+	if (clgen_pci_setup (fb_info, &btype)) { /* Also does OF setup */
+		DPRINTK ("EXIT, returning -ENXIO\n");
+		return -ENXIO;
 	}
-	else
-	{
-	    WSeq(SEQR16, 0x0f); /* Perf. Tuning: Fix value..(?) */
-	    WSeq(SEQRF, 0xb0); /* 2 MB DRAM, 8level write buffer, 32bit bus */
+
+#elif CONFIG_ZORRO
+	if (clgen_zorro_setup (fb_info, &btype)) {
+		DPRINTK ("EXIT, returning -ENXIO\n");
+		return -ENXIO;
 	}
-    }
 
-    WSeq(SEQR2, 0xff);  /* plane mask: nothing */
-    WSeq(SEQR3, 0x00);  /* character map select: doesn't even matter in gx mode */
-    WSeq(SEQR4, 0x0e);  /* memory mode: chain-4, no odd/even, ext. memory */
-
-    /* controller-internal base address of video memory */
-    switch(fb_info->btype)
-    {
-    case BT_SD64:     WSeq(SEQR7, 0xf0); break;
-    case BT_PICCOLO:  WSeq(SEQR7, 0x80); break;
-    case BT_SPECTRUM: WSeq(SEQR7, 0x80); break;
-    case BT_PICASSO:  WSeq(SEQR7, 0x20); break;
-    case BT_PICASSO4: WSeq(SEQR7, 0x20); break;
-    }
-
-/*  WSeq(SEQR8, 0x00);*/  /* EEPROM control: shouldn't be necessary to write to this at all.. */
-
-    WSeq(SEQR10, 0x00); /* graphics cursor X position (incomplete; position gives rem. 3 bits */
-    WSeq(SEQR11, 0x00); /* graphics cursor Y position (..."... ) */
-    WSeq(SEQR12, 0x00); /* graphics cursor attributes */
-    WSeq(SEQR13, 0x00); /* graphics cursor pattern address */
-
-    /* writing these on a P4 might give problems..  */
-    if (fb_info->btype != BT_PICASSO4)
-    {
-	WSeq(SEQR17, 0x00); /* configuration readback and ext. color */
-	WSeq(SEQR18, 0x02); /* signature generator */
-    }
-
-    /* MCLK select etc. */
-    switch(fb_info->btype)
-    {
-    case BT_PICCOLO:
-    case BT_PICASSO:
-    case BT_SPECTRUM:  WSeq(SEQR1F, 0x22); break;
-    case BT_SD64:      WSeq(SEQR1F, 0x20); break;
-    case BT_PICASSO4:/*WSeq(SEQR1F, 0x1c); */ break;
-    }
-
-    WCrt(CRT8, 0x00);  /* Screen A preset row scan: none */
-    WCrt(CRTA, 0x20);  /* Text cursor start: disable text cursor */
-    WCrt(CRTB, 0x00);  /* Text cursor end: - */
-    WCrt(CRTC, 0x00);  /* Screen start address high: 0 */
-    WCrt(CRTD, 0x00);  /* Screen start address low: 0 */
-    WCrt(CRTE, 0x00);  /* text cursor location high: 0 */
-    WCrt(CRTF, 0x00);  /* text cursor location low: 0 */
-
-    WCrt(CRT14, 0x00); /* Underline Row scanline: - */
-    WCrt(CRT17, 0xc3); /* mode control: timing enable, byte mode, no compat modes */
-    WCrt(CRT18, 0x00); /* Line Compare: not needed */
-    /* ### add 0x40 for text modes with > 30 MHz pixclock */
-    WCrt(CRT1B, 0x02); /* ext. display controls: ext.adr. wrap */
-
-    WGfx(GR0, 0x00); /* Set/Reset registes: - */
-    WGfx(GR1, 0x00); /* Set/Reset enable: - */
-    WGfx(GR2, 0x00); /* Color Compare: - */
-    WGfx(GR3, 0x00); /* Data Rotate: - */
-    WGfx(GR4, 0x00); /* Read Map Select: - */
-    WGfx(GR5, 0x00); /* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */
-    WGfx(GR6, 0x01); /* Miscellaneous: memory map base address, graphics mode */
-    WGfx(GR7, 0x0f); /* Color Don't care: involve all planes */
-    WGfx(GR8, 0xff); /* Bit Mask: no mask at all */
-    WGfx(GRB, 0x28); /* Graphics controller mode extensions: finer granularity, 8byte data latches */
-
-    WGfx(GRC, 0xff); /* Color Key compare: - */
-    WGfx(GRD, 0x00); /* Color Key compare mask: - */
-    WGfx(GRE, 0x00); /* Miscellaneous control: - */
-/*  WGfx(GR10, 0x00);*/ /* Background color byte 1: - */
-/*  WGfx(GR11, 0x00); */
-
-    WAttr(AR0, 0x00); /* Attribute Controller palette registers: "identity mapping" */
-    WAttr(AR1, 0x01);
-    WAttr(AR2, 0x02);
-    WAttr(AR3, 0x03);
-    WAttr(AR4, 0x04);
-    WAttr(AR5, 0x05);
-    WAttr(AR6, 0x06);
-    WAttr(AR7, 0x07);
-    WAttr(AR8, 0x08);
-    WAttr(AR9, 0x09);
-    WAttr(ARA, 0x0a);
-    WAttr(ARB, 0x0b);
-    WAttr(ARC, 0x0c);
-    WAttr(ARD, 0x0d);
-    WAttr(ARE, 0x0e);
-    WAttr(ARF, 0x0f);
-
-    WAttr(AR10, 0x01); /* Attribute Controller mode: graphics mode */
-    WAttr(AR11, 0x00); /* Overscan color reg.: reg. 0 */
-    WAttr(AR12, 0x0f); /* Color Plane enable: Enable all 4 planes */
-/* ### 	WAttr(AR33, 0x00); * Pixel Panning: - */
-    WAttr(AR14, 0x00); /* Color Select: - */
-
-    WGen(M_3C6, 0xff); /* Pixel mask: no mask */
-
-    WGen(MISC_W, 0xc3); /* polarity (-/-), enable display mem, CRTC i/o base = color */
-
-    WGfx(GR31, 0x04); /* BLT Start/status: Blitter reset */
-    WGfx(GR31, 0x00); /* - " -           : "end-of-reset" */
-
-    /* CLUT setup */
-    WClut( 0, 0x00, 0x00, 0x00);  /* background: black */
-    WClut( 1, 0x3f, 0x3f, 0x3f);  /* foreground: white */
-    WClut( 2, 0x00, 0x20, 0x00);
-    WClut( 3, 0x00, 0x20, 0x20);
-    WClut( 4, 0x20, 0x00, 0x00);
-    WClut( 5, 0x20, 0x00, 0x20);
-    WClut( 6, 0x20, 0x10, 0x00);
-    WClut( 7, 0x20, 0x20, 0x20);
-    WClut( 8, 0x10, 0x10, 0x10);
-    WClut( 9, 0x10, 0x10, 0x30);
-    WClut(10, 0x10, 0x30, 0x10);
-    WClut(11, 0x10, 0x30, 0x30);
-    WClut(12, 0x30, 0x10, 0x10);
-    WClut(13, 0x30, 0x10, 0x30);
-    WClut(14, 0x30, 0x30, 0x10);
-    WClut(15, 0x30, 0x30, 0x30);
+#else
+#error Unsupported bus.  Supported: PCI, Zorro
+#endif				/* !CONFIG_PCI, !CONFIG_ZORRO */
 
-    /* the rest a grey ramp */
-    {
-	int i;
+	/* sanity checks */
+	assert (btype != BT_NONE);
+	assert (btype == clgen_board_info[btype].btype);
 
-	for (i = 16; i < 256; i++)
-	    WClut(i, i>>2, i>>2, i>>2);
-    }
+	fb_info->btype = btype;
 
+	DPRINTK ("clgen: (RAM start set to: 0x%p)\n", fb_info->fbmem);
 
-    /* misc... */
-    WHDR(0); /* Hidden DAC register: - */
+	init_vgachip (fb_info);
 
-#if 0
-    /* check for 1/2 MB Piccolo/Picasso/Spectrum resp. 2/4 MB SD64 */
-    /* DRAM register has already been pre-set for "large", so it is*/
-    /* only modified if we find that this is a "small" version */
-    {
-	unsigned volatile char *ram = fb_info->fbmem;
-	int i, flag = 0;
+	/* set up a few more things, register framebuffer driver etc */
+	fb_info->gen.parsize = sizeof (struct clgenfb_par);
+	fb_info->gen.fbhw = &clgen_hwswitch;
 
-	ram += (fb_info->size >> 1);
+	strncpy (fb_info->gen.info.modename, clgen_board_info[btype].name,
+		 sizeof (fb_info->gen.info.modename));
+	fb_info->gen.info.modename [sizeof (fb_info->gen.info.modename) - 1] = 0;
 
-	for (i = 0; i < 256; i++)
-	    ram[i] = (unsigned char)i;
+	fb_info->gen.info.node = -1;
+	fb_info->gen.info.fbops = &clgenfb_ops;
+	fb_info->gen.info.disp = &disp;
+	fb_info->gen.info.changevar = NULL;
+	fb_info->gen.info.switch_con = &fbgen_switch;
+	fb_info->gen.info.updatevar = &fbgen_update_var;
+	fb_info->gen.info.blank = &fbgen_blank;
+	fb_info->gen.info.flags = FBINFO_FLAG_DEFAULT;
 
-	for (i = 0; i < 256; i++)
-	{
-	    if (ram[i] != i)
-		flag = 1;
-	}
+	/* now that we know the board has been registered n' stuff, we */
+	/* can finally initialize it to a default mode */
+	clgenfb_default = clgenfb_predefined[clgen_def_mode].var;
+	clgenfb_default.activate = FB_ACTIVATE_NOW;
+	clgenfb_default.yres_virtual = 480 * 3;		/* for fast scrolling (YPAN-Mode) */
+	err = fbgen_do_set_var (&clgenfb_default, 1, &fb_info->gen);
 
-	/* if the DRAM test failed, halve RAM value */
-	if (flag)
-	{
-	    fb_info->size /= 2;
-	    fb_info->smallboard = TRUE;
-	    switch(fb_info->btype)
-	    {
-	    case BT_SD64:     WSeq(SEQRF, 0x38); break; /* 2 MB Ram SD64 */
-	    case BT_PICASSO4: WSeq(SEQRF, 0x38); break; /* ### like SD64? */
-	    case BT_PICCOLO:
-	    case BT_PICASSO:
-	    case BT_SPECTRUM: WSeq(SEQRF, 0x30); break; /* 1 MB DRAM */
-	    default:
-		printk(KERN_WARNING "clgen: Uuhh..could not determine RAM size!\n");
-	    }
-	}
-
-    }
-#endif
-    printk(KERN_INFO "clgen: This board has %ld bytes of DRAM memory\n", fb_info->size);
-    printk("<init_vgachip()\n");
-    return;
-}
-
-static void switch_monitor(int on)
-{
-    static int IsOn = 0;    /* XXX not ok for multiple boards */
-
-    if (fb_info->btype == BT_PICASSO4) return; /* nothing to switch */
-    if (fb_info->btype == BT_PICASSO)
-    {
-	if ((on && !IsOn) || (!on && IsOn))
-	    WSFR(0xff);
-	return;
-    }    
-    if (on)
-        switch(fb_info->btype)
-	{
-        case BT_SD64:     WSFR(fb_info->SFR | 0x21);	break;
-        case BT_PICCOLO:  WSFR(fb_info->SFR | 0x28);	break;
-        case BT_SPECTRUM: WSFR(0x6f);			break;
+	if (err) {
+		DPRINTK ("EXIT, returning -EINVAL\n");
+		return -EINVAL;
 	}
-    else
-        switch(fb_info->btype)
-	{
-        case BT_SD64:     WSFR(fb_info->SFR & 0xde);	break;
-        case BT_PICCOLO:  WSFR(fb_info->SFR & 0xd7);	break;
-        case BT_SPECTRUM: WSFR(0x4f);			break;
-	}
-}
-
-static void clgen_set_disp(const void *par, struct display *disp,
-			   struct fb_info_gen *info)
-{
-    struct clgenfb_par *_par = (struct clgenfb_par*) par;
-    struct clgenfb_info *info2 = (struct clgenfb_info *)info;
-
-    printk("clgen_set_disp(): ");
-    disp->screen_base = info2->fbmem;
-    switch (_par->var.bits_per_pixel)
-    {
-#ifdef FBCON_HAS_MFB
-    case 1:
-	printk("monochrome\n");
-	disp->dispsw = &fbcon_mfb;
-	break;
-#endif
-#ifdef FBCON_HAS_CFB8
-    case 8:
-	printk("8 bit color depth\n");
-	disp->dispsw = &fbcon_clgen_8;
-	break;
-#endif
-#ifdef FBCON_HAS_CFB16
-    case 16:
-	printk("16 bit color depth\n");
-	disp->dispsw = &fbcon_cfb16;
-	disp->dispsw_data = info2->fbcon_cmap.cfb16;
-	break;
-#endif
-#ifdef FBCON_HAS_CFB24
-    case 24:
-	printk("24 bit color depth\n");
-	disp->dispsw = &fbcon_cfb24;
-	disp->dispsw_data = info2->fbcon_cmap.cfb24;
-	break;
-#endif
-#ifdef FBCON_HAS_CFB32
-    case 32:
-	printk("32 bit color depth\n");
-	disp->dispsw = &fbcon_cfb32;
-	disp->dispsw_data = info2->fbcon_cmap.cfb32;
-	break;
-#endif
 
-    default:
-	printk("unsupported color depth\n");
-	disp->dispsw = &fbcon_dummy;
-	break;
-    }
-}
+	disp.var = clgenfb_default;
+	fbgen_set_disp (-1, &fb_info->gen);
+	fbgen_install_cmap (0, &fb_info->gen);
 
-static void fbcon_clgen8_bmove(struct display *p, int sy, int sx, 
-				int dy, int dx, int height, int width)
-{
-    sx     *= fontwidth(p);
-    sy     *= fontheight(p);
-    dx     *= fontwidth(p);
-    dy     *= fontheight(p);
-    width  *= fontwidth(p);
-    height *= fontheight(p);
-
-    fb_info = (struct clgenfb_info*)p->fb_info;
-
-    clgen_BitBLT((unsigned short)sx, (unsigned short)sy,
-		 (unsigned short)dx, (unsigned short)dy,
-		 (unsigned short)width, (unsigned short)height,
-		 fb_info->currentmode.line_length);
-    clgen_WaitBLT();
+	err = register_framebuffer (&fb_info->gen.info);
+	if (err) {
+		printk (KERN_ERR "clgen: ERROR - could not register fb device; err = %d!\n", err);
+		DPRINTK ("EXIT, returning -EINVAL\n");
+		return -EINVAL;
+	}
+	DPRINTK ("EXIT, returning 0\n");
+	return 0;
 }
 
-static void fbcon_clgen8_clear(struct vc_data *conp, struct display *p, 
-				int sy, int sx, int height, int width)
-{
-    unsigned short col;
-    
-    fb_info = (struct clgenfb_info*)p->fb_info;
-
-    sx     *= fontwidth(p);
-    sy     *= fontheight(p);
-    width  *= fontwidth(p);
-    height *= fontheight(p);
-
-    col = attr_bgcol_ec(p, conp);
-    col &= 0xff;
-
-    clgen_RectFill((unsigned short)sx, (unsigned short)sy,
-		    (unsigned short)width,(unsigned short)height,
-		     col, fb_info->currentmode.line_length);
-    clgen_WaitBLT();
-}
 
 
-/********************************************************************/
-/* clgenfb_init() - master initialization function                  */
-/********************************************************************/
-void __init clgenfb_init(void)
+#if defined(CONFIG_FB_OF)
+int __init clgen_of_init (struct device_node *dp)
 {
-    const struct ConfigDev *cd  = NULL;
-    const struct ConfigDev *cd2 = NULL;
-    int err;
-    int btype;
-    int key,key2;
-    unsigned long board_addr,board_size;
-
-    printk(">clgenfb_init()\n");
-    printk(KERN_INFO "clgen: Driver for Cirrus Logic based graphic boards, v" CLGEN_VERSION "\n");
-
-    btype = -1;
-
-    if ((key = zorro_find(ZORRO_PROD_HELFRICH_SD64_RAM, 0, 0)))
-    {
-	key2 = zorro_find(ZORRO_PROD_HELFRICH_SD64_REG, 0, 0);
-        btype = BT_SD64;
-        printk(KERN_INFO "clgen: SD64 board detected; ");
-    }
-    else if ((key = zorro_find(ZORRO_PROD_HELFRICH_PICCOLO_RAM, 0, 0)))
-    {
-        key2      = zorro_find(ZORRO_PROD_HELFRICH_PICCOLO_REG, 0, 0);
-    	btype = BT_PICCOLO;
-    	printk(KERN_INFO "clgen: Piccolo board detected; ");
-    }
-    else if ((key = zorro_find(ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM, 0, 0)))
-    {
-        key2      = zorro_find(ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG, 0, 0);
-	btype = BT_PICASSO;
-    	printk(KERN_INFO "clgen: Picasso II board detected; ");
-    }
-    else if ((key = zorro_find(ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM, 0, 0)))
-    {
-        key2      = zorro_find(ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG, 0, 0);
-        btype = BT_SPECTRUM;
-        printk(KERN_INFO "clgen: Spectrum board detected; ");
-    }
-    else if ((key = zorro_find(ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3, 0, 0)))
-    {
-        btype = BT_PICASSO4;
-        printk(KERN_INFO "clgen: Picasso 4 board detected; ");
-    }
-    else
-    {
-	printk(KERN_NOTICE "clgen: no supported board found.\n");
-	return;
-    }
-    
-    fb_info = &boards[0]; /* FIXME support multiple boards ...*/
-    
-    fb_info->keyRAM = key;
-    fb_info->keyREG = key2;
-    fb_info->btype  = btype;
-    
-    cd = zorro_get_board(key);
-    board_addr = (unsigned long)cd->cd_BoardAddr;
-    board_size = (unsigned long)cd->cd_BoardSize;
-    printk(" RAM (%lu MB) at $%lx, ", board_size/0x100000, board_addr);
-
-    if (btype == BT_PICASSO4)
-    {
-	printk(" REG at $%lx\n", board_addr + 0x600000);
-
-        /* To be precise, for the P4 this is not the */
-        /* begin of the board, but the begin of RAM. */
-	/* for P4, map in its address space in 2 chunks (### TEST! ) */
-	/* (note the ugly hardcoded 16M number) */
-	fb_info->regs = ioremap(board_addr, 16777216);
-        DEBUG printk(KERN_INFO "clgen: Virtual address for board set to: $%p\n", fb_info->regs);
-	fb_info->regs += 0x600000;
-	fb_info->fbregs_phys = board_addr + 0x600000;
-
-	fb_info->fbmem_phys = board_addr + 16777216;
-	fb_info->fbmem = ioremap(fb_info->fbmem_phys, 16777216);
-	DEBUG printk(KERN_INFO "clgen: (RAM start set to: $%lx)\n", fb_info->fbmem);
-    }
-    else
-    {
-        cd2 = zorro_get_board(key2);
-        printk(" REG at $%lx\n", (unsigned long)cd2->cd_BoardAddr);
-
-	fb_info->fbmem_phys = board_addr;
-        if (board_addr > 0x01000000)
-	    fb_info->fbmem = ioremap(board_addr, board_size);
-	else
-	    fb_info->fbmem = ZTWO_VADDR(board_addr);
-
-        /* set address for REG area of board */
-	fb_info->regs = (unsigned char *)ZTWO_VADDR(cd2->cd_BoardAddr);
-	fb_info->fbregs_phys = (unsigned long) cd2->cd_BoardAddr;
-
-        DEBUG printk(KERN_INFO "clgen: Virtual address for board set to: $%p\n", fb_info->regs);
-	DEBUG printk(KERN_INFO "clgen: (RAM start set to: $%lx)\n", fb_info->fbmem);
-    }
-
-    init_vgachip();
-
-    /* set up a few more things, register framebuffer driver etc */
-    fb_info->gen.parsize         = sizeof(struct clgenfb_par);
-    fb_info->gen.fbhw            = &clgen_hwswitch;
-    strcpy (fb_info->gen.info.modename, clgenfb_name);
-    fb_info->gen.info.node       = -1;
-    fb_info->gen.info.fbops      = &clgenfb_ops;
-    fb_info->gen.info.disp       = &disp;
-    fb_info->gen.info.changevar  = NULL;
-    fb_info->gen.info.switch_con = &fbgen_switch;
-    fb_info->gen.info.updatevar  = &fbgen_update_var;
-    fb_info->gen.info.blank      = &fbgen_blank;
-    fb_info->gen.info.flags	 = FBINFO_FLAG_DEFAULT;
-    
-    /* mark this board as "autoconfigured" */
-    zorro_config_board(key, 0);
-    if (btype != BT_PICASSO4)
-	zorro_config_board(key2, 0);
-
-    /* now that we know the board has been registered n' stuff, we */
-    /* can finally initialize it to a default mode (640x480) */
-    clgenfb_default = clgenfb_predefined[1].var;
-    clgenfb_default.activate = FB_ACTIVATE_NOW;
-    clgenfb_default.yres_virtual = 480*3; /* for fast scrolling (YPAN-Mode) */
-    err = fbgen_do_set_var(&clgenfb_default, 1, &fb_info->gen);
+	int rc;
+	
+	DPRINTK ("ENTER\n");
 
-    if (err)
-	return;
+	rc = clgenfb_init ();
 
-    disp.var = clgenfb_default;
-    fbgen_set_disp(-1, &fb_info->gen);
-    fbgen_install_cmap(0, &fb_info->gen);
-
-    err = register_framebuffer(&fb_info->gen.info);
-    if (err)
-    {
-	printk(KERN_ERR "clgen: ERROR - could not register fb device; err = %d!\n", err);
-	return;
-    }
+	DPRINTK ("EXIT, returning %d\n", rc);
 
-    printk("<clgenfb_init()\n");
-    return;
+	return rc;
 }
+#endif				/* CONFIG_FB_OF */
+
+
 
     /*
-     *  Cleanup
+     *  Cleanup (only needed for module)
      */
-
-void clgenfb_cleanup(struct clgenfb_info *info)
+#ifdef MODULE
+static void clgenfb_cleanup (struct clgenfb_info *info)
 {
-    printk(">clgenfb_cleanup()\n");
+	DPRINTK ("ENTER\n");
 
-    fb_info = info;
+#ifdef CONFIG_ZORRO
+	switch_monitor (info, 0);
 
-    switch_monitor(0);
+	zorro_unconfig_board (info->keyRAM, 0);
+	if (info->btype != BT_PICASSO4)
+		zorro_unconfig_board (info->keyREG, 0);
+#endif				/* CONFIG_ZORRO */
 
-    zorro_unconfig_board(info->keyRAM, 0);
-    if (fb_info->btype != BT_PICASSO4)
-	zorro_unconfig_board(info->keyREG, 0);
+	unregister_framebuffer ((struct fb_info *) info);
+	printk ("Framebuffer unregistered\n");
 
-    unregister_framebuffer(&info->gen.info);
-    printk("Framebuffer unregistered\n");
-    printk("<clgenfb_cleanup()\n");
+	DPRINTK ("EXIT\n");
 }
+#endif
 
 
-/* A strtok which returns empty strings, too */
-static char *strtoke(char *s,const char *ct)
-{
-	char *sbegin, *send;
-	static char *ssave = NULL;
 
-	sbegin  = s ? s : ssave;
-	if (!sbegin)
-		return NULL;
-	if (*sbegin == '\0') {
-		ssave = NULL;
-		return NULL;
+
+#ifndef MODULE
+int __init clgenfb_setup(char *options) {
+	char *this_opt, s[32];
+	int i;
+	
+	DPRINTK ("ENTER\n");
+	
+	if (!options || !*options)
+		return 0;
+	
+	for (this_opt = strtok (options, ","); this_opt != NULL;
+	     this_opt = strtok (NULL, ",")) {
+		if (!*this_opt) continue;
+		
+		DPRINTK("clgenfb_setup: option '%s'\n", this_opt);
+		
+		for (i = 0; i < NUM_TOTAL_MODES; i++) {
+			sprintf (s, "mode:%s", clgenfb_predefined[i].name);
+			if (strcmp (this_opt, s) == 0)
+				clgen_def_mode = i;
+		}
 	}
-	send = strpbrk(sbegin, ct);
-	if (send && *send != '\0')
-		*send++ = '\0';
-	ssave = send;
-	return sbegin;
+	return 0;
 }
+#endif
+
 
-/*****************************************************************/
-/* clgenfb_setup() might be used later for parsing possible      */
-/* arguments to the video= bootstrap parameter. Right now, there */
-/* is nothing I do here.                                         */
-/*****************************************************************/
-void __init clgenfb_setup(char *options, int *ints)
-{
-//    char *this_opt;
 
-//    printk("clgenfb_setup(): options: %s\n", options);	
-}
 
 
     /*
@@ -1668,20 +2733,34 @@
      */
 
 #ifdef MODULE
-int init_module(void)
+MODULE_AUTHOR("Copyright 1999 Jeff Garzik <jgarzik@pobox.com>");
+MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips");
+
+int init_module (void)
 {
-    printk("init_module()\n");
-    clgenfb_init();
-    return 0;
+#if defined(CONFIG_FB_OF)
+/* Nothing to do, must be called from offb */
+	return 0;
+#else
+	int i;
+	
+	DPRINTK ("ENTER\n");
+	i = clgenfb_init ();
+	DPRINTK ("EXIT\n");
+	return i;
+#endif
 }
 
-void cleanup_module(void)
+void cleanup_module (void)
 {
-    printk("module_cleanup()\n");
-    clgenfb_cleanup(fb_info);
+	DPRINTK ("ENTER\n");
+
+	clgenfb_cleanup (&boards[0]);	/* FIXME: support multiple boards */
+
+	DPRINTK ("EXIT\n");
 }
-#endif /* MODULE */
 
+#endif				/* MODULE */
 
 
 /**********************************************************************/
@@ -1692,241 +2771,174 @@
 /**********************************************************************/
 
 /*** WGen() - write into one of the external/general registers ***/
-void WGen(int regnum, unsigned char val)
+static void WGen (const struct clgenfb_info *fb_info,
+		  int regnum, unsigned char val)
 {
-	unsigned volatile char *reg = fb_info->regs + regnum;
+	unsigned long regofs = 0;
 
-	if(fb_info->btype == BT_PICASSO)
-	{
+	if (fb_info->btype == BT_PICASSO) {
 		/* Picasso II specific hack */
-/*		if (regnum == M_3C7_W || regnum == M_3C9 || regnum == VSSM2) */
-		if (regnum == M_3C7_W || regnum == M_3C9)
-			reg += 0xfff;
+/*              if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D || regnum == CL_VSSM2) */
+		if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
+			regofs = 0xfff;
 	}
 
-	*reg = val;
+	vga_w (fb_info->regs, regofs + regnum, val);
 }
 
 /*** RGen() - read out one of the external/general registers ***/
-unsigned char RGen(int regnum)
+static unsigned char RGen (const struct clgenfb_info *fb_info, int regnum)
 {
-	unsigned volatile char *reg = fb_info->regs + regnum;
+	unsigned long regofs = 0;
 
-	if(fb_info->btype == BT_PICASSO)
-	{
+	if (fb_info->btype == BT_PICASSO) {
 		/* Picasso II specific hack */
-/*		if (regnum == M_3C7_W || regnum == M_3C9 || regnum == VSSM2) */
-		if (regnum == M_3C7_W || regnum == M_3C9)
-			reg += 0xfff;
+/*              if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D || regnum == CL_VSSM2) */
+		if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
+			regofs = 0xfff;
 	}
 
-	return *reg;
-}
-
-/*** WSeq() - write into a register of the sequencer ***/
-void WSeq(unsigned char regnum, unsigned char val)
-{
-	fb_info->regs[SEQRX]   = regnum;
-	fb_info->regs[SEQRX+1] = val;
-}
-
-/*** RSeq() - read out one of the Sequencer registers ***/
-unsigned char RSeq(unsigned char regnum)
-{
-	fb_info->regs[SEQRX] = regnum;
-	return fb_info->regs[SEQRX+1];
-}
-
-/*** WCrt() - write into a register of the CRT controller ***/
-void WCrt(unsigned char regnum, unsigned char val)
-{
-	fb_info->regs[CRTX]   = regnum;
-	fb_info->regs[CRTX+1] = val;
-}
-
-/*** RCrt() - read out one of the CRT controller registers ***/
-unsigned char RCrt(unsigned char regnum)
-{
-	fb_info->regs[CRTX] = regnum;
-	return fb_info->regs[CRTX+1];
-}
-
-/*** WGfx() - write into a register of the Gfx controller ***/
-void WGfx(unsigned char regnum, unsigned char val)
-{
-	fb_info->regs[GRX]   = regnum;
-	fb_info->regs[GRX+1] = val;
-}
-
-/*** RGfx() - read out one of the Gfx controller registers ***/
-unsigned char RGfx(unsigned char regnum)
-{
-	fb_info->regs[GRX] = regnum;
-	return fb_info->regs[GRX+1];
+	return vga_r (fb_info->regs, regofs + regnum);
 }
 
-/*** WAttr() - write into a register of the Attribute controller ***/
-void WAttr(unsigned char regnum, unsigned char val)
+/*** AttrOn() - turn on VideoEnable for Attribute controller ***/
+static void AttrOn (const struct clgenfb_info *fb_info)
 {
-	/* if the next access to the attribute controller is a data write access, */
-	/* simply write back the information that was already there before, so that */
-	/* the next write access after that will be an index write. */
-	if (RCrt(CRT24) & 0x80)
-		/* can't use WAttr() here - we would go into a recursive loop otherwise */
-		fb_info->regs[ARX] = fb_info->regs[ARX+1];
-
-	if (RCrt(CRT24) & 0x80)
-		printk(KERN_WARNING "clgen: *** AttrIdx BAD!***\n");
+	assert (fb_info != NULL);
 
-	/* now, first set index and after that the value - both to the same address (!) */
-	fb_info->regs[ARX] = regnum;
-	fb_info->regs[ARX] = val;
-}
+	DPRINTK ("ENTER\n");
 
-/*** AttrOn() - turn on VideoEnable for Attribute controller ***/
-void AttrOn()
-{
-	if (RCrt(CRT24) & 0x80)
+	if (vga_rcrt (fb_info->regs, CL_CRT24) & 0x80) {
 		/* if we're just in "write value" mode, write back the */
 		/* same value as before to not modify anything */
-		fb_info->regs[ARX] = fb_info->regs[ARX+1];
-
+		vga_w (fb_info->regs, VGA_ATT_IW,
+		       vga_r (fb_info->regs, VGA_ATT_R));
+	}
 	/* turn on video bit */
-/*	fb_info->regs[ARX] = 0x20; */
-	fb_info->regs[ARX] = 0x33;
+/*      vga_w (fb_info->regs, VGA_ATT_IW, 0x20); */
+	vga_w (fb_info->regs, VGA_ATT_IW, 0x33);
 
 	/* dummy write on Reg0 to be on "write index" mode next time */
-	fb_info->regs[ARX] = 0x00;
-}
-
-/*** RAttr() - read out a register of the Attribute controller ***/
-unsigned char RAttr(unsigned char regnum)
-{
-	/* (explanation see above in WAttr() ) */
-	if (RCrt(CRT24) & 0x80)
-		fb_info->regs[ARX] = fb_info->regs[ARX+1];
+	vga_w (fb_info->regs, VGA_ATT_IW, 0x00);
 
-	fb_info->regs[ARX] = regnum;
-	return fb_info->regs[ARX+1];
+	DPRINTK ("EXIT\n");
 }
 
-
 /*** WHDR() - write into the Hidden DAC register ***/
 /* as the HDR is the only extension register that requires special treatment 
  * (the other extension registers are accessible just like the "ordinary"
  * registers of their functional group) here is a specialized routine for 
  * accessing the HDR
  */
-void WHDR(unsigned char val)
+static void WHDR (const struct clgenfb_info *fb_info, unsigned char val)
 {
 	unsigned char dummy;
 
-	if(fb_info->btype == BT_PICASSO)
-	{
+	if (fb_info->btype == BT_PICASSO) {
 		/* Klaus' hint for correct access to HDR on some boards */
 		/* first write 0 to pixel mask (3c6) */
-		WGen(M_3C6, 0x00); udelay(200);
+		WGen (fb_info, VGA_PEL_MSK, 0x00);
+		udelay (200);
 		/* next read dummy from pixel address (3c8) */
-		dummy = RGen(M_3C8); udelay(200);
+		dummy = RGen (fb_info, VGA_PEL_IW);
+		udelay (200);
 	}
-
 	/* now do the usual stuff to access the HDR */
 
-	dummy = RGen(M_3C6); udelay(200);
-	dummy = RGen(M_3C6); udelay(200);
-	dummy = RGen(M_3C6); udelay(200);
-	dummy = RGen(M_3C6); udelay(200);
+	dummy = RGen (fb_info, VGA_PEL_MSK);
+	udelay (200);
+	dummy = RGen (fb_info, VGA_PEL_MSK);
+	udelay (200);
+	dummy = RGen (fb_info, VGA_PEL_MSK);
+	udelay (200);
+	dummy = RGen (fb_info, VGA_PEL_MSK);
+	udelay (200);
 
-	WGen(M_3C6, val); udelay(200);
+	WGen (fb_info, VGA_PEL_MSK, val);
+	udelay (200);
 
-	if(fb_info->btype == BT_PICASSO)
-	{
+	if (fb_info->btype == BT_PICASSO) {
 		/* now first reset HDR access counter */
-		dummy = RGen(M_3C8); udelay(200);
+		dummy = RGen (fb_info, VGA_PEL_IW);
+		udelay (200);
 
 		/* and at the end, restore the mask value */
 		/* ## is this mask always 0xff? */
-		WGen(M_3C6, 0xff); udelay(200);
+		WGen (fb_info, VGA_PEL_MSK, 0xff);
+		udelay (200);
 	}
 }
 
-/*** RHDR() - read out the Hidden DAC register ***/
-/* I hope this does not break on the GD5428 - cannot test it. */
-/* (Is there any board for the Amiga that uses the 5428 ?) */
-unsigned char RHDR()
-{
-	unsigned char dummy;
-
-	dummy = RGen(M_3C6);
-	dummy = RGen(M_3C6);
-	dummy = RGen(M_3C6);
-	dummy = RGen(M_3C6);
-
-	return RGen(M_3C6);
-}
 
 
 /*** WSFR() - write to the "special function register" (SFR) ***/
-void WSFR(unsigned char val)
+static void WSFR (struct clgenfb_info *fb_info, unsigned char val)
 {
-	fb_info->SFR          = val;
-	fb_info->regs[0x8000] = val;
+#ifdef CONFIG_ZORRO
+	assert (fb_info->regs != NULL);
+	fb_info->SFR = val;
+	writeb (val, fb_info->regs + 0x8000);
+#endif
 }
 
 /* The Picasso has a second register for switching the monitor bit */
-void WSFR2(unsigned char val)
+static void WSFR2 (struct clgenfb_info *fb_info, unsigned char val)
 {
+#ifdef CONFIG_ZORRO
 	/* writing an arbitrary value to this one causes the monitor switcher */
 	/* to flip to Amiga display */
-	fb_info->SFR          = val;
-	fb_info->regs[0x9000] = val;
+	assert (fb_info->regs != NULL);
+	fb_info->SFR = val;
+	writeb (val, fb_info->regs + 0x9000);
+#endif
 }
 
+
 /*** WClut - set CLUT entry (range: 0..63) ***/
-void WClut(unsigned char regnum, unsigned char red, unsigned char green, unsigned char blue)
+static void WClut (struct clgenfb_info *fb_info, unsigned char regnum, unsigned char red,
+	    unsigned char green, unsigned char blue)
 {
-	unsigned int data = 0x3c9;
+	unsigned int data = VGA_PEL_D;
 
 	/* address write mode register is not translated.. */
-	fb_info->regs[0x3c8] = regnum;
+	vga_w (fb_info->regs, VGA_PEL_IW, regnum);
 
-	if(fb_info->btype == BT_PICASSO || fb_info->btype == BT_PICASSO4)
-	{
+	if (fb_info->btype == BT_PICASSO || fb_info->btype == BT_PICASSO4 ||
+	    fb_info->btype == BT_ALPINE || fb_info->btype == BT_GD5480) {
 		/* but DAC data register IS, at least for Picasso II */
-		if(fb_info->btype == BT_PICASSO)
+		if (fb_info->btype == BT_PICASSO)
 			data += 0xfff;
-		fb_info->regs[data] = red;
-		fb_info->regs[data] = green;
-		fb_info->regs[data] = blue;
-	}
-	else
-	{
-		fb_info->regs[data] = blue;
-		fb_info->regs[data] = green;
-		fb_info->regs[data] = red;
+		vga_w (fb_info->regs, data, red);
+		vga_w (fb_info->regs, data, green);
+		vga_w (fb_info->regs, data, blue);
+	} else {
+		vga_w (fb_info->regs, data, blue);
+		vga_w (fb_info->regs, data, green);
+		vga_w (fb_info->regs, data, red);
 	}
 }
 
+
+
 /*** RClut - read CLUT entry (range 0..63) ***/
-void RClut(unsigned char regnum, unsigned char *red, unsigned char *green, unsigned char *blue)
+static void RClut (struct clgenfb_info *fb_info, unsigned char regnum, unsigned char *red,
+	    unsigned char *green, unsigned char *blue)
 {
-	unsigned int data = 0x3c9;
+	unsigned int data = VGA_PEL_D;
 
-	fb_info->regs[0x3c7] = regnum;
+	vga_w (fb_info->regs, VGA_PEL_IR, regnum);
 
-	if(fb_info->btype == BT_PICASSO || fb_info->btype == BT_PICASSO4)
-	{
-		if(fb_info->btype == BT_PICASSO)
+	if (fb_info->btype == BT_PICASSO || fb_info->btype == BT_PICASSO4 ||
+	    fb_info->btype == BT_ALPINE || fb_info->btype == BT_GD5480) {
+		if (fb_info->btype == BT_PICASSO)
 			data += 0xfff;
-		*red   = fb_info->regs[data];
-		*green = fb_info->regs[data];
-		*blue  = fb_info->regs[data];
-	}
-	else
-	{
-		*blue  = fb_info->regs[data];
-		*green = fb_info->regs[data];
-		*red   = fb_info->regs[data];
+		*red = vga_r (fb_info->regs, data);
+		*green = vga_r (fb_info->regs, data);
+		*blue = vga_r (fb_info->regs, data);
+	} else {
+		*blue = vga_r (fb_info->regs, data);
+		*green = vga_r (fb_info->regs, data);
+		*red = vga_r (fb_info->regs, data);
 	}
 }
 
@@ -1937,11 +2949,12 @@
 	Wait for the BitBLT engine to complete a possible earlier job
 *********************************************************************/
 
-void clgen_WaitBLT()
+/* FIXME: use interrupts instead */
+extern inline void clgen_WaitBLT (caddr_t regbase)
 {
 	/* now busy-wait until we're done */
-	while (RGfx(GR31) & 0x08)
-		;
+	while (vga_rgfx (regbase, CL_GR31) & 0x08)
+		/* do nothing */ ;
 }
 
 /*******************************************************************
@@ -1950,90 +2963,87 @@
 	perform accelerated "scrolling"
 ********************************************************************/
 
-void clgen_BitBLT (u_short curx, u_short cury, u_short destx, u_short desty,
-		u_short width, u_short height, u_short line_length)
+static void clgen_BitBLT (caddr_t regbase, u_short curx, u_short cury, u_short destx, u_short desty,
+		   u_short width, u_short height, u_short line_length)
 {
 	u_short nwidth, nheight;
 	u_long nsrc, ndest;
 	u_char bltmode;
 
+	DPRINTK ("ENTER\n");
+
 	nwidth = width - 1;
 	nheight = height - 1;
 
 	bltmode = 0x00;
 	/* if source adr < dest addr, do the Blt backwards */
-	if (cury <= desty)
-	{
-		if (cury == desty)
-		{
+	if (cury <= desty) {
+		if (cury == desty) {
 			/* if src and dest are on the same line, check x */
 			if (curx < destx)
 				bltmode |= 0x01;
-		}
-		else
+		} else
 			bltmode |= 0x01;
 	}
-
-	if (!bltmode)
-	{
+	if (!bltmode) {
 		/* standard case: forward blitting */
 		nsrc = (cury * line_length) + curx;
 		ndest = (desty * line_length) + destx;
-	}
-	else
-	{
+	} else {
 		/* this means start addresses are at the end, counting backwards */
 		nsrc = cury * line_length + curx + nheight * line_length + nwidth;
 		ndest = desty * line_length + destx + nheight * line_length + nwidth;
 	}
 
-//	clgen_WaitBLT(); /* ### NOT OK for multiple boards! */
+        clgen_WaitBLT(regbase);
 
 	/*
-		run-down of registers to be programmed:
-		destination pitch
-		source pitch
-		BLT width/height
-		source start
-		destination start
-		BLT mode
-		BLT ROP
-		GR0 / GR1: "fill color"
-		start/stop
-	*/
+	   run-down of registers to be programmed:
+	   destination pitch
+	   source pitch
+	   BLT width/height
+	   source start
+	   destination start
+	   BLT mode
+	   BLT ROP
+	   VGA_GFX_SR_VALUE / VGA_GFX_SR_ENABLE: "fill color"
+	   start/stop
+	 */
 
 	/* pitch: set to line_length */
-	WGfx(GR24, line_length & 0xff);	/* dest pitch low */
-	WGfx(GR25, (line_length >> 8));	/* dest pitch hi */
-	WGfx(GR26, line_length & 0xff);	/* source pitch low */
-	WGfx(GR27, (line_length >> 8));	/* source pitch hi */
+	vga_wgfx (regbase, CL_GR24, line_length & 0xff);	/* dest pitch low */
+	vga_wgfx (regbase, CL_GR25, (line_length >> 8));	/* dest pitch hi */
+	vga_wgfx (regbase, CL_GR26, line_length & 0xff);	/* source pitch low */
+	vga_wgfx (regbase, CL_GR27, (line_length >> 8));	/* source pitch hi */
 
 	/* BLT width: actual number of pixels - 1 */
-	WGfx(GR20, nwidth & 0xff);	/* BLT width low */
-	WGfx(GR21, (nwidth >> 8));	/* BLT width hi */
+	vga_wgfx (regbase, CL_GR20, nwidth & 0xff);	/* BLT width low */
+	vga_wgfx (regbase, CL_GR21, (nwidth >> 8));	/* BLT width hi */
 
 	/* BLT height: actual number of lines -1 */
-	WGfx(GR22, nheight & 0xff);	/* BLT height low */
-	WGfx(GR23, (nheight >> 8));	/* BLT width hi */
+	vga_wgfx (regbase, CL_GR22, nheight & 0xff);	/* BLT height low */
+	vga_wgfx (regbase, CL_GR23, (nheight >> 8));	/* BLT width hi */
 
 	/* BLT destination */
-	WGfx(GR28, (u_char)(ndest & 0xff));	/* BLT dest low */
-	WGfx(GR29, (u_char)(ndest >> 8));	/* BLT dest mid */
-	WGfx(GR2A, (u_char)(ndest >> 16));	/* BLT dest hi */
+	vga_wgfx (regbase, CL_GR28, (u_char) (ndest & 0xff));	/* BLT dest low */
+	vga_wgfx (regbase, CL_GR29, (u_char) (ndest >> 8));	/* BLT dest mid */
+	vga_wgfx (regbase, CL_GR2A, (u_char) (ndest >> 16));	/* BLT dest hi */
 
 	/* BLT source */
-	WGfx(GR2C, (u_char)(nsrc & 0xff));	/* BLT src low */
-	WGfx(GR2D, (u_char)(nsrc >> 8));	/* BLT src mid */
-	WGfx(GR2E, (u_char)(nsrc >> 16));	/* BLT src hi */
+	vga_wgfx (regbase, CL_GR2C, (u_char) (nsrc & 0xff));	/* BLT src low */
+	vga_wgfx (regbase, CL_GR2D, (u_char) (nsrc >> 8));		/* BLT src mid */
+	vga_wgfx (regbase, CL_GR2E, (u_char) (nsrc >> 16));	/* BLT src hi */
 
 	/* BLT mode */
-	WGfx(GR30, bltmode);	/* BLT mode */
+	vga_wgfx (regbase, CL_GR30, bltmode);	/* BLT mode */
 
 	/* BLT ROP: SrcCopy */
-	WGfx(GR32, 0x0d);	/* BLT ROP */
+	vga_wgfx (regbase, CL_GR32, 0x0d);		/* BLT ROP */
 
 	/* and finally: GO! */
-	WGfx(GR31, 0x02);	/* BLT Start/status */
+	vga_wgfx (regbase, CL_GR31, 0x02);		/* BLT Start/status */
+
+	DPRINTK ("EXIT\n");
 }
 
 /*******************************************************************
@@ -2042,56 +3052,78 @@
 	perform accelerated rectangle fill
 ********************************************************************/
 
-void clgen_RectFill (u_short x, u_short y, u_short width, u_short height,
-                     u_char color, u_short line_length)
+static void clgen_RectFill (struct clgenfb_info *fb_info,
+		     u_short x, u_short y, u_short width, u_short height,
+		     u_char color, u_short line_length)
 {
 	u_short nwidth, nheight;
 	u_long ndest;
+	u_char op;
+
+	DPRINTK ("ENTER\n");
 
 	nwidth = width - 1;
 	nheight = height - 1;
 
 	ndest = (y * line_length) + x;
 
-//	clgen_WaitBLT(); /* ### NOT OK for multiple boards! */
+        clgen_WaitBLT(fb_info->regs);
 
 	/* pitch: set to line_length */
-	WGfx(GR24, line_length & 0xff);	/* dest pitch low */
-	WGfx(GR25, (line_length >> 8));	/* dest pitch hi */
-	WGfx(GR26, line_length & 0xff);	/* source pitch low */
-	WGfx(GR27, (line_length >> 8));	/* source pitch hi */
+	vga_wgfx (fb_info->regs, CL_GR24, line_length & 0xff);	/* dest pitch low */
+	vga_wgfx (fb_info->regs, CL_GR25, (line_length >> 8));	/* dest pitch hi */
+	vga_wgfx (fb_info->regs, CL_GR26, line_length & 0xff);	/* source pitch low */
+	vga_wgfx (fb_info->regs, CL_GR27, (line_length >> 8));	/* source pitch hi */
 
 	/* BLT width: actual number of pixels - 1 */
-	WGfx(GR20, nwidth & 0xff);	/* BLT width low */
-	WGfx(GR21, (nwidth >> 8));	/* BLT width hi */
+	vga_wgfx (fb_info->regs, CL_GR20, nwidth & 0xff);	/* BLT width low */
+	vga_wgfx (fb_info->regs, CL_GR21, (nwidth >> 8));	/* BLT width hi */
 
 	/* BLT height: actual number of lines -1 */
-	WGfx(GR22, nheight & 0xff);	/* BLT height low */
-	WGfx(GR23, (nheight >> 8));	/* BLT width hi */
+	vga_wgfx (fb_info->regs, CL_GR22, nheight & 0xff);		/* BLT height low */
+	vga_wgfx (fb_info->regs, CL_GR23, (nheight >> 8));		/* BLT width hi */
 
 	/* BLT destination */
-	WGfx(GR28, (u_char)(ndest & 0xff));	/* BLT dest low */
-	WGfx(GR29, (u_char)(ndest >> 8));	/* BLT dest mid */
-	WGfx(GR2A, (u_char)(ndest >> 16));	/* BLT dest hi */
+	vga_wgfx (fb_info->regs, CL_GR28, (u_char) (ndest & 0xff));	/* BLT dest low */
+	vga_wgfx (fb_info->regs, CL_GR29, (u_char) (ndest >> 8));	/* BLT dest mid */
+	vga_wgfx (fb_info->regs, CL_GR2A, (u_char) (ndest >> 16));		/* BLT dest hi */
 
 	/* BLT source: set to 0 (is a dummy here anyway) */
-	WGfx(GR2C, 0x00);	/* BLT src low */
-	WGfx(GR2D, 0x00);	/* BLT src mid */
-	WGfx(GR2E, 0x00);	/* BLT src hi */
+	vga_wgfx (fb_info->regs, CL_GR2C, 0x00);	/* BLT src low */
+	vga_wgfx (fb_info->regs, CL_GR2D, 0x00);	/* BLT src mid */
+	vga_wgfx (fb_info->regs, CL_GR2E, 0x00);	/* BLT src hi */
 
 	/* This is a ColorExpand Blt, using the */
 	/* same color for foreground and background */
-	WGfx(GR0, color);	/* foreground color */
-	WGfx(GR1, color);	/* background color */
+	vga_wgfx (fb_info->regs, VGA_GFX_SR_VALUE, color);	/* foreground color */
+	vga_wgfx (fb_info->regs, VGA_GFX_SR_ENABLE, color);	/* background color */
 
+	op = 0xc0;
+	if (fb_info->currentmode.var.bits_per_pixel == 16) {
+		vga_wgfx (fb_info->regs, CL_GR10, color);	/* foreground color */
+		vga_wgfx (fb_info->regs, CL_GR11, color);	/* background color */
+		op = 0x50;
+		op = 0xd0;
+	} else if (fb_info->currentmode.var.bits_per_pixel == 32) {
+		vga_wgfx (fb_info->regs, CL_GR10, color);	/* foreground color */
+		vga_wgfx (fb_info->regs, CL_GR11, color);	/* background color */
+		vga_wgfx (fb_info->regs, CL_GR12, color);	/* foreground color */
+		vga_wgfx (fb_info->regs, CL_GR13, color);	/* background color */
+		vga_wgfx (fb_info->regs, CL_GR14, 0);	/* foreground color */
+		vga_wgfx (fb_info->regs, CL_GR15, 0);	/* background color */
+		op = 0x50;
+		op = 0xf0;
+	}
 	/* BLT mode: color expand, Enable 8x8 copy (faster?) */
-	WGfx(GR30, 0xc0);	/* BLT mode */
+	vga_wgfx (fb_info->regs, CL_GR30, op);	/* BLT mode */
 
 	/* BLT ROP: SrcCopy */
-	WGfx(GR32, 0x0d);	/* BLT ROP */
+	vga_wgfx (fb_info->regs, CL_GR32, 0x0d);	/* BLT ROP */
 
 	/* and finally: GO! */
-	WGfx(GR31, 0x02);	/* BLT Start/status */
+	vga_wgfx (fb_info->regs, CL_GR31, 0x02);	/* BLT Start/status */
+
+	DPRINTK ("EXIT\n");
 }
 
 /**************************************************************************
@@ -2099,70 +3131,283 @@
  * desired pixel clock
  **************************************************************************/
 #define abs(x) ((x)<0 ? -(x) : (x))
-static void bestclock(long freq, long *best, long *nom,
-		      long *den, long *div,  long maxfreq)
+static void bestclock (long freq, long *best, long *nom,
+		       long *den, long *div, long maxfreq)
 {
-    long n, h, d, f;
+	long n, h, d, f;
 
-    *nom = 0;
-    *den = 0;
-    *div = 0;
-
-    if (freq < 8000)
-	freq = 8000;
-
-    if (freq > maxfreq)
-	freq = maxfreq;
-
-    *best = 0;
-    f = freq * 10;
-
-    for(n = 32; n < 128; n++)
-    {
-        d = (143181 * n) / f;
-	if ( (d >= 7) && (d <= 63) )
-        {
-            if (d > 31)
-            	d = (d / 2) * 2;
-            h = (14318 * n) / d;
-            if ( abs(h - freq) < abs(*best - freq) )
-            {
-                *best = h;
-		*nom = n;
-		if (d < 32)
-		{
-                    *den = d;
-                    *div = 0;
+	assert (best != NULL);
+	assert (nom != NULL);
+	assert (den != NULL);
+	assert (div != NULL);
+	assert (maxfreq > 0);
+
+	*nom = 0;
+	*den = 0;
+	*div = 0;
+
+	DPRINTK ("ENTER\n");
+
+	if (freq < 8000)
+		freq = 8000;
+
+	if (freq > maxfreq)
+		freq = maxfreq;
+
+	*best = 0;
+	f = freq * 10;
+
+	for (n = 32; n < 128; n++) {
+		d = (143181 * n) / f;
+		if ((d >= 7) && (d <= 63)) {
+			if (d > 31)
+				d = (d / 2) * 2;
+			h = (14318 * n) / d;
+			if (abs (h - freq) < abs (*best - freq)) {
+				*best = h;
+				*nom = n;
+				if (d < 32) {
+					*den = d;
+					*div = 0;
+				} else {
+					*den = d / 2;
+					*div = 1;
+				}
+			}
 		}
-		else
-		{
-                    *den = d / 2;
-		    *div = 1;
+		d = ((143181 * n) + f - 1) / f;
+		if ((d >= 7) && (d <= 63)) {
+			if (d > 31)
+				d = (d / 2) * 2;
+			h = (14318 * n) / d;
+			if (abs (h - freq) < abs (*best - freq)) {
+				*best = h;
+				*nom = n;
+				if (d < 32) {
+					*den = d;
+					*div = 0;
+				} else {
+					*den = d / 2;
+					*div = 1;
+				}
+			}
 		}
-            }
-        }
-        d = ( (143181 * n)+f-1) / f;
-        if ( (d >= 7) && (d <= 63) )
-	{
-	    if (d > 31)
-    		d = (d / 2) * 2;
-	    h = (14318 * n) / d;
-	    if ( abs(h - freq) < abs(*best - freq) )
-	    {
-    	        *best = h;
-    	        *nom = n;
-            	if (d < 32)
-		{
-    	            *den = d;
-        	    *div = 0;
-	        }
-    	        else
-    	        {
-    	            *den = d / 2;
-	            *div = 1;
-	        }
-	    }
 	}
-    }
+
+	DPRINTK ("Best possible values for given frequency:\n");
+	DPRINTK ("        best: %ld kHz  nom: %ld  den: %ld  div: %ld\n",
+		 freq, *nom, *den, *div);
+
+	DPRINTK ("EXIT\n");
+}
+
+
+
+
+
+
+/* -------------------------------------------------------------------------
+ *
+ * debugging functions
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifdef CLGEN_DEBUG
+
+/**
+ * clgen_dbg_print_byte
+ * @name: name associated with byte value to be displayed
+ * @val: byte value to be displayed
+ *
+ * DESCRIPTION:
+ * Display an indented string, along with a hexidecimal byte value, and
+ * its decoded bits.  Bits 7 through 0 are listed in left-to-right
+ * order.
+ */
+
+static
+void clgen_dbg_print_byte (const char *name, unsigned char val)
+{
+	DPRINTK ("%8s = 0x%02X (bits 7-0: %c%c%c%c%c%c%c%c)\n",
+		 name, val,
+		 val & 0x80 ? '1' : '0',
+		 val & 0x40 ? '1' : '0',
+		 val & 0x20 ? '1' : '0',
+		 val & 0x10 ? '1' : '0',
+		 val & 0x08 ? '1' : '0',
+		 val & 0x04 ? '1' : '0',
+		 val & 0x02 ? '1' : '0',
+		 val & 0x01 ? '1' : '0');
+}
+
+
+
+/**
+ * clgen_dbg_print_regs
+ * @base: If using newmmio, the newmmio base address, otherwise %NULL
+ * @reg_class: type of registers to read: %CRT, or %SEQ
+ *
+ * DESCRIPTION:
+ * Dumps the given list of VGA CRTC registers.  If @base is %NULL,
+ * old-style I/O ports are queried for information, otherwise MMIO is
+ * used at the given @base address to query the information.
+ */
+
+static
+void clgen_dbg_print_regs (caddr_t regbase, clgen_dbg_reg_class_t reg_class,...)
+{
+	va_list list;
+	unsigned char val = 0;
+	unsigned reg;
+	char *name;
+
+	va_start (list, reg_class);
+
+	name = va_arg (list, char *);
+	while (name != NULL) {
+		reg = va_arg (list, int);
+
+		switch (reg_class) {
+		case CRT:
+			val = vga_rcrt (regbase, (unsigned char) reg);
+			break;
+		case SEQ:
+			val = vga_rseq (regbase, (unsigned char) reg);
+			break;
+		default:
+			/* should never occur */
+			assert (0);
+			break;
+		}
+
+		clgen_dbg_print_byte (name, val);
+
+		name = va_arg (list, char *);
+	}
+
+	va_end (list);
+}
+
+
+
+
+
+/**
+ * clgen_dump
+ * @clgeninfo:
+ *
+ * DESCRIPTION:
+ */
+ 
+static
+void clgen_dump (void)
+{
+	clgen_dbg_reg_dump (NULL);
+}
+
+
+
+/**
+ * clgen_dbg_reg_dump
+ * @base: If using newmmio, the newmmio base address, otherwise %NULL
+ *
+ * DESCRIPTION:
+ * Dumps a list of interesting VGA and CLGEN registers.  If @base is %NULL,
+ * old-style I/O ports are queried for information, otherwise MMIO is
+ * used at the given @base address to query the information.
+ */
+
+static
+void clgen_dbg_reg_dump (caddr_t regbase)
+{
+	DPRINTK ("CLGEN VGA CRTC register dump:\n");
+
+	clgen_dbg_print_regs (regbase, CRT,
+			   "CR00", 0x00,
+			   "CR01", 0x01,
+			   "CR02", 0x02,
+			   "CR03", 0x03,
+			   "CR04", 0x04,
+			   "CR05", 0x05,
+			   "CR06", 0x06,
+			   "CR07", 0x07,
+			   "CR08", 0x08,
+			   "CR09", 0x09,
+			   "CR0A", 0x0A,
+			   "CR0B", 0x0B,
+			   "CR0C", 0x0C,
+			   "CR0D", 0x0D,
+			   "CR0E", 0x0E,
+			   "CR0F", 0x0F,
+			   "CR10", 0x10,
+			   "CR11", 0x11,
+			   "CR12", 0x12,
+			   "CR13", 0x13,
+			   "CR14", 0x14,
+			   "CR15", 0x15,
+			   "CR16", 0x16,
+			   "CR17", 0x17,
+			   "CR18", 0x18,
+			   "CR22", 0x22,
+			   "CR24", 0x24,
+			   "CR26", 0x26,
+			   "CR2D", 0x2D,
+			   "CR2E", 0x2E,
+			   "CR2F", 0x2F,
+			   "CR30", 0x30,
+			   "CR31", 0x31,
+			   "CR32", 0x32,
+			   "CR33", 0x33,
+			   "CR34", 0x34,
+			   "CR35", 0x35,
+			   "CR36", 0x36,
+			   "CR37", 0x37,
+			   "CR38", 0x38,
+			   "CR39", 0x39,
+			   "CR3A", 0x3A,
+			   "CR3B", 0x3B,
+			   "CR3C", 0x3C,
+			   "CR3D", 0x3D,
+			   "CR3E", 0x3E,
+			   "CR3F", 0x3F,
+			   NULL);
+
+	DPRINTK ("\n");
+
+	DPRINTK ("CLGEN VGA SEQ register dump:\n");
+
+	clgen_dbg_print_regs (regbase, SEQ,
+			   "SR00", 0x00,
+			   "SR01", 0x01,
+			   "SR02", 0x02,
+			   "SR03", 0x03,
+			   "SR04", 0x04,
+			   "SR08", 0x08,
+			   "SR09", 0x09,
+			   "SR0A", 0x0A,
+			   "SR0B", 0x0B,
+			   "SR0D", 0x0D,
+			   "SR10", 0x10,
+			   "SR11", 0x11,
+			   "SR12", 0x12,
+			   "SR13", 0x13,
+			   "SR14", 0x14,
+			   "SR15", 0x15,
+			   "SR16", 0x16,
+			   "SR17", 0x17,
+			   "SR18", 0x18,
+			   "SR19", 0x19,
+			   "SR1A", 0x1A,
+			   "SR1B", 0x1B,
+			   "SR1C", 0x1C,
+			   "SR1D", 0x1D,
+			   "SR1E", 0x1E,
+			   "SR1F", 0x1F,
+			   NULL);
+
+	DPRINTK ("\n");
 }
 
+
+#endif				/* CLGEN_DEBUG */
diff -u --recursive --new-file v2.3.13/linux/drivers/video/clgenfb.h linux/drivers/video/clgenfb.h
--- v2.3.13/linux/drivers/video/clgenfb.h	Sun Jul 26 14:40:19 1998
+++ linux/drivers/video/clgenfb.h	Wed Aug 18 10:10:06 1999
@@ -1,175 +1,122 @@
-
-/* definitions for Piccolo/SD64 VGA controller chip   */
-/* these definitions might most of the time also work */
-/* for other CL-GD542x/543x based boards..            */
+/*
+ * drivers/video/clgenfb.h - Cirrus Logic chipset constants
+ *
+ * Copyright 1999 Jeff Garzik <jgarzik@pobox.com>
+ *
+ * Original clgenfb author:  Frank Neumann
+ *
+ * Based on retz3fb.c and clgen.c:
+ *      Copyright (C) 1997 Jes Sorensen
+ *      Copyright (C) 1996 Frank Neumann
+ *
+ ***************************************************************
+ *
+ * Format this code with GNU indent '-kr -i8 -pcs' options.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __CLGENFB_H__
+#define __CLGENFB_H__
+
+/* OLD COMMENT: definitions for Piccolo/SD64 VGA controller chip   */
+/* OLD COMMENT: these definitions might most of the time also work */
+/* OLD COMMENT: for other CL-GD542x/543x based boards..            */
 
 /*** External/General Registers ***/
-#define POS102	0x102  	/* POS102 register */
-#define VSSM	0x46e8 	/* Adapter Sleep */
-#define VSSM2	0x3c3	/* Motherboard Sleep */
-#define MISC_W	0x3c2	/* Miscellaneous Output register, write */
-#define MISC_R	0x3cc	/* Miscellaneous Output register, read */
-#define FC_W	0x3da	/* Feature Control Register, write (color) */
-#define FC_R	0x3ca	/* Feature Control Register, read */
-#define FEAT	0x3c2	/* Input Status Register 0 */
-#define STAT	0x3da	/* Input Status Register 1, read-only */
-#define M_3C6	0x3c6	/* Pixel Mask */
-#define M_3C7_W	0x3c7   /* Pixel Address Read Mode (write) */
-#define M_3C7_R	0x3c7	/* DAC State (read-only */
-#define M_3C8	0x3c8	/* Pixel Address Write Mode */
-#define M_3C9	0x3c9	/* Pixel Data */
+#define CL_POS102	0x102  	/* POS102 register */
+#define CL_VSSM		0x46e8 	/* Adapter Sleep */
+#define CL_VSSM2	0x3c3	/* Motherboard Sleep */
 
 /*** VGA Sequencer Registers ***/
-#define SEQRX	0x3c4	/* Sequencer Index */
-#define SEQR0	0x0	/* Reset */
-#define SEQR1     0x1	/* Clocking Mode */
-#define SEQR2	0x2	/* Plane Mask / Write Pixel Extension */
-#define SEQR3	0x3	/* Character Map Select */
-#define SEQR4	0x4	/* Memory Mode */
+#define CL_SEQR0	0x0	/* Reset */
 /* the following are from the "extension registers" group */
-#define SEQR6	0x6	/* Unlock ALL Extensions */
-#define SEQR7	0x7	/* Extended Sequencer Mode */
-#define SEQR8	0x8	/* EEPROM Control */
-#define SEQR9	0x9	/* Scratch Pad 0 (do not access!) */
-#define SEQRA	0xa	/* Scratch Pad 1 (do not access!) */
-#define SEQRB	0xb	/* VCLK0 Numerator */
-#define SEQRC	0xc	/* VCLK1 Numerator */
-#define SEQRD	0xd	/* VCLK2 Numerator */
-#define SEQRE	0xe	/* VCLK3 Numerator */
-#define SEQRF	0xf	/* DRAM Control */
-#define SEQR10	0x10	/* Graphics Cursor X Position */
-#define SEQR11	0x11	/* Graphics Cursor Y Position */
-#define SEQR12	0x12	/* Graphics Cursor Attributes */
-#define SEQR13	0x13	/* Graphics Cursor Pattern Address Offset */
-#define SEQR14	0x14	/* Scratch Pad 2 (CL-GD5426/'28 Only) (do not access!) */
-#define SEQR15	0x15	/* Scratch Pad 3 (CL-GD5426/'28 Only) (do not access!) */
-#define SEQR16	0x16	/* Performance Tuning (CL-GD5424/'26/'28 Only) */
-#define SEQR17	0x17	/* Configuration ReadBack and Extended Control (CL-GF5428 Only) */
-#define SEQR18	0x18	/* Signature Generator Control (Not CL-GD5420) */
-#define SEQR19	0x19	/* Signature Generator Result Low Byte (Not CL-GD5420) */
-#define SEQR1A	0x1a	/* Signature Generator Result High Byte (Not CL-GD5420) */
-#define SEQR1B	0x1b	/* VCLK0 Denominator and Post-Scalar Value */
-#define SEQR1C	0x1c	/* VCLK1 Denominator and Post-Scalar Value */
-#define SEQR1D	0x1d	/* VCLK2 Denominator and Post-Scalar Value */
-#define SEQR1E	0x1e	/* VCLK3 Denominator and Post-Scalar Value */
-#define SEQR1F	0x1f	/* BIOS ROM write enable and MCLK Select */
+#define CL_SEQR6	0x6	/* Unlock ALL Extensions */
+#define CL_SEQR7	0x7	/* Extended Sequencer Mode */
+#define CL_SEQR8	0x8	/* EEPROM Control */
+#define CL_SEQR9	0x9	/* Scratch Pad 0 (do not access!) */
+#define CL_SEQRA	0xa	/* Scratch Pad 1 (do not access!) */
+#define CL_SEQRB	0xb	/* VCLK0 Numerator */
+#define CL_SEQRC	0xc	/* VCLK1 Numerator */
+#define CL_SEQRD	0xd	/* VCLK2 Numerator */
+#define CL_SEQRE	0xe	/* VCLK3 Numerator */
+#define CL_SEQRF	0xf	/* DRAM Control */
+#define CL_SEQR10	0x10	/* Graphics Cursor X Position */
+#define CL_SEQR11	0x11	/* Graphics Cursor Y Position */
+#define CL_SEQR12	0x12	/* Graphics Cursor Attributes */
+#define CL_SEQR13	0x13	/* Graphics Cursor Pattern Address Offset */
+#define CL_SEQR14	0x14	/* Scratch Pad 2 (CL-GD5426/'28 Only) (do not access!) */
+#define CL_SEQR15	0x15	/* Scratch Pad 3 (CL-GD5426/'28 Only) (do not access!) */
+#define CL_SEQR16	0x16	/* Performance Tuning (CL-GD5424/'26/'28 Only) */
+#define CL_SEQR17	0x17	/* Configuration ReadBack and Extended Control (CL-GF5428 Only) */
+#define CL_SEQR18	0x18	/* Signature Generator Control (Not CL-GD5420) */
+#define CL_SEQR19	0x19	/* Signature Generator Result Low Byte (Not CL-GD5420) */
+#define CL_SEQR1A	0x1a	/* Signature Generator Result High Byte (Not CL-GD5420) */
+#define CL_SEQR1B	0x1b	/* VCLK0 Denominator and Post-Scalar Value */
+#define CL_SEQR1C	0x1c	/* VCLK1 Denominator and Post-Scalar Value */
+#define CL_SEQR1D	0x1d	/* VCLK2 Denominator and Post-Scalar Value */
+#define CL_SEQR1E	0x1e	/* VCLK3 Denominator and Post-Scalar Value */
+#define CL_SEQR1F	0x1f	/* BIOS ROM write enable and MCLK Select */
 
 /*** CRT Controller Registers ***/
-#define CRTX	0x3d4	/* CRTC Index */
-#define	CRT0	0x0	/* Horizontal Total */
-#define CRT1	0x1	/* Horizontal Display End */
-#define CRT2	0x2	/* Horizontal Blanking Start */
-#define CRT3	0x3	/* Horizontal Blabking End */
-#define CRT4	0x4	/* Horizontal Sync Start */
-#define CRT5	0x5	/* Horizontal Sync End */
-#define CRT6 	0x6	/* Vertical Total */
-#define CRT7	0x7	/* Overflow */
-#define CRT8	0x8	/* Screen A Preset Row Scan */
-#define CRT9	0x9	/* Character Cell Height */
-#define CRTA	0xa	/* Text Cursor Start */
-#define CRTB	0xb	/* Text Cursor End */
-#define CRTC	0xc	/* Screen Start Address High */
-#define CRTD	0xd	/* Screen Start Address Low */
-#define CRTE	0xe	/* Text Cursor Location High */
-#define CRTF	0xf	/* Text Cursor Location Low */
-#define CRT10	0x10	/* Vertical Sync Start */
-#define CRT11	0x11	/* Vertical Sync End */
-#define CRT12	0x12	/* Vertical Display End */
-#define CRT13	0x13	/* Offset */
-#define CRT14	0x14	/* Underline Row Scan */
-#define CRT15  	0x15	/* Vertical Blanking Start */
-#define CRT16	0x16	/* Vertical Blanking End */
-#define CRT17	0x17	/* Mode Control */
-#define CRT18	0x18	/* Line Compare */
-#define CRT22	0x22	/* Graphics Data Latches ReadBack */
-#define CRT24	0x24	/* Attribute Controller Toggle ReadBack */
-#define CRT26	0x26	/* Attribute Controller Index ReadBack */
+#define CL_CRT22	0x22	/* Graphics Data Latches ReadBack */
+#define CL_CRT24	0x24	/* Attribute Controller Toggle ReadBack */
+#define CL_CRT26	0x26	/* Attribute Controller Index ReadBack */
 /* the following are from the "extension registers" group */
-#define CRT19	0x19	/* Interlace End */
-#define CRT1A	0x1a	/* Interlace Control */
-#define CRT1B	0x1b	/* Extended Display Controls */
-#define CRT1C	0x1c	/* Sync adjust and genlock register */
-#define CRT1D	0x1d	/* Overlay Extended Control register */
-#define CRT25	0x25	/* Part Status Register */
-#define CRT27	0x27	/* ID Register */
-#define CRT51	0x51	/* P4 disable "flicker fixer" */
+#define CL_CRT19	0x19	/* Interlace End */
+#define CL_CRT1A	0x1a	/* Interlace Control */
+#define CL_CRT1B	0x1b	/* Extended Display Controls */
+#define CL_CRT1C	0x1c	/* Sync adjust and genlock register */
+#define CL_CRT1D	0x1d	/* Overlay Extended Control register */
+#define CL_CRT25	0x25	/* Part Status Register */
+#define CL_CRT27	0x27	/* ID Register */
+#define CL_CRT51	0x51	/* P4 disable "flicker fixer" */
 
 /*** Graphics Controller Registers ***/
-#define GRX	0x3ce	/* Graphics Controller Index */
-#define GR0	0x0	/* Set/Reset, Write Mode 5 Background Extension */
-#define GR1	0x1	/* Set/Reset Enable, Write Mode 4, 5 Foreground Ext. */
-#define GR2	0x2	/* Color Compare */
-#define GR3	0x3	/* Data Rotate */
-#define GR4	0x4	/* Read Map Select */
-#define GR5	0x5	/* Mode */
-#define GR6	0x6	/* Miscellaneous */
-#define GR7	0x7     /* Color Don't Care */
-#define GR8	0x8	/* Bit Mask */
 /* the following are from the "extension registers" group */
-#define GR9	0x9	/* Offset Register 0 */
-#define GRA	0xa	/* Offset Register 1 */
-#define GRB	0xb	/* Graphics Controller Mode Extensions */
-#define GRC	0xc	/* Color Key (CL-GD5424/'26/'28 Only) */
-#define GRD	0xd	/* Color Key Mask (CL-GD5424/'26/'28 Only) */
-#define GRE	0xe	/* Miscellaneous Control (Cl-GD5428 Only) */
-#define GRF	0xf	/* Display Compression Control register */
-#define GR10	0x10	/* 16-bit Pixel BG Color High Byte (Not CL-GD5420) */
-#define GR11	0x11	/* 16-bit Pixel FG Color High Byte (Not CL-GD5420) */
-#define GR12	0x12	/* Background Color Byte 2 Register */
-#define GR13	0x13	/* Foreground Color Byte 2 Register */
-#define GR14	0x14	/* Background Color Byte 3 Register */
-#define GR15	0x15	/* Foreground Color Byte 3 Register */
+#define CL_GR9		0x9	/* Offset Register 0 */
+#define CL_GRA		0xa	/* Offset Register 1 */
+#define CL_GRB		0xb	/* Graphics Controller Mode Extensions */
+#define CL_GRC		0xc	/* Color Key (CL-GD5424/'26/'28 Only) */
+#define CL_GRD		0xd	/* Color Key Mask (CL-GD5424/'26/'28 Only) */
+#define CL_GRE		0xe	/* Miscellaneous Control (Cl-GD5428 Only) */
+#define CL_GRF		0xf	/* Display Compression Control register */
+#define CL_GR10		0x10	/* 16-bit Pixel BG Color High Byte (Not CL-GD5420) */
+#define CL_GR11		0x11	/* 16-bit Pixel FG Color High Byte (Not CL-GD5420) */
+#define CL_GR12		0x12	/* Background Color Byte 2 Register */
+#define CL_GR13		0x13	/* Foreground Color Byte 2 Register */
+#define CL_GR14		0x14	/* Background Color Byte 3 Register */
+#define CL_GR15		0x15	/* Foreground Color Byte 3 Register */
 /* the following are CL-GD5426/'28 specific blitter registers */
-#define GR20	0x20	/* BLT Width Low */
-#define GR21	0x21	/* BLT Width High */
-#define GR22	0x22	/* BLT Height Low */
-#define GR23	0x23	/* BLT Height High */
-#define GR24	0x24	/* BLT Destination Pitch Low */
-#define GR25	0x25	/* BLT Destination Pitch High */
-#define GR26	0x26	/* BLT Source Pitch Low */
-#define GR27	0x27	/* BLT Source Pitch High */
-#define GR28	0x28	/* BLT Destination Start Low */
-#define GR29	0x29	/* BLT Destination Start Mid */
-#define GR2A    0x2a	/* BLT Destination Start High */
-#define GR2C	0x2c	/* BLT Source Start Low */
-#define GR2D	0x2d	/* BLT Source Start Mid */
-#define GR2E	0x2e	/* BLT Source Start High */
-#define GR2F	0x2f	/* Picasso IV Blitter compat mode..? */
-#define GR30	0x30	/* BLT Mode */
-#define GR31	0x31	/* BLT Start/Status */
-#define GR32	0x32	/* BLT Raster Operation */
-#define GR33	0x33	/* another P4 "compat" register.. */
-#define GR34	0x34	/* Transparent Color Select Low */
-#define GR35	0x35	/* Transparent Color Select High */
-#define GR38	0x38	/* Source Transparent Color Mask Low */
-#define GR39	0x39	/* Source Transparent Color Mask High */
+#define CL_GR20		0x20	/* BLT Width Low */
+#define CL_GR21		0x21	/* BLT Width High */
+#define CL_GR22		0x22	/* BLT Height Low */
+#define CL_GR23		0x23	/* BLT Height High */
+#define CL_GR24		0x24	/* BLT Destination Pitch Low */
+#define CL_GR25		0x25	/* BLT Destination Pitch High */
+#define CL_GR26		0x26	/* BLT Source Pitch Low */
+#define CL_GR27		0x27	/* BLT Source Pitch High */
+#define CL_GR28		0x28	/* BLT Destination Start Low */
+#define CL_GR29		0x29	/* BLT Destination Start Mid */
+#define CL_GR2A		0x2a	/* BLT Destination Start High */
+#define CL_GR2C		0x2c	/* BLT Source Start Low */
+#define CL_GR2D		0x2d	/* BLT Source Start Mid */
+#define CL_GR2E		0x2e	/* BLT Source Start High */
+#define CL_GR2F		0x2f	/* Picasso IV Blitter compat mode..? */
+#define CL_GR30		0x30	/* BLT Mode */
+#define CL_GR31		0x31	/* BLT Start/Status */
+#define CL_GR32		0x32	/* BLT Raster Operation */
+#define CL_GR33		0x33	/* another P4 "compat" register.. */
+#define CL_GR34		0x34	/* Transparent Color Select Low */
+#define CL_GR35		0x35	/* Transparent Color Select High */
+#define CL_GR38		0x38	/* Source Transparent Color Mask Low */
+#define CL_GR39		0x39	/* Source Transparent Color Mask High */
 
 /*** Attribute Controller Registers ***/
-#define ARX	0x3c0	/* Attribute Controller Index */
-#define AR0     0x0	/* Attribute Controller Palette Register 0 */
-#define AR1     0x1	/* Attribute Controller Palette Register 1 */
-#define AR2     0x2	/* Attribute Controller Palette Register 2 */
-#define AR3     0x3	/* Attribute Controller Palette Register 3 */
-#define AR4     0x4	/* Attribute Controller Palette Register 4 */
-#define AR5     0x5	/* Attribute Controller Palette Register 5 */
-#define AR6     0x6	/* Attribute Controller Palette Register 6 */
-#define AR7     0x7	/* Attribute Controller Palette Register 7 */
-#define AR8     0x8	/* Attribute Controller Palette Register 8 */
-#define AR9     0x9	/* Attribute Controller Palette Register 9 */
-#define ARA     0xa	/* Attribute Controller Palette Register 10 */
-#define ARB     0xb	/* Attribute Controller Palette Register 11 */
-#define ARC     0xc	/* Attribute Controller Palette Register 12 */
-#define ARD     0xd	/* Attribute Controller Palette Register 13 */
-#define ARE     0xe	/* Attribute Controller Palette Register 14 */
-#define ARF     0xf	/* Attribute Controller Palette Register 15 */
-#define AR10	0x10	/* Attribute Controller Mode Register */
-#define AR11	0x11	/* Overscan (Border) Color Register */
-#define AR12	0x12    /* Color Plane Enable Register */
-#define AR13	0x13	/* Pixel Panning Register */
-#define AR14	0x14	/* Color Select Register */
-#define AR33	0x33	/* The "real" Pixel Panning register (?) */
-#define AR34	0x34	/* *TEST* */
-
-/*** Extension Registers ***/
-#define HDR	0x3c6	/* Hidden DAC Register (Not CL-GD5420) */
+#define CL_AR33		0x33	/* The "real" Pixel Panning register (?) */
+#define CL_AR34		0x34	/* TEST */
 
+#endif /* __CLGENFB_H__ */
diff -u --recursive --new-file v2.3.13/linux/drivers/video/controlfb.c linux/drivers/video/controlfb.c
--- v2.3.13/linux/drivers/video/controlfb.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/controlfb.c	Wed Aug 18 10:00:52 1999
@@ -153,7 +153,7 @@
 #ifdef CONFIG_FB_OF
 void control_of_init(struct device_node *dp);
 #endif
-void control_setup(char *options, int *ints);
+void control_setup(char *);
 
 static int read_control_sense(struct fb_info_control *p);
 static inline int control_vram_reqd(int video_mode, int color_mode);
@@ -1152,7 +1152,7 @@
 }
 
 /* Parse user speficied options (`video=controlfb:') */
-void __init control_setup(char *options, int *ints)
+void __init control_setup(char *options)
 {
 	char *this_opt;
 
diff -u --recursive --new-file v2.3.13/linux/drivers/video/cyber2000fb.c linux/drivers/video/cyber2000fb.c
--- v2.3.13/linux/drivers/video/cyber2000fb.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/cyber2000fb.c	Thu Aug 12 10:22:33 1999
@@ -1018,8 +1018,9 @@
 	}
 }
 
-void __init cyber2000fb_setup(char *options, int *ints)
+int __init cyber2000fb_setup(char *options)
 {
+	return 0;
 }
 
 static struct fb_ops cyber2000fb_ops =
@@ -1138,14 +1139,14 @@
 /*
  *    Initialization
  */
-void __init cyber2000fb_init(void)
+int __init cyber2000fb_init(void)
 {
 	struct pci_dev *dev;
 	u_int h_sync, v_sync;
 
 	dev = pci_find_device(PCI_VENDOR_ID_INTERG, 0x2000, NULL);
 	if (!dev)
-		return;
+		return -ENXIO;
 
 	CyberRegs = bus_to_virt(dev->base_address[0]) + 0x00800000;/*FIXME*/
 
@@ -1156,10 +1157,13 @@
 	cyber2000fb_init_fbinfo();
 
 	current_par.currcon		= -1;
-	current_par.screen_base_p	= 0x80000000 + dev->base_address[0];
-	current_par.screen_base		= (u_int)bus_to_virt(dev->base_address[0]);
+	/* this should be done by PCI generic code */
+	current_par.screen_base_p	= 0x80000000 + dev->resource[0].start;
+	/* and this by ioremap... But I have no such device here to test */
+	/* current_par.screen_base = ioremap(dev->resource[0].start, dev->resource[0].end - dev->resource[0].start + 1); */
+	current_par.screen_base		= (u_int)bus_to_virt(dev->resource[0].start);
 	current_par.screen_size		= 0x00200000;
-	current_par.regs_base_p		= 0x80800000 + dev->base_address[0];
+	current_par.regs_base_p		= 0x80800000 + dev->resource[0].start;
 
 	cyber2000fb_set_var(&init_var, -1, &fb_info);
 
@@ -1175,18 +1179,18 @@
 		h_sync / 1000, h_sync % 1000, v_sync);
 
 	if (register_framebuffer(&fb_info) < 0)
-		return;
+		return -EINVAL;
 
 	MOD_INC_USE_COUNT;	/* TODO: This driver cannot be unloaded yet */
+	return 0;
 }
 
 
 
 #ifdef MODULE
-int init_module(void)
+int __init init_module(void)
 {
-	cyber2000fb_init();
-	return 0;
+	return cyber2000fb_init();
 }
 
 void cleanup_module(void)
diff -u --recursive --new-file v2.3.13/linux/drivers/video/cyberfb.c linux/drivers/video/cyberfb.c
--- v2.3.13/linux/drivers/video/cyberfb.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/cyberfb.c	Thu Aug 12 10:22:33 1999
@@ -239,7 +239,7 @@
  *    Interface used by the world
  */
 
-void cyberfb_setup(char *options, int *ints);
+int cyberfb_setup(char *options);
 
 static int cyberfb_open(struct fb_info *info, int user);
 static int cyberfb_release(struct fb_info *info, int user);
@@ -262,7 +262,7 @@
  *    Interface to the low level console driver
  */
 
-void cyberfb_init(void);
+int cyberfb_init(void);
 static int Cyberfb_switch(int con, struct fb_info *info);
 static int Cyberfb_updatevar(int con, struct fb_info *info);
 static void Cyberfb_blank(int blank, struct fb_info *info);
@@ -1062,7 +1062,7 @@
 };
 
 
-void __init cyberfb_setup(char *options, int *ints)
+int __init cyberfb_setup(char *options)
 {
 	char *this_opt;
 	DPRINTK("ENTER\n");
@@ -1071,7 +1071,7 @@
 
 	if (!options || !*options) {
 		DPRINTK("EXIT - no options\n");
-		return;
+		return 0;
 	}
 
 	for (this_opt = strtok(options, ","); this_opt;
@@ -1095,13 +1095,14 @@
 		cyberfb_default.yres,
 		cyberfb_default.bits_per_pixel);
 	DPRINTK("EXIT\n");
+	return 0;
 }
 
 /*
  *    Initialization
  */
 
-void __init cyberfb_init(void)
+int __init cyberfb_init(void)
 {
 	struct cyberfb_par par;
 	unsigned long board_addr;
@@ -1112,7 +1113,7 @@
 
 	if (!(CyberKey = zorro_find(ZORRO_PROD_PHASE5_CYBERVISION64, 0, 0))) {
 		DPRINTK("EXIT - zorro_find failed\n");
-		return;
+		return -ENXIO;
 	}
 
 	cd = zorro_get_board (CyberKey);
@@ -1163,7 +1164,7 @@
 
 	if (register_framebuffer(&fb_info) < 0) {
 		DPRINTK("EXIT - register_framebuffer failed\n");
-		return;
+		return -EINVAL;
 	}
 
 	printk("fb%d: %s frame buffer device, using %ldK of video memory\n",
@@ -1172,6 +1173,7 @@
 	/* TODO: This driver cannot be unloaded yet */
 	MOD_INC_USE_COUNT;
 	DPRINTK("EXIT\n");
+	return 0;
 }
 
 
@@ -1299,8 +1301,7 @@
 #ifdef MODULE
 int init_module(void)
 {
-	cyberfb_init();
-	return 0;
+	return cyberfb_init();
 }
 
 void cleanup_module(void)
diff -u --recursive --new-file v2.3.13/linux/drivers/video/dnfb.c linux/drivers/video/dnfb.c
--- v2.3.13/linux/drivers/video/dnfb.c	Thu Oct  1 10:02:21 1998
+++ linux/drivers/video/dnfb.c	Thu Aug 12 10:22:33 1999
@@ -310,7 +310,7 @@
 #endif
 }
   
-void dnfb_init(void)
+int dnfb_init(void)
 {
 	fb_info.changevar=NULL;
 	strcpy(&fb_info.modename[0],dnfb_name);
@@ -333,11 +333,14 @@
         dnfb_get_var(&disp[0].var, 0, &fb_info);
 	dnfb_set_disp(-1, &fb_info);
 
-	if (register_framebuffer(&fb_info) < 0)
-		panic("unable to register apollo frame buffer\n");
+	if (register_framebuffer(&fb_info) < 0) {
+		printk(KERN_ERR "unable to register apollo frame buffer\n");
+		return -EINVAL;
+	}
  
         printk("fb%d: apollo frame buffer alive and kicking !\n",
 	       GET_FB_IDX(fb_info.node));
+	return 0;
 }	
 
 	
diff -u --recursive --new-file v2.3.13/linux/drivers/video/fbcon-vga-planes.c linux/drivers/video/fbcon-vga-planes.c
--- v2.3.13/linux/drivers/video/fbcon-vga-planes.c	Thu May 13 23:48:20 1999
+++ linux/drivers/video/fbcon-vga-planes.c	Thu Aug 12 09:44:38 1999
@@ -44,7 +44,8 @@
    OR. */
 static inline void rmw(volatile char *p)
 {
-	*p |= 1;
+	readb(p);
+	writeb(1, p);
 }
 
 /* Set the Graphics Mode Register.  Bits 0-1 are write mode, bit 3 is
@@ -122,8 +123,12 @@
 		dest = p->screen_base + dx + dy * p->line_length;
 		src = p->screen_base + sx + sy * p->line_length;
 		while (height--) {
-			for (x = 0; x < width; x++) 
-				*dest++ = *src++;
+			for (x = 0; x < width; x++) {
+				readb(src);
+				writeb(0, dest);
+				dest++;
+				src++;
+			}
 			src += line_ofs;
 			dest += line_ofs;
 		}
@@ -132,8 +137,12 @@
 		dest = p->screen_base + dx + width + (dy + height - 1) * p->line_length;
 		src = p->screen_base + sx + width + (sy + height - 1) * p->line_length;
 		while (height--) {
-			for (x = 0; x < width; x++)
-				*--dest = *--src;
+			for (x = 0; x < width; x++) {
+				dest--;
+				src--;
+				readb(src);
+				writeb(0, dest);
+			}
 			src -= line_ofs;
 			dest -= line_ofs;
 		}
@@ -160,8 +169,10 @@
 
 	where = p->screen_base + sx + sy * p->line_length;
 	while (height--) {
-		for (x = 0; x < width; x++)
-			*where++ = 0;
+		for (x = 0; x < width; x++) {
+			writeb(0, where);
+			where++;
+		}
 		where += line_ofs;
 	}
 }
@@ -211,13 +222,13 @@
 	selectmask();
 
 	setmask(0xff);
-	*where = bg;
+	writeb(bg, where);
 	rmb();
-	*(volatile char*)where; /* fill latches */
+	readb(where); /* fill latches */
 	setmode(3);
 	wmb();
 	for (y = 0; y < fontheight(p); y++, where += p->line_length) 
-		*where = cdat[y];
+		writeb(cdat[y], where);
 	wmb();
 }
 
@@ -237,9 +248,9 @@
 
 	setmask(0xff);
 	where = p->screen_base + xx + yy * p->line_length * fontheight(p);
-	*where = bg;
+	writeb(bg, where);
 	rmb();
-	*(volatile char*)where;
+	readb(where); /* fill latches */
 	wmb();
 	selectmask();
 	for (n = 0; n < count; n++) {
@@ -250,7 +261,7 @@
 		while (cdat < end) {
 			outb(*cdat++, GRAPHICS_DATA_REG);	
 			wmb();
-			*where = fg;
+			writeb(fg, where);
 			where += p->line_length;
 		}
 		where += 1 - p->line_length * fontheight(p);
@@ -277,9 +288,9 @@
 
 	setmask(0xff);
 	where = p->screen_base + xx + yy * p->line_length * fontheight(p);
-	*where = bg;
+	writeb(bg, where);
 	rmb();
-	*(volatile char*)where; /* fill latches with background */
+	readb(where); /* fill latches */
 	setmode(3);	
 	wmb();
 	for (n = 0; n < count; n++) {
@@ -288,7 +299,7 @@
 		u8 *cdat = p->fontdata + (c & p->charmask) * fontheight(p);
 
 		for (y = 0; y < fontheight(p); y++, cdat++) {
-			*where = *cdat;
+			writeb (*cdat, where);
 			where += p->line_length;
 		}
 		where += 1 - p->line_length * fontheight(p);
diff -u --recursive --new-file v2.3.13/linux/drivers/video/fbmem.c linux/drivers/video/fbmem.c
--- v2.3.13/linux/drivers/video/fbmem.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/fbmem.c	Wed Aug 18 10:10:06 1999
@@ -44,65 +44,65 @@
      *  Frame buffer device initialization and setup routines
      */
 
-extern void acornfb_init(void);
-extern void acornfb_setup(char *options, int *ints);
-extern void amifb_init(void);
-extern void amifb_setup(char *options, int *ints);
-extern void atafb_init(void);
-extern void atafb_setup(char *options, int *ints);
-extern void macfb_init(void);
-extern void macfb_setup(char *options, int *ints);
-extern void cyberfb_init(void);
-extern void cyberfb_setup(char *options, int *ints);
-extern void pm2fb_init(void);
-extern void pm2fb_setup(char *options, int *ints);
-extern void cyber2000fb_init(void);
-extern void cyber2000fb_setup(char *options, int *ints);
-extern void retz3fb_init(void);
-extern void retz3fb_setup(char *options, int *ints);
-extern void clgenfb_init(void);
-extern void clgenfb_setup(char *options, int *ints);
-extern void vfb_init(void);
-extern void vfb_setup(char *options, int *ints);
-extern void offb_init(void);
-extern void offb_setup(char *options, int *ints);
-extern void atyfb_init(void);
-extern void atyfb_setup(char *options, int *ints);
-extern void igafb_init(void);
-extern void igafb_setup(char *options, int *ints);
-extern void imsttfb_init(void);
-extern void imsttfb_setup(char *options, int *ints);
-extern void dnfb_init(void);
-extern void tgafb_init(void);
-extern void tgafb_setup(char *options, int *ints);
-extern void virgefb_init(void);
-extern void virgefb_setup(char *options, int *ints);
-extern void resolver_video_setup(char *options, int *ints);
-extern void s3triofb_init(void);
-extern void s3triofb_setup(char *options, int *ints);
-extern void vesafb_init(void);
-extern void vesafb_setup(char *options, int *ints);
-extern void vga16fb_init(void);
-extern void vga16fb_setup(char *options, int *ints);
-extern void matroxfb_init(void);
-extern void matroxfb_setup(char* options, int *ints);
-extern void hpfb_init(void);
-extern void hpfb_setup(char *options, int *ints);
-extern void sbusfb_init(void);
-extern void sbusfb_setup(char *options, int *ints);
-extern void valkyriefb_init(void);
-extern void valkyriefb_setup(char *options, int *ints);
-extern void g364fb_init(void);
-extern void fm2fb_init(void);
-extern void fm2fb_setup(char *options, int *ints);
-extern void q40fb_init(void);
-extern void sgivwfb_init(void);
-extern void sgivwfb_setup(char* options, int *ints);
+extern int acornfb_init(void);
+extern int acornfb_setup(char*);
+extern int amifb_init(void);
+extern int amifb_setup(char*);
+extern int atafb_init(void);
+extern int atafb_setup(char*);
+extern int macfb_init(void);
+extern int macfb_setup(char*);
+extern int cyberfb_init(void);
+extern int cyberfb_setup(char*);
+extern int pm2fb_init(void);
+extern int pm2fb_setup(char*);
+extern int cyber2000fb_init(void);
+extern int cyber2000fb_setup(char*);
+extern int retz3fb_init(void);
+extern int retz3fb_setup(char*);
+extern int clgenfb_init(void);
+extern int clgenfb_setup(char*);
+extern int vfb_init(void);
+extern int vfb_setup(char*);
+extern int offb_init(void);
+extern int offb_setup(char*);
+extern int atyfb_init(void);
+extern int atyfb_setup(char*);
+extern int igafb_init(void);
+extern int igafb_setup(char*);
+extern int imsttfb_init(void);
+extern int imsttfb_setup(char*);
+extern int dnfb_init(void);
+extern int tgafb_init(void);
+extern int tgafb_setup(char*);
+extern int virgefb_init(void);
+extern int virgefb_setup(char*);
+extern int resolver_video_setup(char*);
+extern int s3triofb_init(void);
+extern int s3triofb_setup(char*);
+extern int vesafb_init(void);
+extern int vesafb_setup(char*);
+extern int vga16fb_init(void);
+extern int vga16fb_setup(char*);
+extern int matroxfb_init(void);
+extern int matroxfb_setup(char*);
+extern int hpfb_init(void);
+extern int hpfb_setup(char*);
+extern int sbusfb_init(void);
+extern int sbusfb_setup(char*);
+extern int valkyriefb_init(void);
+extern int valkyriefb_setup(char*);
+extern int g364fb_init(void);
+extern int fm2fb_init(void);
+extern int fm2fb_setup(char*);
+extern int q40fb_init(void);
+extern int sgivwfb_init(void);
+extern int sgivwfb_setup(char*);
 
 static struct {
 	const char *name;
-	void (*init)(void);
-	void (*setup)(char *options, int *ints);
+	int (*init)(void);
+	int (*setup)(char*);
 } fb_drivers[] __initdata = {
 #ifdef CONFIG_FB_SGIVW
 	{ "sgivw", sgivwfb_init, sgivwfb_setup },
@@ -197,7 +197,9 @@
 
 #define NUM_FB_DRIVERS	(sizeof(fb_drivers)/sizeof(*fb_drivers))
 
-static void (*pref_init_funcs[FB_MAX])(void);
+extern const char *global_mode_option;
+
+static initcall_t pref_init_funcs[FB_MAX];
 static int num_pref_init_funcs __initdata = 0;
 
 
@@ -214,7 +216,7 @@
 static int last_fb_vc = MAX_NR_CONSOLES-1;
 static int fbcon_is_default = 1;
 
-static int PROC_CONSOLE(struct fb_info *info)
+static int PROC_CONSOLE(const struct fb_info *info)
 {
 	int fgc;
 	
@@ -679,12 +681,12 @@
      *  Command line options
      */
 
-void __init video_setup(char *options, int *ints)
+int __init video_setup(char *options)
 {
     int i, j;
 
     if (!options || !*options)
-	    return;
+	    return 0;
 	    
     if (!strncmp(options, "scrollback:", 11)) {
 	    options += 11;
@@ -695,10 +697,10 @@
 			options++;
 		}
 		if (*options != ',')
-			return;
+			return 0;
 		options++;
 	    } else
-	        return;
+	        return 0;
     }
 
     if (!strncmp(options, "map:", 4)) {
@@ -709,7 +711,7 @@
 				    j = 0;
 			    con2fb_map[i] = (options[j++]-'0') % FB_MAX;
 		    }
-	    return;
+	    return 0;
     }
     
     if (!strncmp(options, "vc:", 3)) {
@@ -724,7 +726,7 @@
     }
 
     if (num_pref_init_funcs == FB_MAX)
-	    return;
+	    return 0;
 
     for (i = 0; i < NUM_FB_DRIVERS; i++) {
 	    j = strlen(fb_drivers[i].name);
@@ -739,28 +741,21 @@
 				    fb_drivers[i].init = NULL;
 			    }
 			    if (fb_drivers[i].setup)
-				    fb_drivers[i].setup(options+j+1, ints);
+				    fb_drivers[i].setup(options+j+1);
 		    }
-		    return;
+		    return 0;
 	    }
     }
+
     /*
-     * If we get here no fb was specified and we default to pass the
-     * options to the first frame buffer that has an init and a setup
-     * function.
+     * If we get here no fb was specified.
+     * We consider the argument to be a global video mode option.
      */
-    for (i = 0; i < NUM_FB_DRIVERS; i++) {
-	    if (fb_drivers[i].init && fb_drivers[i].setup) {
-		    pref_init_funcs[num_pref_init_funcs++] =
-			    fb_drivers[i].init;
-		    fb_drivers[i].init = NULL;
-
-		    fb_drivers[i].setup(options, ints);
-		    return;
-	    }
-    }
+    global_mode_option = options;
+    return 0;
 }
 
+__setup("video=", video_setup);
 
     /*
      *  Visible symbols for modules
diff -u --recursive --new-file v2.3.13/linux/drivers/video/fm2fb.c linux/drivers/video/fm2fb.c
--- v2.3.13/linux/drivers/video/fm2fb.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/fm2fb.c	Thu Aug 12 10:22:33 1999
@@ -205,7 +205,7 @@
      *  Interface to the low level console driver
      */
 
-void fm2fb_init(void);
+int fm2fb_init(void);
 static int fm2fbcon_switch(int con, struct fb_info *info);
 static int fm2fbcon_updatevar(int con, struct fb_info *info);
 static void fm2fbcon_blank(int blank, struct fb_info *info);
@@ -374,7 +374,7 @@
      *  Initialisation
      */
 
-void __init fm2fb_init(void)
+int __init fm2fb_init(void)
 {
     int key, is_fm;
     const struct ConfigDev *cd  = NULL;
@@ -383,10 +383,10 @@
 
     if (!(key = is_fm = zorro_find(ZORRO_PROD_BSC_FRAMEMASTER_II, 0, 0)) &&
 	!(key = zorro_find(ZORRO_PROD_HELFRICH_RAINBOW_II, 0, 0)))
-	return;
+	return -ENXIO;
     cd = zorro_get_board(key);
     if (!(board = (u_long)cd->cd_BoardAddr))
-	return;
+	return -ENXIO;
     zorro_config_board(key, 0);
 
     /* assigning memory to kernel space */
@@ -460,18 +460,19 @@
     fm2fb_set_var(&fb_var, -1, &fb_info);
 
     if (register_framebuffer(&fb_info) < 0)
-	return;
+	return -EINVAL;
 
     printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.node),
 	   fb_fix.id);
+    return 0;
 }
 
-void __init fm2fb_setup(char *options, int *ints)
+int __init fm2fb_setup(char *options)
 {
     char *this_opt;
 
     if (!options || !*options)
-	return;
+	return 0;
 
     for (this_opt = strtok(options, ","); this_opt;
 	 this_opt = strtok(NULL, ",")) {
@@ -480,6 +481,7 @@
 	else if (!strncmp(this_opt, "ntsc", 4))
 	    fm2fb_mode = FM2FB_MODE_NTSC;
     }
+    return 0;
 }
 
 
diff -u --recursive --new-file v2.3.13/linux/drivers/video/font_6x11.c linux/drivers/video/font_6x11.c
--- v2.3.13/linux/drivers/video/font_6x11.c	Tue Sep 29 20:56:33 1998
+++ linux/drivers/video/font_6x11.c	Fri Aug 13 12:15:00 1999
@@ -1207,6 +1207,8 @@
 	0x00, /* 00000000 */
 
 	/* 92 0x5c '\' */
+	0x40, /* 0 000000 */
+	0x40, /* 0 000000 */
 	0x20, /* 00 00000 */
 	0x20, /* 00 00000 */
 	0x10, /* 000 0000 */
@@ -1215,8 +1217,6 @@
 	0x08, /* 0000 000 */
 	0x04, /* 00000 00 */
 	0x04, /* 00000 00 */
-	0x02, /* 000000 0 */
-	0x02, /* 000000 0 */
 	0x00, /* 00000000 */
 
 	/* 93 0x5d ']' */
@@ -1253,7 +1253,7 @@
 	0x00, /* 00000000 */
 	0x00, /* 00000000 */
 	0x00, /* 00000000 */
-	0x7e, /* 0      0 */
+	0xfc, /*       00 */
 	0x00, /* 00000000 */
 	0x00, /* 00000000 */
 	0x00, /* 00000000 */
@@ -2222,9 +2222,9 @@
 
 	/* 170 0xaa '\252' */
 	0x00, /* 00000000 */
-	0x7a, /* 0    0 0 */
-	0x2e, /* 00 0   0 */
-	0x2e, /* 00 0   0 */
+	0xf4, /*     0 00 */
+	0x5c, /* 0 0   00 */
+	0x5c, /* 0 0   00 */
 	0x00, /* 00000000 */
 	0x00, /* 00000000 */
 	0x00, /* 00000000 */
@@ -2732,7 +2732,7 @@
 	0x00, /* 00000000 */
 	0x00, /* 00000000 */
 	0x00, /* 00000000 */
-	0x7e, /* 0      0 */
+	0xfc, /*       00 */
 	0x00, /* 00000000 */
 	0x00, /* 00000000 */
 	0x00, /* 00000000 */
@@ -2834,11 +2834,11 @@
 	/* 217 0xd9 '\331' */
 	0x00, /* 00000000 */
 	0x00, /* 00000000 */
-	0x7e, /* 0      0 */
+	0xfc, /*       00 */
 	0x00, /* 00000000 */
-	0x7e, /* 0      0 */
+	0xfc, /*       00 */
 	0x00, /* 00000000 */
-	0x7e, /* 0      0 */
+	0xfc, /*       00 */
 	0x00, /* 00000000 */
 	0x00, /* 00000000 */
 	0x00, /* 00000000 */
diff -u --recursive --new-file v2.3.13/linux/drivers/video/g364fb.c linux/drivers/video/g364fb.c
--- v2.3.13/linux/drivers/video/g364fb.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/g364fb.c	Thu Aug 12 10:22:33 1999
@@ -112,7 +112,7 @@
 /*
  *  Interface to the low level console driver
  */
-void g364fb_init(void);
+int g364fb_init(void);
 static int g364fbcon_switch(int con, struct fb_info *info);
 static int g364fbcon_updatevar(int con, struct fb_info *info);
 static void g364fbcon_blank(int blank, struct fb_info *info);
@@ -297,7 +297,7 @@
 /*
  *  Initialisation
  */
-void __init g364fb_init(void)
+int __init g364fb_init(void)
 {
     int i,j;
     volatile unsigned int *pal_ptr = (volatile unsigned int *) CLR_PAL_REG;
@@ -413,10 +413,11 @@
     g364fb_set_var(&fb_var, -1, &fb_info);
 
     if (register_framebuffer(&fb_info) < 0)
-	return;
+	return -EINVAL;
 
     printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.node),
 	   fb_fix.id);
+    return 0;
 }
 
 
diff -u --recursive --new-file v2.3.13/linux/drivers/video/hpfb.c linux/drivers/video/hpfb.c
--- v2.3.13/linux/drivers/video/hpfb.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/hpfb.c	Thu Aug 12 10:22:33 1999
@@ -384,7 +384,7 @@
  * Initialise the framebuffer
  */
 
-unsigned long __init hpfb_init(unsigned long mem_start)
+int __init hpfb_init(void)
 {
 	unsigned int sid;
 
@@ -421,9 +421,10 @@
 		}
 	}
 
-	return mem_start;
+	return 0;
 }
 
-void __init hpfb_setup(char *options, int *ints)
+int __init hpfb_setup(char *options)
 {
+	return 0;
 }
diff -u --recursive --new-file v2.3.13/linux/drivers/video/igafb.c linux/drivers/video/igafb.c
--- v2.3.13/linux/drivers/video/igafb.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/igafb.c	Thu Aug 12 10:22:33 1999
@@ -624,7 +624,7 @@
 }	
 
 
-void __init igafb_init(void)
+int __init igafb_init(void)
 {
         struct pci_dev *pdev;
         struct fb_info_iga *info;
@@ -634,7 +634,7 @@
 
         /* Do not attach when we have a serial console. */
         if (!con_is_present())
-                return;
+                return -ENXIO;
 
         pdev = pci_find_device(PCI_VENDOR_ID_INTERG, 
                                PCI_DEVICE_ID_INTERG_1682, 0);
@@ -642,28 +642,28 @@
         	pdev = pci_find_device(PCI_VENDOR_ID_INTERG, 
                                0x2000, 0);
         	if(pdev == NULL)
-        	        return;
+        	        return -ENXIO;
 		iga2000 = 1;
 	}
 
         info = kmalloc(sizeof(struct fb_info_iga), GFP_ATOMIC);
         if (!info) {
                 printk("igafb_init: can't alloc fb_info_iga\n");
-                return;
+                return -ENOMEM;
         }
         memset(info, 0, sizeof(struct fb_info_iga));
 
-	info->frame_buffer = pdev->base_address[0];
+	info->frame_buffer = pdev->resource[0].start;
 	if (!info->frame_buffer) {
 		kfree(info);
-		return;
+		return -ENXIO;
 	}
 
         pcibios_read_config_dword(0, pdev->devfn,
                                   PCI_BASE_ADDRESS_0, 
                                   (unsigned int*)&addr);
 	if (!addr)
-		return;
+		return -ENXIO;
 	info->frame_buffer_phys = addr & PCI_BASE_ADDRESS_MEM_MASK;
 
 #ifdef __sparc__
@@ -684,7 +684,7 @@
 	}
 	if (!info->io_base) {
                 kfree(info);
-		return;
+		return -ENXIO;
 	}
 
 	/*
@@ -700,7 +700,7 @@
                 printk("igafb_init: can't alloc mmap_map\n");
 		/* XXX Here we left I/O allocated */
                 kfree(info);
-		return;
+		return -ENOMEM;
 	}
 
 	memset(info->mmap_map, 0, 4 * sizeof(*info->mmap_map));
@@ -775,14 +775,16 @@
 	    info->mmap_map[1].prot_mask = SRMMU_CACHE;
 	    info->mmap_map[1].prot_flag = SRMMU_WRITE;
 #endif /* __sparc__ */
+
+	return 0;
 }
 
-void __init igafb_setup(char *options, int *ints)
+int __init igafb_setup(char *options)
 {
     char *this_opt;
 
     if (!options || !*options)
-        return;
+        return 0;
 
     for (this_opt = strtok(options, ","); this_opt;
          this_opt = strtok(NULL, ",")) {
@@ -798,4 +800,5 @@
                 fontname[i] = 0;
         }
     }
+    return 0;
 }
diff -u --recursive --new-file v2.3.13/linux/drivers/video/imsttfb.c linux/drivers/video/imsttfb.c
--- v2.3.13/linux/drivers/video/imsttfb.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/imsttfb.c	Thu Aug 12 10:22:33 1999
@@ -380,9 +380,7 @@
 #if defined(CONFIG_PPC)
 static signed char init_vmode __initdata = -1, init_cmode __initdata = -1;
 #endif
-#ifdef MODULE
 static struct fb_info_imstt *fb_info_imstt_p[FB_MAX] = { 0, 0, 0, 0, 0, 0, 0, 0 };
-#endif
 
 static struct imstt_regvals tvp_reg_init_2 = {
 	512,
@@ -1853,9 +1851,7 @@
 	printk("fb%u: %s frame buffer; %uMB vram; chip version %u\n",
 		i, p->fix.id, p->total_vram >> 20, tmp);
 
-#ifdef MODULE
 	fb_info_imstt_p[i] = p;
-#endif
 #ifdef CONFIG_FB_COMPAT_XPMAC
 	strncpy(display_info.name, "IMS,tt128mb", sizeof(display_info.name));
 	display_info.fb_address = (__u32)p->frame_buffer_phys;
@@ -1912,9 +1908,10 @@
 }
 #endif
 
-void __init 
+int __init 
 imsttfb_init(void)
 {
+	int i;
 #if defined(CONFIG_FB_OF) && !defined(MODULE)
 	/* We don't want to be called like this. */
 	/* We rely on Open Firmware (offb) instead. */
@@ -1935,13 +1932,13 @@
 			pci_write_config_word(pdev, PCI_COMMAND, cmd);
 		}
 
-		addr = pdev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK;
+		addr = pdev->resource[0].start;
 		if (!addr)
 			continue;
 
 		p = kmalloc(sizeof(struct fb_info_imstt), GFP_ATOMIC);
 		if (!p)
-			return;
+			continue;
 		memset(p, 0, sizeof(struct fb_info_imstt));
 
 		printk("imsttfb: device=%04x\n", pdev->device);
@@ -1966,16 +1963,21 @@
 		init_imstt(p);
 	}
 #endif /* CONFIG_PCI */
+	for (i = 0; i < FB_MAX; i++) {
+		if (fb_info_imstt_p[i])
+			return 0;
+	}
+	return -ENXIO;
 }
 
 #ifndef MODULE
-void __init 
-imsttfb_setup(char *options, int *ints)
+int __init 
+imsttfb_setup(char *options)
 {
 	char *this_opt;
 
 	if (!options || !*options)
-		return;
+		return 0;
 
 	for (this_opt = strtok(options, ","); this_opt;
 	     this_opt = strtok(NULL, ",")) {
@@ -2020,25 +2022,16 @@
 		}
 #endif
 	}
+	return 0;
 }
 
 #else /* MODULE */
 
-int
+int __init
 init_module (void)
 {
-	struct fb_info_imstt *p;
-	__u32 i;
-
-	imsttfb_init();
 
-	for (i = 0; i < FB_MAX; i++) {
-		p = fb_info_imstt_p[i];
-		if (p)
-			return 0;
-	}
-
-	return -ENXIO;
+	return imsttfb_init();
 }
 
 void
diff -u --recursive --new-file v2.3.13/linux/drivers/video/macfb.c linux/drivers/video/macfb.c
--- v2.3.13/linux/drivers/video/macfb.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/macfb.c	Thu Aug 12 10:22:33 1999
@@ -459,14 +459,14 @@
 	macfb_ioctl
 };
 
-void macfb_setup(char *options, int *ints)
+int __init macfb_setup(char *options)
 {
     char *this_opt;
 
     fb_info.fontname[0] = '\0';
 
     if (!options || !*options)
-		return;
+		return 0;
      
     for(this_opt=strtok(options,","); this_opt; this_opt=strtok(NULL,",")) {
 	if (!*this_opt) continue;
@@ -478,6 +478,7 @@
 	   printk("macfb_setup: option %s\n", this_opt);
 	}
     }
+    return 0;
 }
 
 static int macfb_switch(int con, struct fb_info *info)
@@ -512,12 +513,12 @@
 	NULL
 };
 
-void __init macfb_init(void)
+int __init macfb_init(void)
 {
 	/* nubus_remap the video .. */
 
 	if (!MACH_IS_MAC) 
-		return;
+		return -ENXIO;
 
 	mac_xres=mac_bi_data.dimensions&0xFFFF;
 	mac_yres=(mac_bi_data.dimensions&0xFFFF0000)>>16;
@@ -572,11 +573,12 @@
 
 	if (register_framebuffer(&fb_info) < 0)
 	{
-		return;
+		return -EINVAL;
 	}
 
 	printk("fb%d: %s frame buffer device using %ldK of video memory\n",
 	       GET_FB_IDX(fb_info.node), fb_info.modename, mac_videosize>>10);
+	return 0;
 }
 
 #if 0
diff -u --recursive --new-file v2.3.13/linux/drivers/video/macmodes.c linux/drivers/video/macmodes.c
--- v2.3.13/linux/drivers/video/macmodes.c	Wed Sep 30 10:19:11 1998
+++ linux/drivers/video/macmodes.c	Wed Aug 18 10:10:06 1999
@@ -14,240 +14,151 @@
 
 #include <video/macmodes.h>
 
-struct mac_mode {
-    int number;
-    u32 xres;
-    u32 yres;
-    u32 pixclock;
-    u32 left_margin;
-    u32 right_margin;
-    u32 upper_margin;
-    u32 lower_margin;
-    u32 hsync_len;
-    u32 vsync_len;
-    u32 sync;
-    u32 vmode;
-};
-
-
-    /* 512x384, 60Hz, Interlaced (NTSC) */
-
-#if 0
-static const struct mac_mode mac_mode_1 = {
-    VMODE_512_384_60I, 512, 384,
-    pixclock, left, right, upper, lower, hslen, vslen,
-    sync, FB_VMODE_INTERLACED
-};
-#endif
-
-    /* 512x384, 60Hz, Non-Interlaced */
-
-#if 0
-static const struct mac_mode mac_mode_2 = {
-    VMODE_512_384_60, 512, 384,
-    pixclock, left, right, upper, lower, hslen, vslen,
-    sync, FB_VMODE_NONINTERLACED
-};
-#endif
-
-    /* 640x480, 50Hz, Interlaced (PAL) */
-
-#if 0
-static const struct mac_mode mac_mode_3 = {
-    VMODE_640_480_50I, 640, 480,
-    pixclock, left, right, upper, lower, hslen, vslen,
-    sync, FB_VMODE_INTERLACED
-};
-#endif
-
-    /* 640x480, 60Hz, Interlaced (NTSC) */
-
-#if 0
-static const struct mac_mode mac_mode_4 = {
-    VMODE_640_480_60I, 640, 480,
-    pixclock, left, right, upper, lower, hslen, vslen,
-    sync, FB_VMODE_INTERLACED
-};
-#endif
 
-    /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
-
-static const struct mac_mode mac_mode_5 = {
-    VMODE_640_480_60, 640, 480,
-    39722, 32, 32, 33, 10, 96, 2,
-    0, FB_VMODE_NONINTERLACED
-};
-
-    /* 640x480, 67Hz, Non-Interlaced (30.0 MHz dotclock) */
+    /*
+     *  MacOS video mode definitions
+     *
+     *  Order IS important! If you change these, don't forget to update
+     *  mac_modes[] below!
+     */
 
-static const struct mac_mode mac_mode_6 = {
-    VMODE_640_480_67, 640, 480,
-    33334, 80, 80, 39, 3, 64, 3,
-    0, FB_VMODE_NONINTERLACED
-};
+#define DEFAULT_MODEDB_INDEX	0
 
-    /* 640x870, 75Hz (portrait), Non-Interlaced */
+static const struct fb_videomode mac_modedb[] = {
+    {
+	/* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
+	"mac5", 60, 640, 480, 39722, 32, 32, 33, 10, 96, 2,
+	0, FB_VMODE_NONINTERLACED
+    }, {
+	/* 640x480, 67Hz, Non-Interlaced (30.0 MHz dotclock) */
+	"mac6", 67, 640, 480, 33334, 80, 80, 39, 3, 64, 3,
+	0, FB_VMODE_NONINTERLACED
+    }, {
+	/* 800x600, 56 Hz, Non-Interlaced (36.00 MHz dotclock) */
+	"mac9", 56, 800, 600, 27778, 112, 40, 22, 1, 72, 2,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    }, {
+	/* 800x600, 60 Hz, Non-Interlaced (40.00 MHz dotclock) */
+	"mac10", 60, 800, 600, 25000, 72, 56, 23, 1, 128, 4,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    }, {
+	/* 800x600, 72 Hz, Non-Interlaced (50.00 MHz dotclock) */
+	"mac11", 72, 800, 600, 20000, 48, 72, 23, 37, 120, 6,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    }, {
+	/* 800x600, 75 Hz, Non-Interlaced (49.50 MHz dotclock) */
+	"mac12", 75, 800, 600, 20203, 144, 32, 21, 1, 80, 3,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    }, {
+	/* 832x624, 75Hz, Non-Interlaced (57.6 MHz dotclock) */
+	"mac13", 75, 832, 624, 17362, 208, 48, 39, 1, 64, 3,
+	0, FB_VMODE_NONINTERLACED
+    }, {
+	/* 1024x768, 60 Hz, Non-Interlaced (65.00 MHz dotclock) */
+	"mac14", 60, 1024, 768, 15385, 144, 40, 29, 3, 136, 6,
+	0, FB_VMODE_NONINTERLACED
+    }, {
+	/* 1024x768, 72 Hz, Non-Interlaced (75.00 MHz dotclock) */
+	"mac15", 72, 1024, 768, 13334, 128, 40, 29, 3, 136, 6,
+	0, FB_VMODE_NONINTERLACED
+    }, {
+	/* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */
+	"mac16", 75, 1024, 768, 12699, 176, 16, 28, 1, 96, 3,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    }, {
+	/* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */
+	"mac17", 75, 1024, 768, 12699, 160, 32, 28, 1, 96, 3,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    }, {
+	/* 1152x870, 75 Hz, Non-Interlaced (100.0 MHz dotclock) */
+	"mac18", 75, 1152, 870, 10000, 128, 48, 39, 3, 128, 3,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    }, {
+	/* 1280x960, 75 Hz, Non-Interlaced (126.00 MHz dotclock) */
+	"mac19", 75, 1280, 960, 7937, 224, 32, 36, 1, 144, 3,
+	0, FB_VMODE_NONINTERLACED
+    }, {
+	/* 1280x1024, 75 Hz, Non-Interlaced (135.00 MHz dotclock) */
+	"mac20", 75, 1280, 1024, 7408, 232, 64, 38, 1, 112, 3,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
 
 #if 0
-static const struct mac_mode mac_mode_7 = {
-    VMODE_640_870_75P, 640, 870,
-    pixclock, left, right, upper, lower, hslen, vslen,
-    sync, FB_VMODE_NONINTERLACED
-};
+    /* Anyone who has timings for these? */
+    {
+	/* VMODE_512_384_60I: 512x384, 60Hz, Interlaced (NTSC) */
+	"mac1", 60, 512, 384, pixclock, left, right, upper, lower, hslen, vslen,
+	sync, FB_VMODE_INTERLACED
+    }, {
+	/* VMODE_512_384_60: 512x384, 60Hz, Non-Interlaced */
+    	"mac2", 60, 512, 384, pixclock, left, right, upper, lower, hslen, vslen,
+	sync, FB_VMODE_NONINTERLACED
+    }, {
+	/* VMODE_640_480_50I: 640x480, 50Hz, Interlaced (PAL) */
+	"mac3", 50, 640, 480, pixclock, left, right, upper, lower, hslen, vslen,
+	sync, FB_VMODE_INTERLACED
+    }, {
+	/* VMODE_640_480_60I: 640x480, 60Hz, Interlaced (NTSC) */
+	"mac4", 60, 640, 480, pixclock, left, right, upper, lower, hslen, vslen,
+	sync, FB_VMODE_INTERLACED
+    }, {
+	/* VMODE_640_870_75P: 640x870, 75Hz (portrait), Non-Interlaced */
+	"mac7", 75, 640, 870, pixclock, left, right, upper, lower, hslen, vslen,
+	sync, FB_VMODE_NONINTERLACED
+    }, {
+	/* VMODE_768_576_50I: 768x576, 50Hz (PAL full frame), Interlaced */
+	"mac8", 50, 768, 576, pixclock, left, right, upper, lower, hslen, vslen,
+	sync, FB_VMODE_INTERLACED
+    },
 #endif
-
-    /* 768x576, 50Hz (PAL full frame), Interlaced */
-
-#if 0
-static const struct mac_mode mac_mode_8 = {
-    VMODE_768_576_50I, 768, 576,
-    pixclock, left, right, upper, lower, hslen, vslen,
-    sync, FB_VMODE_INTERLACED
 };
-#endif
 
-    /* 800x600, 56 Hz, Non-Interlaced (36.00 MHz dotclock) */
-
-static const struct mac_mode mac_mode_9 = {
-    VMODE_800_600_56, 800, 600,
-    27778, 112, 40, 22, 1, 72, 2,
-    FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-};
-
-    /* 800x600, 60 Hz, Non-Interlaced (40.00 MHz dotclock) */
-
-static const struct mac_mode mac_mode_10 = {
-    VMODE_800_600_60, 800, 600,
-    25000, 72, 56, 23, 1, 128, 4,
-    FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-};
-
-    /* 800x600, 72 Hz, Non-Interlaced (50.00 MHz dotclock) */
-
-static const struct mac_mode mac_mode_11 = {
-    VMODE_800_600_72, 800, 600,
-    20000, 48, 72, 23, 37, 120, 6,
-    FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-};
-
-    /* 800x600, 75 Hz, Non-Interlaced (49.50 MHz dotclock) */
-
-static const struct mac_mode mac_mode_12 = {
-    VMODE_800_600_75, 800, 600,
-    20203, 144, 32, 21, 1, 80, 3,
-    FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-};
-
-    /* 832x624, 75Hz, Non-Interlaced (57.6 MHz */
-
-static const struct mac_mode mac_mode_13 = {
-    VMODE_832_624_75, 832, 624,
-    17362, 208, 48, 39, 1, 64, 3,
-    0, FB_VMODE_NONINTERLACED
-};
-
-    /* 1024x768, 60 Hz, Non-Interlaced (65.00 MHz dotclock) */
-
-static const struct mac_mode mac_mode_14 = {
-    VMODE_1024_768_60, 1024, 768,
-    15385, 144, 40, 29, 3, 136, 6,
-    0, FB_VMODE_NONINTERLACED
-};
-
-    /* 1024x768, 72 Hz, Non-Interlaced (75.00 MHz dotclock) */
-
-static const struct mac_mode mac_mode_15 = {
-    VMODE_1024_768_70, 1024, 768,
-    13334, 128, 40, 29, 3, 136, 6,
-    0, FB_VMODE_NONINTERLACED
-};
-
-    /* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */
-
-static const struct mac_mode mac_mode_16 = {
-    VMODE_1024_768_75V, 1024, 768,
-    12699, 176, 16, 28, 1, 96, 3,
-    FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-};
-
-    /* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */
-
-static const struct mac_mode mac_mode_17 = {
-    VMODE_1024_768_75, 1024, 768,
-    12699, 160, 32, 28, 1, 96, 3,
-    FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-};
-
-    /* 1152x870, 75 Hz, Non-Interlaced (100.0 MHz dotclock) */
-
-static const struct mac_mode mac_mode_18 = {
-    VMODE_1152_870_75, 1152, 870,
-    10000, 128, 48, 39, 3, 128, 3,
-    FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-};
-
-    /* 1280x960, 75 Hz, Non-Interlaced (126.00 MHz dotclock) */
-
-static const struct mac_mode mac_mode_19 = {
-    VMODE_1280_960_75, 1280, 960,
-    7937, 224, 32, 36, 1, 144, 3,
-    0, FB_VMODE_NONINTERLACED
-};
-
-    /* 1280x1024, 75 Hz, Non-Interlaced (135.00 MHz dotclock) */
-
-static const struct mac_mode mac_mode_20 = {
-    VMODE_1280_1024_75, 1280, 1024,
-    7408, 232, 64, 38, 1, 112, 3,
-    FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-};
 
+    /*
+     *  Mapping between MacOS video mode numbers and video mode definitions
+     *
+     *  These MUST be ordered in
+     *    - increasing resolution
+     *    - decreasing refresh rate
+     */
 
-static const struct mac_mode *mac_modes[20] = {
-    NULL,		/* 512x384, 60Hz interlaced (NTSC) */
-    NULL,		/* 512x384, 60Hz */
-    NULL,		/* 640x480, 50Hz interlaced (PAL) */
-    NULL,		/* 640x480, 60Hz interlaced (NTSC) */
-    &mac_mode_5,	/* 640x480, 60Hz (VGA) */
-    &mac_mode_6,	/* 640x480, 67Hz */
-    NULL,		/* 640x870, 75Hz (portrait) */
-    NULL,		/* 768x576, 50Hz (PAL full frame) */
-    &mac_mode_9,	/* 800x600, 56Hz */
-    &mac_mode_10,	/* 800x600, 60Hz */
-    &mac_mode_11,	/* 800x600, 72Hz */
-    &mac_mode_12,	/* 800x600, 75Hz */
-    &mac_mode_13,	/* 832x624, 75Hz */
-    &mac_mode_14,	/* 1024x768, 60Hz */
-    &mac_mode_15,	/* 1024x768, 70Hz (or 72Hz?) */
-    &mac_mode_16,	/* 1024x768, 75Hz (VESA) */
-    &mac_mode_17,	/* 1024x768, 75Hz */
-    &mac_mode_18,	/* 1152x870, 75Hz */
-    &mac_mode_19,	/* 1280x960, 75Hz */
-    &mac_mode_20,	/* 1280x1024, 75Hz */
+static const struct mode_map {
+    int vmode;
+    const struct fb_videomode *mode;
+} mac_modes[] = {
+    /* 640x480 */
+    { VMODE_640_480_67, &mac_modedb[1] },
+    { VMODE_640_480_60, &mac_modedb[0] },
+    /* 800x600 */
+    { VMODE_800_600_75, &mac_modedb[5] },
+    { VMODE_800_600_72, &mac_modedb[4] },
+    { VMODE_800_600_60, &mac_modedb[3] },
+    { VMODE_800_600_56, &mac_modedb[2] },
+    /* 832x624 */
+    { VMODE_832_624_75, &mac_modedb[6] },
+    /* 1024x768 */
+    { VMODE_1024_768_75, &mac_modedb[10] },
+    { VMODE_1024_768_75V, &mac_modedb[9] },
+    { VMODE_1024_768_70, &mac_modedb[8] },
+    { VMODE_1024_768_60, &mac_modedb[7] },
+    /* 1152x870 */
+    { VMODE_1152_870_75, &mac_modedb[11] },
+    /* 1280x960 */
+    { VMODE_1280_960_75, &mac_modedb[12] },
+    /* 1280x1024 */
+    { VMODE_1280_1024_75, &mac_modedb[13] },
+    { -1, NULL }
 };
 
-static const struct mac_mode *mac_modes_inv[] = {
-    &mac_mode_6,	/* 640x480, 67Hz */
-    &mac_mode_5,	/* 640x480, 60Hz (VGA) */
-    &mac_mode_12,	/* 800x600, 75Hz */
-    &mac_mode_11,	/* 800x600, 72Hz */
-    &mac_mode_10,	/* 800x600, 60Hz */
-    &mac_mode_9,	/* 800x600, 56Hz */
-    &mac_mode_13,	/* 832x624, 75Hz */
-    &mac_mode_17,	/* 1024x768, 75Hz */
-    &mac_mode_16,	/* 1024x768, 75Hz (VESA) */
-    &mac_mode_15,	/* 1024x768, 70Hz (or 72Hz?) */
-    &mac_mode_14,	/* 1024x768, 60Hz */
-    &mac_mode_18,	/* 1152x870, 75Hz */
-    &mac_mode_19,	/* 1280x960, 75Hz */
-    &mac_mode_20,	/* 1280x1024, 75Hz */
-};
 
+    /*
+     *  Mapping between monitor sense values and MacOS video mode numbers
+     */
 
-static struct mon_map {
+static const struct monitor_map {
     int sense;
     int vmode;
-} monitor_map[] = {
+} mac_monitors[] = {
     { 0x000, VMODE_1280_1024_75 },	/* 21" RGB */
     { 0x114, VMODE_640_870_75P },	/* Portrait Monochrome */
     { 0x221, VMODE_512_384_60 },	/* 12" RGB*/
@@ -277,11 +188,14 @@
 
 int mac_vmode_to_var(int vmode, int cmode, struct fb_var_screeninfo *var)
 {
-    const struct mac_mode *mode = NULL;
-
-    if (vmode > 0 && vmode <= VMODE_MAX)
-	mode = mac_modes[vmode-1];
+    const struct fb_videomode *mode = NULL;
+    const struct mode_map *map;
 
+    for (map = mac_modes; map->vmode != -1; map++)
+	if (map->vmode == vmode) {
+	    mode = map->mode;
+	    break;
+	}
     if (!mode)
 	return -EINVAL;
 
@@ -348,7 +262,8 @@
 int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode,
 		     int *cmode)
 {
-    unsigned int i;
+    const struct fb_videomode *mode = NULL;
+    const struct mode_map *map;
 
     if (var->bits_per_pixel <= 8)
 	*cmode = CMODE_8;
@@ -359,8 +274,8 @@
     else
 	return -EINVAL;
 
-    for (i = 0; i < sizeof(mac_modes_inv)/sizeof(*mac_modes_inv); i++) {
-	const struct mac_mode *mode = mac_modes_inv[i];
+    for (map = mac_modes; map->vmode != -1; map++) {
+	mode = map->mode;
 	if (var->xres > mode->xres || var->yres > mode->yres)
 	    continue;
 	if (var->xres_virtual > mode->xres || var->yres_virtual > mode->yres)
@@ -369,7 +284,7 @@
 	    continue;
 	if ((var->vmode & FB_VMODE_MASK) != mode->vmode)
 	    continue;
-	*vmode = mode->number;
+	*vmode = map->vmode;
 	return 0;
     }
     return -EINVAL;
@@ -382,10 +297,32 @@
 
 int mac_map_monitor_sense(int sense)
 {
-    struct mon_map *map;
+    const struct monitor_map *map;
 
-    for (map = monitor_map; map->sense >= 0; ++map)
+    for (map = mac_monitors; map->sense != -1; map++)
 	if (map->sense == sense)
 	    break;
     return map->vmode;
+}
+
+
+    /*
+     *  Find a suitable video mode
+     *
+     *  If the name of the wanted mode begins with `mac', use the Mac video
+     *  mode database, else fall back to the standard video mode database.
+     */
+
+int __init mac_find_mode(struct fb_var_screeninfo *var, struct fb_info *info,
+			 const char *mode_option, unsigned int default_bpp)
+{
+    const struct fb_videomode *db = NULL;
+    unsigned int dbsize = 0;
+
+    if (mode_option && !strncmp(mode_option, "mac", 3)) {
+	db = mac_modedb;
+	dbsize = sizeof(mac_modedb)/sizeof(*mac_modedb);
+    }
+    return fb_find_mode(var, info, mode_option, db, dbsize,
+			&mac_modedb[DEFAULT_MODEDB_INDEX], default_bpp);
 }
diff -u --recursive --new-file v2.3.13/linux/drivers/video/matroxfb.c linux/drivers/video/matroxfb.c
--- v2.3.13/linux/drivers/video/matroxfb.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/matroxfb.c	Thu Aug 12 10:22:33 1999
@@ -5152,9 +5152,10 @@
 static unsigned int fh = 0;		/* "matrox:fh:xxxxxk" */
 static unsigned int maxclk = 0;		/* "matrox:maxclk:xxxxM" */
 static char fontname[64];		/* "matrox:font:xxxxx" */
+static char videomode[64];		/* "matrox:mode:xxxxx" or "matrox:xxxxx" */
 
 #ifndef MODULE
-void __init matroxfb_setup(char *options, int *ints){
+int __init matroxfb_setup(char *options) {
 	char *this_opt;
 	
 	DBG("matroxfb_setup")
@@ -6088,7 +6089,7 @@
 #ifndef MODULE
 static int __init initialized = 0;
 
-void __init matroxfb_init(void)
+int __init matroxfb_init(void)
 {
 	DBG("matroxfb_init")
 	
diff -u --recursive --new-file v2.3.13/linux/drivers/video/offb.c linux/drivers/video/offb.c
--- v2.3.13/linux/drivers/video/offb.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/offb.c	Sat Aug 14 22:27:41 1999
@@ -72,8 +72,8 @@
      *  Interface used by the world
      */
 
-void offb_init(void);
-void offb_setup(char *options, int *ints);
+int offb_init(void);
+int offb_setup(char*);
 
 static int offb_open(struct fb_info *info, int user);
 static int offb_release(struct fb_info *info, int user);
@@ -314,13 +314,16 @@
 #ifdef CONFIG_FB_PLATINUM
 extern void platinum_of_init(struct device_node *dp);
 #endif /* CONFIG_FB_PLATINUM */
+#ifdef CONFIG_FB_CLGEN
+extern void clgen_of_init(struct device_node *dp);
+#endif /* CONFIG_FB_CLGEN */
 
 
     /*
      *  Initialisation
      */
 
-void __init offb_init(void)
+int __init offb_init(void)
 {
     struct device_node *dp;
     unsigned int dpy;
@@ -389,6 +392,7 @@
 		offb_init_driver(dp);
 	}
     }
+    return 0;
 }
 
 static int __init offb_init_driver(struct device_node *dp)
@@ -441,6 +445,13 @@
 	return 1;
     }
 #endif /* CONFIG_FB_PLATINUM */
+#ifdef CONFIG_FB_CLGEN
+    if ((!strncmp(dp->name, "MacPicasso",10) ||
+        (!strncmp(dp->name, "54m30",5)) {
+       clgen_of_init(dp);
+       return 1;
+    }
+#endif /* CONFIG_FB_CLGEN */
     return 0;
 }
 
@@ -473,7 +484,7 @@
 	    if (dp->addrs[i].size >= len)
 		break;
 	if (i >= dp->n_addrs) {
-	    printk("no framebuffer address found for %s\n", dp->full_name);
+	    printk(KERN_ERR "no framebuffer address found for %s\n", dp->full_name);
 	    return;
 	}
 
@@ -501,7 +512,7 @@
     printk(KERN_INFO "Using unsupported %dx%d %s at %lx, depth=%d, pitch=%d\n",
 	   width, height, name, address, depth, pitch);
     if (depth != 8 && depth != 16 && depth != 32) {
-	printk("%s: can't use depth = %d\n", full_name, depth);
+	printk(KERN_ERR "%s: can't use depth = %d\n", full_name, depth);
 	return;
     }
 
@@ -674,7 +685,7 @@
 	return;
     }
 
-    printk("fb%d: Open Firmware frame buffer device on %s\n",
+    printk(KERN_INFO "fb%d: Open Firmware frame buffer device on %s\n",
 	   GET_FB_IDX(info->info.node), full_name);
 
 #ifdef CONFIG_FB_COMPAT_XPMAC
@@ -706,13 +717,14 @@
      *  Setup: parse used options
      */
 
-void offb_setup(char *options, int *ints)
+int offb_setup(char *options)
 {
     if (!options || !*options)
-	return;
+	return 0;
 
     if (!strcmp(options, "ofonly"))
 	ofonly = 1;
+    return 0;
 }
 
 
diff -u --recursive --new-file v2.3.13/linux/drivers/video/platinumfb.c linux/drivers/video/platinumfb.c
--- v2.3.13/linux/drivers/video/platinumfb.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/platinumfb.c	Thu Aug 12 10:22:33 1999
@@ -156,11 +156,11 @@
  * Interface used by the world
  */
 
-void platinum_init(void);
+int platinum_init(void);
 #ifdef CONFIG_FB_OF
 void platinum_of_init(struct device_node *dp);
 #endif
-void platinum_setup(char *options, int *ints);
+int platinum_setup(char*);
 
 
 static struct fb_ops platinumfb_ops = {
@@ -651,7 +651,7 @@
 	return 1;
 }
 
-void __init platinum_init(void)
+int __init platinum_init(void)
 {
 #ifndef CONFIG_FB_OF
 	struct device_node *dp;
@@ -660,6 +660,7 @@
 	if (dp != 0)
 		platinum_of_init(dp);
 #endif /* CONFIG_FB_OF */
+	return 0;
 }
 
 #ifdef __powerpc__
@@ -676,8 +677,10 @@
 	unsigned long		addr, size;
 	int			i, bank0, bank1, bank2, bank3;
 
-	if(dp->n_addrs != 2)
-		panic("expecting 2 address for platinum (got %d)", dp->n_addrs);
+	if(dp->n_addrs != 2) {
+		printk(KERN_ERR "expecting 2 address for platinum (got %d)", dp->n_addrs);
+		return;
+	}
 
 	info = kmalloc(sizeof(*info), GFP_ATOMIC);
 	if (info == 0)
@@ -854,12 +857,12 @@
 /* 
  * Parse user speficied options (`video=platinumfb:')
  */
-void __init platinum_setup(char *options, int *ints)
+int __init platinum_setup(char *options)
 {
 	char *this_opt;
 
 	if (!options || !*options)
-		return;
+		return 0;
 
 	for (this_opt = strtok(options, ","); this_opt;
 	     this_opt = strtok(NULL, ",")) {
@@ -895,4 +898,5 @@
 			}
 		}
 	}
+	return 0;
 }
diff -u --recursive --new-file v2.3.13/linux/drivers/video/pm2fb.c linux/drivers/video/pm2fb.c
--- v2.3.13/linux/drivers/video/pm2fb.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/pm2fb.c	Thu Aug 12 10:22:33 1999
@@ -50,7 +50,7 @@
 
 #define PM2FB_MASTER_DEBUG
 #ifdef PM2FB_MASTER_DEBUG
-#define DPRINTK(a,b...)	printk("pm2fb: %s: " a, __FUNCTION__ , ## b)
+#define DPRINTK(a,b...)	printk(KERN_DEBUG "pm2fb: %s: " a, __FUNCTION__ , ## b)
 #else
 #define DPRINTK(a,b...)
 #endif 
@@ -852,27 +852,27 @@
 		return 0;
 	}
 	DPRINTK("PCI board @%08lx %08lx %08lx rom %08lx\n",
-			pci->dev->base_address[0],
-			pci->dev->base_address[1],
-			pci->dev->base_address[2],
+			pci->dev->resource[0].start,
+			pci->dev->resource[1].start,
+			pci->dev->resource[2].start,
 			pci->dev->rom_address);
 #ifdef __sparc__
 	p->regions.rg_base=(unsigned char* )
-		__pa(pci->dev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK);
+		__pa(pci->dev->resource[0].start);
 	p->regions.fb_base=(unsigned char* )
-		__pa(pci->dev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK);
+		__pa(pci->dev->resource[1].start);
 #else
 	if (pm2fb_options.flags & OPTF_VIRTUAL) {
 		p->regions.rg_base=(unsigned char* )
-			__pa(pci->dev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK);
+			__pa(pci->dev->resource[0].start);
 		p->regions.fb_base=(unsigned char* )
-			__pa(pci->dev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK);
+			__pa(pci->dev->resource[1].start);
 	}
 	else {
 		p->regions.rg_base=(unsigned char* )
-			(pci->dev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK);
+			(pci->dev->resource[0].start);
 		p->regions.fb_base=(unsigned char* )
-			(pci->dev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK);
+			(pci->dev->resource[0].start);
 	}
 #endif
 #ifdef __BIG_ENDIAN
@@ -1591,11 +1591,11 @@
 		board_table[i->board].cleanup(i);
 }
 
-void __init pm2fb_init(void){
+int __init pm2fb_init(void){
 
 	memset(&fb_info, 0, sizeof(fb_info));
 	if (!pm2fb_conf(&fb_info))
-		return;
+		return -ENXIO;
 	pm2fb_reset(&fb_info);
 	fb_info.disp.scrollmode=SCROLL_YNOMOVE;
 	fb_info.gen.parsize=sizeof(struct pm2fb_par);
@@ -1613,15 +1613,16 @@
 	fbgen_set_disp(-1, &fb_info.gen);
 	fbgen_install_cmap(0, &fb_info.gen);
 	if (register_framebuffer(&fb_info.gen.info)<0) {
-		printk("pm2fb: unable to register.\n");
-		return;
+		printk(KERN_ERR "pm2fb: unable to register.\n");
+		return -EINVAL;
 	}
-	printk("fb%d: %s (%s), using %uK of video memory.\n",
+	printk(KERN_INFO "fb%d: %s (%s), using %uK of video memory.\n",
 				GET_FB_IDX(fb_info.gen.info.node),
 				board_table[fb_info.board].name,
 				permedia2_name,
 				(u32 )(fb_info.regions.fb_size>>10));
 	MOD_INC_USE_COUNT;
+	return 0;
 }
 
 void __init pm2fb_mode_setup(char* options){
@@ -1640,7 +1641,7 @@
 	pm2fb_options.font[sizeof(pm2fb_options.font)-1]='\0';
 }
 
-void __init pm2fb_setup(char* options, int* ints){
+int __init pm2fb_setup(char* options){
 	char* next;
 
 	while (options) {
@@ -1658,6 +1659,7 @@
 			pm2fb_options.flags |= OPTF_VIRTUAL;
 		options=next;
 	}
+	return 0;
 }
 
 /***************************************************************************
@@ -1665,9 +1667,9 @@
  ***************************************************************************/
 
 #ifdef MODULE
-int init_module(void) {
+int __init init_module(void) {
 
-	pm2fb_init();
+	return pm2fb_init();
 }
 
 void cleanup_module(void) {
diff -u --recursive --new-file v2.3.13/linux/drivers/video/q40fb.c linux/drivers/video/q40fb.c
--- v2.3.13/linux/drivers/video/q40fb.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/q40fb.c	Thu Aug 12 10:22:33 1999
@@ -236,7 +236,7 @@
 			     cmap, kspc ? 0 : 2);
 	return 0;
 #else
-	printk("get cmap not supported\n");
+	printk(KERN_ERR "get cmap not supported\n");
 
 	return -EINVAL;
 #endif
@@ -260,7 +260,7 @@
 		fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
 	return 0;
 #else
-	printk("set cmap not supported\n");
+	printk(KERN_ERR "set cmap not supported\n");
 
 	return -EINVAL;
 #endif
@@ -269,7 +269,7 @@
 static int q40fb_pan_display(struct fb_var_screeninfo *var, int con,
 			    struct fb_info *info)
 {
-	printk("panning not supported\n");
+	printk(KERN_ERR "panning not supported\n");
 
 	return -EINVAL;
 
@@ -337,11 +337,11 @@
 #endif
 }
   
-void q40fb_init(void)
+int q40fb_init(void)
 {
 
         if ( !MACH_IS_Q40)
-	  return;
+	  return -ENXIO;
 #if 0
         q40_screen_addr = kernel_map(Q40_PHYS_SCREEN_ADDR, 1024*1024,
 					   KERNELMAP_NO_COPYBACK, NULL);
@@ -365,12 +365,14 @@
         q40fb_get_var(&disp[0].var, 0, &fb_info);
 	q40fb_set_disp(-1, &fb_info);
 
-	if (register_framebuffer(&fb_info) < 0)
-		panic("unable to register Q40 frame buffer\n");
- 
+	if (register_framebuffer(&fb_info) < 0) {
+		printk(KERN_ERR "unable to register Q40 frame buffer\n");
+		return -EINVAL;
+	}
 
-        printk("fb%d: Q40 frame buffer alive and kicking !\n",
+        printk(KERN_INFO "fb%d: Q40 frame buffer alive and kicking !\n",
 	       GET_FB_IDX(fb_info.node));
+	return 0;
 }	
 
 	
diff -u --recursive --new-file v2.3.13/linux/drivers/video/retz3fb.c linux/drivers/video/retz3fb.c
--- v2.3.13/linux/drivers/video/retz3fb.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/retz3fb.c	Wed Aug 18 10:10:06 1999
@@ -170,7 +170,10 @@
  *    Predefined Video Modes
  */
 
-static struct fb_videomode retz3fb_predefined[] __initdata = {
+static struct {
+    const char *name;
+    struct fb_var_screeninfo var;
+} retz3fb_predefined[] __initdata = {
     /*
      * NB: it is very important to adjust the pixel-clock to the color-depth.
      */
@@ -262,7 +265,7 @@
  *    Interface used by the world
  */
 
-void retz3fb_setup(char *options);
+int retz3fb_setup(char *options);
 
 static int retz3fb_open(struct fb_info *info, int user);
 static int retz3fb_release(struct fb_info *info, int user);
@@ -287,7 +290,7 @@
  *    Interface to the low level console driver
  */
 
-void retz3fb_init(void);
+int retz3fb_init(void);
 static int z3fb_switch(int con, struct fb_info *info);
 static int z3fb_updatevar(int con, struct fb_info *info);
 static void z3fb_blank(int blank, struct fb_info *info);
@@ -487,7 +490,7 @@
 #endif
 
 	if (data.v_total >= 1024)
-		printk("MAYDAY: v_total >= 1024; bailing out!\n");
+		printk(KERN_ERR "MAYDAY: v_total >= 1024; bailing out!\n");
 
 	reg_w(regs, GREG_MISC_OUTPUT_W, 0xe3 | ((clocksel & 3) * 0x04));
 	reg_w(regs, GREG_FEATURE_CONTROL_W, 0x00);
@@ -767,7 +770,7 @@
 		reg_w(regs, 0x83c6, 0xe0);
 		break;
 	default:
-		printk("Illegal color-depth: %i\n", bpp);
+		printk(KERN_INFO "Illegal color-depth: %i\n", bpp);
 	}
 
 	reg_w(regs, VDAC_ADDRESS, 0x00);
@@ -1391,12 +1394,12 @@
 };
 
 
-void __init retz3fb_setup(char *options, int *ints)
+int __init retz3fb_setup(char *options)
 {
 	char *this_opt;
 
 	if (!options || !*options)
-		return;
+		return 0;
 
 	for (this_opt = strtok(options, ","); this_opt;
 	     this_opt = strtok(NULL, ",")){
@@ -1409,6 +1412,7 @@
 		} else
 			z3fb_mode = get_video_mode(this_opt);
 	}
+	return 0;
 }
 
 
@@ -1416,7 +1420,7 @@
  *    Initialization
  */
 
-void __init retz3fb_init(void)
+int __init retz3fb_init(void)
 {
 	unsigned long board_addr, board_size;
 	unsigned int key;
@@ -1428,10 +1432,10 @@
 	short i;
 
 	if (!(key = zorro_find(ZORRO_PROD_MACROSYSTEMS_RETINA_Z3, 0, 0)))
-		return;
+		return -ENXIO;
 
 	if (!(zinfo = kmalloc(sizeof(struct retz3_fb_info), GFP_KERNEL)))
-		return;
+		return -ENOMEM;
 	memset(zinfo, 0, sizeof(struct retz3_fb_info));
 
 	cd = zorro_get_board (key);
@@ -1489,13 +1493,15 @@
 	do_install_cmap(0, fb_info);
 
 	if (register_framebuffer(fb_info) < 0)
-		return;
+		return -EINVAL;
 
-	printk("fb%d: %s frame buffer device, using %ldK of video memory\n",
+	printk(KERN_INFO "fb%d: %s frame buffer device, using %ldK of video memory\n",
 	       GET_FB_IDX(fb_info->node), fb_info->modename,zinfo->fbsize>>10);
 
 	/* TODO: This driver cannot be unloaded yet */
 	MOD_INC_USE_COUNT;
+
+	return 0;
 }
 
 
@@ -1576,8 +1582,7 @@
 #ifdef MODULE
 int init_module(void)
 {
-	retz3fb_init();
-	return 0;
+	return retz3fb_init();
 }
 
 void cleanup_module(void)
diff -u --recursive --new-file v2.3.13/linux/drivers/video/sbusfb.c linux/drivers/video/sbusfb.c
--- v2.3.13/linux/drivers/video/sbusfb.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/sbusfb.c	Thu Aug 12 10:22:33 1999
@@ -53,8 +53,8 @@
      *  Interface used by the world
      */
 
-void sbusfb_init(void);
-void sbusfb_setup(char *options, int *ints);
+int sbusfb_init(void);
+int sbusfb_setup(char*);
 
 static int currcon;
 static int defx_margin = -1, defy_margin = -1;
@@ -743,7 +743,7 @@
      *  Setup: parse used options
      */
 
-void __init sbusfb_setup(char *options, int *ints)
+int __init sbusfb_setup(char *options)
 {
 	char *p;
 	
@@ -775,6 +775,7 @@
 		if (*p != ',') break;
 		p++;
 	}
+	return 0;
 }
 
 static int sbusfbcon_switch(int con, struct fb_info *info)
@@ -1128,7 +1129,7 @@
 		kfree(fb);
 		return;
 	}
-	printk("fb%d: %s\n", GET_FB_IDX(fb->info.node), p);
+	printk(KERN_INFO "fb%d: %s\n", GET_FB_IDX(fb->info.node), p);
 }
 
 static inline int known_card(char *name)
@@ -1151,7 +1152,7 @@
 	return FBTYPE_NOTYPE;
 }
 
-void __init sbusfb_init(void)
+int __init sbusfb_init(void)
 {
 	int type;
 	struct linux_sbus_device *sbdp;
@@ -1159,7 +1160,7 @@
 	char prom_name[40];
 	extern int con_is_present(void);
 	
-	if (!con_is_present()) return;
+	if (!con_is_present()) return -ENXIO;
 	
 #ifdef CONFIG_FB_CREATOR
 	{
@@ -1199,4 +1200,5 @@
 				       sbdp->num_registers, sbdp);
 		sbusfb_init_fb(sbdp->prom_node, sbdp->my_bus->prom_node, type, sbdp);
 	}
+	return 0;
 }	
diff -u --recursive --new-file v2.3.13/linux/drivers/video/sgivwfb.c linux/drivers/video/sgivwfb.c
--- v2.3.13/linux/drivers/video/sgivwfb.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/sgivwfb.c	Thu Aug 12 10:22:33 1999
@@ -89,7 +89,7 @@
 /*
  *  Interface used by the world
  */
-void sgivwfb_setup(char *options, int *ints);
+int sgivwfb_setup(char*);
 
 static int sgivwfb_open(struct fb_info *info, int user);
 static int sgivwfb_release(struct fb_info *info, int user);
@@ -126,7 +126,7 @@
 /*
  *  Interface to the low level console driver
  */
-void sgivwfb_init(void);
+int sgivwfb_init(void);
 static int sgivwfbcon_switch(int con, struct fb_info *info);
 static int sgivwfbcon_updatevar(int con, struct fb_info *info);
 static void sgivwfbcon_blank(int blank, struct fb_info *info);
@@ -165,7 +165,7 @@
     length = 4;
     break;
   default:
-    printk("sgivwfb: unsupported bpp=%d\n", bpp);
+    printk(KERN_INFO "sgivwfb: unsupported bpp=%d\n", bpp);
     length = 0;
     break;
   }
@@ -271,7 +271,7 @@
   if (wholeTilesX*maxPixelsPerTileX < xpmax)
     wholeTilesX++;
 
-  printk("sgivwfb: pixPerTile=%d wholeTilesX=%d\n",
+  printk(KERN_DEBUG "sgivwfb: pixPerTile=%d wholeTilesX=%d\n",
 	 maxPixelsPerTileX, wholeTilesX);
 
   /* dbe_InitGammaMap(); */
@@ -465,7 +465,7 @@
     }
 
   if (i==100000)
-    printk("sgivwfb: timeout waiting for frame DMA enable.\n");
+    printk(KERN_INFO "sgivwfb: timeout waiting for frame DMA enable.\n");
 
   outputVal = 0;
   htmp = currentTiming->hblank_end - 19;
@@ -688,7 +688,7 @@
   /* XXX FIXME - should try to pick best refresh rate */
   /* for now, pick closest dot-clock within 3MHz*/
   req_dot = (int)((1.0e3/1.0e6) / (1.0e-12 * (float)var->pixclock));
-  printk("sgivwfb: requested pixclock=%d ps (%d KHz)\n", var->pixclock,
+  printk(KERN_INFO "sgivwfb: requested pixclock=%d ps (%d KHz)\n", var->pixclock,
 	 req_dot);
   test_mode=min_mode;
   while (dbeVTimings[min_mode].width == dbeVTimings[test_mode].width) {
@@ -700,7 +700,7 @@
     test_mode--;
   min_mode = test_mode;
   timing = &dbeVTimings[min_mode];
-  printk("sgivwfb: granted dot-clock=%d KHz\n", timing->cfreq);
+  printk(KERN_INFO "sgivwfb: granted dot-clock=%d KHz\n", timing->cfreq);
 
   /* Adjust virtual resolution, if necessary */
   if (var->xres > var->xres_virtual || (!ywrap && !ypan))
@@ -775,9 +775,9 @@
 	oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
 	oldbpp != var->bits_per_pixel || !par_current.valid) {
       struct fb_fix_screeninfo fix;
-      printk("sgivwfb: new video mode xres=%d yres=%d bpp=%d\n",
+      printk(KERN_INFO "sgivwfb: new video mode xres=%d yres=%d bpp=%d\n",
 	     var->xres, var->yres, var->bits_per_pixel);
-      printk("         vxres=%d vyres=%d\n",
+      printk(KERN_INFO "         vxres=%d vyres=%d\n",
 	     var->xres_virtual, var->yres_virtual);
       activate_par(&par_current);
       sgivwfb_encode_fix(&fix, var);
@@ -915,37 +915,38 @@
   if (remap_page_range(vma->vm_start, offset, size, vma->vm_page_prot))
     return -EAGAIN;
   vma->vm_file = file;
-  printk("sgivwfb: mmap framebuffer P(%lx)->V(%lx)\n", offset, vma->vm_start);
+  printk(KERN_DEBUG "sgivwfb: mmap framebuffer P(%lx)->V(%lx)\n", offset, vma->vm_start);
   return 0;
 }
 
-void __init sgivwfb_setup(char *options, int *ints)
+int __init sgivwfb_setup(char *options)
 {
   char *this_opt;
 
   fb_info.fontname[0] = '\0';
 
   if (!options || !*options)
-    return;
+    return 0;
 
   for (this_opt = strtok(options, ","); this_opt;
        this_opt = strtok(NULL, ",")) {
     if (!strncmp(this_opt, "font:", 5))
       strcpy(fb_info.fontname, this_opt+5);
   }
+  return 0;
 }
 
 /*
  *  Initialisation
  */
-void __init sgivwfb_init(void)
+int __init sgivwfb_init(void)
 {
-  printk("sgivwfb: framebuffer at 0x%lx, size %ldk\n",
+  printk(KERN_INFO "sgivwfb: framebuffer at 0x%lx, size %ldk\n",
 	 sgivwfb_mem_phys, sgivwfb_mem_size/1024);
 
   regs = (asregs*)ioremap_nocache(DBE_REG_PHYS, DBE_REG_SIZE);
   if (!regs) {
-    printk("sgivwfb: couldn't ioremap registers\n");
+    printk(KERN_ERR "sgivwfb: couldn't ioremap registers\n");
     goto fail_ioremap_regs;
   }
 
@@ -965,7 +966,7 @@
 
   fbmem = ioremap_nocache((unsigned long)sgivwfb_mem_phys, sgivwfb_mem_size);
   if (!fbmem) {
-    printk("sgivwfb: couldn't ioremap fbmem\n");
+    printk(KERN_ERR "sgivwfb: couldn't ioremap fbmem\n");
     goto fail_ioremap_fbmem;
   }
 
@@ -973,21 +974,21 @@
   sgivwfb_set_var(&par_current.var, -1, &fb_info);
 
   if (register_framebuffer(&fb_info) < 0) {
-    printk("sgivwfb: couldn't register framebuffer\n");
+    printk(KERN_ERR "sgivwfb: couldn't register framebuffer\n");
     goto fail_register_framebuffer;
   }
 
-  printk("fb%d: Virtual frame buffer device, using %ldK of video memory\n",
+  printk(KERN_INFO "fb%d: Virtual frame buffer device, using %ldK of video memory\n",
 	 GET_FB_IDX(fb_info.node), sgivwfb_mem_size>>10);
 
-  return;
+  return 0;
 
  fail_register_framebuffer:
   iounmap((char*)fbmem);
  fail_ioremap_fbmem:
   iounmap(regs);
  fail_ioremap_regs:
-  return;
+  return -ENXIO;
 }
 
 static int sgivwfbcon_switch(int con, struct fb_info *info)
@@ -1022,8 +1023,7 @@
 #ifdef MODULE
 int init_module(void)
 {
-  sgivwfb_init();
-  return 0;
+  return sgivwfb_init();
 }
 
 void cleanup_module(void)
diff -u --recursive --new-file v2.3.13/linux/drivers/video/skeletonfb.c linux/drivers/video/skeletonfb.c
--- v2.3.13/linux/drivers/video/skeletonfb.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/skeletonfb.c	Thu Aug 12 10:22:33 1999
@@ -73,6 +73,8 @@
 static int currcon = 0;
 static int inverse = 0;
 
+int xxxfb_init(void);
+int xxxfb_setup(char*);
 
 /* ------------------- chipset specific functions -------------------------- */
 
@@ -297,7 +299,7 @@
      *  Initialization
      */
 
-void __init xxxfb_init(void)
+int __init xxxfb_init(void)
 {
     fb_info.gen.fbhw = &xxx_switch;
     fb_info.gen.fbhw->detect();
@@ -316,12 +318,13 @@
     fbgen_set_disp(-1, &fb_info.gen);
     fbgen_install_cmap(0, &fb_info.gen);
     if (register_framebuffer(&fb_info.gen.info) < 0)
-	return;
-    printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.gen.info.node),
+	return -EINVAL;
+    printk(KERN_INFO "fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.gen.info.node),
 	   fb_info.gen.info.modename);
 
     /* uncomment this if your driver cannot be unloaded */
     /* MOD_INC_USE_COUNT; */
+    return 0;
 }
 
 
@@ -345,7 +348,7 @@
      *  Setup
      */
 
-void __init xxxfb_setup(char *options, int *ints)
+int __init xxxfb_setup(char *options)
 {
     /* Parse user speficied options (`video=xxxfb:') */
 }
@@ -393,8 +396,7 @@
 #ifdef MODULE
 int init_module(void)
 {
-    xxxfb_init();
-    return 0;
+    return xxxfb_init();
 }
 
 void cleanup_module(void)
diff -u --recursive --new-file v2.3.13/linux/drivers/video/tgafb.c linux/drivers/video/tgafb.c
--- v2.3.13/linux/drivers/video/tgafb.c	Thu Jul  8 15:42:21 1999
+++ linux/drivers/video/tgafb.c	Wed Aug 18 10:10:06 1999
@@ -125,7 +125,10 @@
      *      fbcon should provide a general mechanism for doing something like this.
      */
 
-static struct fb_videomode tgafb_predefined[] __initdata = {
+static struct {
+    const char *name;
+    struct fb_var_screeninfo var;
+} tgafb_predefined[] __initdata = {
     { "640x480-60", {
 	640, 480, 640, 480, 0, 0, 0, 0,
 	{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
@@ -287,8 +290,8 @@
 
 static int tgafb_open(struct fb_info *info, int user);
 static int tgafb_release(struct fb_info *info, int user);
-void tgafb_setup(char *options, int *ints);
-void tgafb_init(void);
+int tgafb_setup(char*);
+int tgafb_init(void);
 void tgafb_cleanup(struct fb_info *info);
 
 static void tgafb_set_pll(int f);
@@ -325,9 +328,9 @@
 	fix->visual = FB_VISUAL_TRUECOLOR;
 
     fix->line_length = par->xres * (par->bits_per_pixel >> 3);
-    fix->smem_start = (char *)__pa(fb_info.tga_fb_base + dense_mem(fb_info.tga_fb_base));
+    fix->smem_start = ioremap(fb_info.tga_fb_base);
     fix->smem_len = fix->line_length * par->yres;
-    fix->mmio_start = (char *)__pa(fb_info.tga_regs_base);
+    fix->mmio_start = ioremap(fb_info.tga_regs_base);
     fix->mmio_len = 0x1000;		/* Is this sufficient? */
     fix->xpanstep = fix->ypanstep = fix->ywrapstep = 0;
     fix->accel = FB_ACCEL_DEC_TGA;
@@ -934,7 +937,7 @@
 static void tgafb_set_disp(const void *fb_par, struct display *disp,
 	struct fb_info_gen *info)
 {
-    disp->screen_base = (char *)fb_info.tga_fb_base + dense_mem(fb_info.tga_fb_base);
+    disp->screen_base = ioremap(fb_info.tga_fb_base);
     switch (fb_info.tga_type) {
 #ifdef FBCON_HAS_CFB8
 	case 0: /* 8-plane */
@@ -996,7 +999,7 @@
      *  Setup
      */
 
-__initfunc(void tgafb_setup(char *options, int *ints)) {
+int __init tgafb_setup(char *options) {
     char *this_opt;
     int i;
     
@@ -1016,6 +1019,7 @@
       		printk(KERN_ERR "tgafb: unknown parameter %s\n", this_opt);
     	    }
       	}
+    return 0;
 }
 
 
@@ -1023,16 +1027,16 @@
      *  Initialisation
      */
 
-__initfunc(void tgafb_init(void))
+__initfunc(int tgafb_init(void))
 {
     struct pci_dev *pdev;
 
     pdev = pci_find_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA, NULL);
     if (!pdev)
-	return;
-    fb_info.tga_mem_base = pdev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK;
+	return -ENXIO;
+    fb_info.tga_mem_base = pdev->resource[0].start;
 #ifdef DEBUG
-    printk("tgafb_init: mem_base 0x%x\n", fb_info.tga_mem_base);
+    printk(KERN_DEBUG "tgafb_init: mem_base 0x%x\n", fb_info.tga_mem_base);
 #endif /* DEBUG */
 
     fb_info.tga_type = (readl((unsigned long)fb_info.tga_mem_base) >> 12) & 0x0f;
@@ -1078,9 +1082,10 @@
     fbgen_set_disp(-1, &fb_info.gen);
     fbgen_install_cmap(0, &fb_info.gen);
     if (register_framebuffer(&fb_info.gen.info) < 0)
-	return;
-    printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.gen.info.node),
+	return -EINVAL;
+    printk(KERN_INFO "fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.gen.info.node),
 	fb_info.gen.info.modename);
+    return 0;
 }
 
 
@@ -1101,8 +1106,7 @@
 #ifdef MODULE
 int init_module(void)
 {
-    tgafb_init();
-    return 0;
+    return tgafb_init();
 }
 
 void cleanup_module(void)
diff -u --recursive --new-file v2.3.13/linux/drivers/video/valkyriefb.c linux/drivers/video/valkyriefb.c
--- v2.3.13/linux/drivers/video/valkyriefb.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/valkyriefb.c	Thu Aug 12 10:22:33 1999
@@ -113,9 +113,9 @@
 /*
  * Exported functions
  */
-void valkyriefb_init(void);
+int valkyriefb_init(void);
 void valkyrie_of_init(struct device_node *dp);
-void valkyriefb_setup(char *options, int *ints);
+int valkyriefb_setup(char*);
 
 static int valkyrie_open(struct fb_info *info, int user);
 static int valkyrie_release(struct fb_info *info, int user);
@@ -218,7 +218,7 @@
 	}
 	
 	if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) {
-		/* printk("Not activating, in valkyrie_set_var.\n"); */
+		/* printk(KERN_ERR "Not activating, in valkyrie_set_var.\n"); */
 		valkyrie_par_to_var(&par, var);
 		return 0;
 	}
@@ -478,7 +478,7 @@
 	int j, k;
 
 	p->sense = read_valkyrie_sense(p);
-	printk("Monitor sense value = 0x%x, ", p->sense);
+	printk(KERN_INFO "Monitor sense value = 0x%x, ", p->sense);
 
 	/* Try to pick a video mode out of NVRAM if we have one. */
 	if (default_vmode == VMODE_NVRAM) {
@@ -504,7 +504,7 @@
 	 || valkyrie_vram_reqd(default_vmode, default_cmode) > p->total_vram)
 		default_cmode = CMODE_8;
 	
-	printk("using video mode %d and color mode %d.\n", default_vmode, default_cmode);
+	printk(KERN_INFO "using video mode %d and color mode %d.\n", default_vmode, default_cmode);
 
 	mac_vmode_to_var(default_vmode, default_cmode, &var);
 	if (valkyrie_var_to_par(&var, par, &p->info)) {
@@ -534,7 +534,7 @@
 		return;
 	}
 	
-	printk("fb%d: valkyrie frame buffer device\n", GET_FB_IDX(p->info.node));	
+	printk(KERN_INFO "fb%d: valkyrie frame buffer device\n", GET_FB_IDX(p->info.node));	
 }
 
 static void valkyrie_set_par(const struct fb_par_valkyrie *par,
@@ -584,7 +584,7 @@
 #endif /* CONFIG_FB_COMPAT_XPMAC */
 }
 
-void __init valkyriefb_init(void)
+int __init valkyriefb_init(void)
 {
 #ifndef CONFIG_FB_OF
 	struct device_node *dp;
@@ -593,6 +593,7 @@
 	if (dp != 0)
 		valkyrie_of_init(dp);
 #endif /* CONFIG_FB_OF */
+	return 0;
 }
 
 void __init valkyrie_of_init(struct device_node *dp)
@@ -600,8 +601,10 @@
 	struct fb_info_valkyrie	*p;
 	unsigned long addr, size;
 	
-	if(dp->n_addrs != 1)
-		panic("expecting 1 address for valkyrie (got %d)", dp->n_addrs);
+	if(dp->n_addrs != 1) {
+		printk(KERN_ERR "expecting 1 address for valkyrie (got %d)", dp->n_addrs);
+		return;
+	}	
 
 	p = kmalloc(sizeof(*p), GFP_ATOMIC);
 	if (p == 0)
@@ -848,12 +851,12 @@
 /*
  * Parse user speficied options (`video=valkyriefb:')
  */
-void __init valkyriefb_setup(char *options, int *ints)
+int __init valkyriefb_setup(char *options)
 {
 	char *this_opt;
 
 	if (!options || !*options)
-		return;
+		return 0;
 
 	for (this_opt = strtok(options, ","); this_opt;
 	     this_opt = strtok(NULL, ",")) {
@@ -893,4 +896,5 @@
 			can_soft_blank = 1;
 		}
 	}
+	return 0;
 }
diff -u --recursive --new-file v2.3.13/linux/drivers/video/vesafb.c linux/drivers/video/vesafb.c
--- v2.3.13/linux/drivers/video/vesafb.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/vesafb.c	Thu Aug 12 10:22:33 1999
@@ -264,7 +264,7 @@
 	    var->bits_per_pixel != vesafb_defined.bits_per_pixel ||
 	    var->nonstd) {
 		if (first) {
-			printk("Vesafb does not support changing the video mode\n");
+			printk(KERN_ERR "Vesafb does not support changing the video mode\n");
 			first = 0;
 		}
 		return -EINVAL;
@@ -470,14 +470,14 @@
 	vesafb_ioctl
 };
 
-void vesafb_setup(char *options, int *ints)
+int vesafb_setup(char *options)
 {
 	char *this_opt;
 	
 	fb_info.fontname[0] = '\0';
 	
 	if (!options || !*options)
-		return;
+		return 0;
 	
 	for(this_opt=strtok(options,","); this_opt; this_opt=strtok(NULL,",")) {
 		if (!*this_opt) continue;
@@ -499,6 +499,7 @@
 		else if (!strncmp(this_opt, "font:", 5))
 			strcpy(fb_info.fontname, this_opt+5);
 	}
+	return 0;
 }
 
 static int vesafb_switch(int con, struct fb_info *info)
@@ -522,12 +523,12 @@
 	/* Not supported */
 }
 
-void __init vesafb_init(void)
+int __init vesafb_init(void)
 {
 	int i,j;
 
 	if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB)
-		return;
+		return -ENXIO;
 
 	video_base          = (char*)screen_info.lfb_base;
 	video_bpp           = screen_info.lfb_depth;
@@ -539,13 +540,13 @@
 		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
         video_vbase = ioremap((unsigned long)video_base, video_size);
 
-	printk("vesafb: framebuffer at 0x%p, mapped to 0x%p, size %dk\n",
+	printk(KERN_INFO "vesafb: framebuffer at 0x%p, mapped to 0x%p, size %dk\n",
 	       video_base, video_vbase, video_size/1024);
-	printk("vesafb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
+	printk(KERN_INFO "vesafb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
 	       video_width, video_height, video_bpp, video_linelength, screen_info.pages);
 
 	if (screen_info.vesapm_seg) {
-		printk("vesafb: protected mode interface info at %04x:%04x\n",
+		printk(KERN_INFO "vesafb: protected mode interface info at %04x:%04x\n",
 		       screen_info.vesapm_seg,screen_info.vesapm_off);
 	}
 
@@ -553,12 +554,12 @@
 		ypan = pmi_setpal = 0; /* not available or some DOS TSR ... */
 
 	if (ypan || pmi_setpal) {
-		pmi_base  = (unsigned short*)(__PAGE_OFFSET+((unsigned long)screen_info.vesapm_seg << 4) + screen_info.vesapm_off);
+		pmi_base  = (unsigned short*)bus_to_virt(((unsigned long)screen_info.vesapm_seg << 4) + screen_info.vesapm_off);
 		pmi_start = (void*)((char*)pmi_base + pmi_base[1]);
 		pmi_pal   = (void*)((char*)pmi_base + pmi_base[2]);
-		printk("vesafb: pmi: set display start = %p, set palette = %p\n",pmi_start,pmi_pal);
+		printk(KERN_INFO "vesafb: pmi: set display start = %p, set palette = %p\n",pmi_start,pmi_pal);
 		if (pmi_base[3]) {
-			printk("vesafb: pmi: ports = ");
+			printk(KERN_INFO "vesafb: pmi: ports = ");
 				for (i = pmi_base[3]/2; pmi_base[i] != 0xffff; i++)
 					printk("%x ",pmi_base[i]);
 			printk("\n");
@@ -569,7 +570,7 @@
 				 * Rules are: we have to set up a descriptor for the requested
 				 * memory area and pass it in the ES register to the BIOS function.
 				 */
-				printk("vesafb: can't handle memory requests, pmi disabled\n");
+				printk(KERN_INFO "vesafb: can't handle memory requests, pmi disabled\n");
 				ypan = pmi_setpal = 0;
 			}
 		}
@@ -582,10 +583,10 @@
 	vesafb_defined.bits_per_pixel=video_bpp;
 
 	if (ypan && vesafb_defined.yres_virtual > video_height) {
-		printk("vesafb: scrolling: %s using protected mode interface, yres_virtual=%d\n",
+		printk(KERN_INFO "vesafb: scrolling: %s using protected mode interface, yres_virtual=%d\n",
 		       (ypan > 1) ? "ywrap" : "ypan",vesafb_defined.yres_virtual);
 	} else {
-		printk("vesafb: scrolling: redraw\n");
+		printk(KERN_INFO "vesafb: scrolling: redraw\n");
 		vesafb_defined.yres_virtual = video_height;
 		ypan = 0;
 	}
@@ -609,7 +610,7 @@
 		vesafb_defined.blue.length   = screen_info.blue_size;
 		vesafb_defined.transp.offset = screen_info.rsvd_pos;
 		vesafb_defined.transp.length = screen_info.rsvd_size;
-		printk("vesafb: directcolor: "
+		printk(KERN_INFO "vesafb: directcolor: "
 		       "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
 		       screen_info.rsvd_size,
 		       screen_info.red_size,
@@ -648,10 +649,11 @@
 	vesafb_set_disp(-1);
 
 	if (register_framebuffer(&fb_info)<0)
-		return;
+		return -EINVAL;
 
-	printk("fb%d: %s frame buffer device\n",
+	printk(KERN_INFO "fb%d: %s frame buffer device\n",
 	       GET_FB_IDX(fb_info.node), fb_info.modename);
+	return 0;
 }
 
 /*
diff -u --recursive --new-file v2.3.13/linux/drivers/video/vfb.c linux/drivers/video/vfb.c
--- v2.3.13/linux/drivers/video/vfb.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/vfb.c	Thu Aug 12 10:22:33 1999
@@ -78,7 +78,7 @@
      *  Interface used by the world
      */
 
-void vfb_setup(char *options, int *ints);
+int vfb_setup(char*);
 
 static int vfb_open(struct fb_info *info, int user);
 static int vfb_release(struct fb_info *info, int user);
@@ -102,7 +102,7 @@
      *  Interface to the low level console driver
      */
 
-void vfb_init(void);
+int vfb_init(void);
 static int vfbcon_switch(int con, struct fb_info *info);
 static int vfbcon_updatevar(int con, struct fb_info *info);
 static void vfbcon_blank(int blank, struct fb_info *info);
@@ -406,7 +406,7 @@
 }
 
 
-void __init vfb_setup(char *options, int *ints)
+int __init vfb_setup(char *options)
 {
     char *this_opt;
 
@@ -415,13 +415,14 @@
     vfb_enable = 1;
 
     if (!options || !*options)
-	return;
+	return 0;
 
     for (this_opt = strtok(options, ","); this_opt;
 	 this_opt = strtok(NULL, ",")) {
 	if (!strncmp(this_opt, "font:", 5))
 	    strcpy(fb_info.fontname, this_opt+5);
     }
+    return 0;
 }
 
 
@@ -429,13 +430,13 @@
      *  Initialisation
      */
 
-void __init vfb_init(void)
+int __init vfb_init(void)
 {
     if (!vfb_enable)
-	return;
+	return -ENXIO;
 
     if (!(videomemory = (u_long)vmalloc(videomemorysize)))
-	return;
+	return -ENOMEM;
 
     strcpy(fb_info.modename, vfb_name);
     fb_info.changevar = NULL;
@@ -451,11 +452,12 @@
 
     if (register_framebuffer(&fb_info) < 0) {
 	vfree((void *)videomemory);
-	return;
+	return -EINVAL;
     }
 
-    printk("fb%d: Virtual frame buffer device, using %ldK of video memory\n",
+    printk(KERN_INFO "fb%d: Virtual frame buffer device, using %ldK of video memory\n",
 	   GET_FB_IDX(fb_info.node), videomemorysize>>10);
+    return 0;
 }
 
 
@@ -636,8 +638,7 @@
 #ifdef MODULE
 int init_module(void)
 {
-    vfb_init();
-    return 0;
+    return vfb_init();
 }
 
 void cleanup_module(void)
diff -u --recursive --new-file v2.3.13/linux/drivers/video/vga.h linux/drivers/video/vga.h
--- v2.3.13/linux/drivers/video/vga.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/vga.h	Wed Aug 18 10:10:06 1999
@@ -0,0 +1,443 @@
+/*
+ * linux/include/video/vga.h -- standard VGA chipset interaction
+ *
+ * Copyright 1999 Jeff Garzik <jgarzik@pobox.com>
+ * 
+ * Copyright history from vga16fb.c:
+ *	Copyright 1999 Ben Pfaff and Petr Vandrovec
+ *	Based on VGA info at http://www.goodnet.com/~tinara/FreeVGA/home.htm
+ *	Based on VESA framebuffer (c) 1998 Gerd Knorr
+ *
+ * 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.  
+ *
+ */
+
+#ifndef __linux_video_vga_h__
+#define __linux_video_vga_h__
+
+#include <linux/types.h>
+#include <asm/io.h>
+#ifndef CONFIG_AMIGA
+#include <asm/vga.h>
+#endif
+#include <asm/byteorder.h>
+
+
+/* Some of the code below is taken from SVGAlib.  The original,
+   unmodified copyright notice for that code is below. */
+/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen                    */
+/*                                                                 */
+/* This library is free software; you can redistribute it and/or   */
+/* modify it without any restrictions. This library is distributed */
+/* in the hope that it will be useful, but without any warranty.   */
+
+/* Multi-chipset support Copyright 1993 Harm Hanemaayer */
+/* partially copyrighted (C) 1993 by Hartmut Schirmer */
+
+/* VGA data register ports */
+#define VGA_CRT_DC  	0x3D5	/* CRT Controller Data Register - color emulation */
+#define VGA_CRT_DM  	0x3B5	/* CRT Controller Data Register - mono emulation */
+#define VGA_ATT_R   	0x3C1	/* Attribute Controller Data Read Register */
+#define VGA_ATT_W   	0x3C0	/* Attribute Controller Data Write Register */
+#define VGA_GFX_D   	0x3CF	/* Graphics Controller Data Register */
+#define VGA_SEQ_D   	0x3C5	/* Sequencer Data Register */
+#define VGA_MIS_R   	0x3CC	/* Misc Output Read Register */
+#define VGA_MIS_W   	0x3C2	/* Misc Output Write Register */
+#define VGA_FTC_R	0x3CA	/* Feature Control Read Register */
+#define VGA_IS1_RC  	0x3DA	/* Input Status Register 1 - color emulation */
+#define VGA_IS1_RM  	0x3BA	/* Input Status Register 1 - mono emulation */
+#define VGA_PEL_D   	0x3C9	/* PEL Data Register */
+#define VGA_PEL_MSK 	0x3C6	/* PEL mask register */
+
+/* EGA-specific registers */
+#define EGA_GFX_E0	0x3CC	/* Graphics enable processor 0 */
+#define EGA_GFX_E1	0x3CA	/* Graphics enable processor 1 */
+
+/* VGA index register ports */
+#define VGA_CRT_IC  	0x3D4	/* CRT Controller Index - color emulation */
+#define VGA_CRT_IM  	0x3B4	/* CRT Controller Index - mono emulation */
+#define VGA_ATT_IW  	0x3C0	/* Attribute Controller Index & Data Write Register */
+#define VGA_GFX_I   	0x3CE	/* Graphics Controller Index */
+#define VGA_SEQ_I   	0x3C4	/* Sequencer Index */
+#define VGA_PEL_IW  	0x3C8	/* PEL Write Index */
+#define VGA_PEL_IR  	0x3C7	/* PEL Read Index */
+
+/* standard VGA indexes max counts */
+#define VGA_CRT_C   	0x19	/* Number of CRT Controller Registers */
+#define VGA_ATT_C   	0x15	/* Number of Attribute Controller Registers */
+#define VGA_GFX_C   	0x09	/* Number of Graphics Controller Registers */
+#define VGA_SEQ_C   	0x05	/* Number of Sequencer Registers */
+#define VGA_MIS_C   	0x01	/* Number of Misc Output Register */
+
+/* VGA misc register bit masks */
+#define VGA_MIS_COLOR		0x01
+#define VGA_MIS_ENB_MEM_ACCESS	0x02
+#define VGA_MIS_DCLK_28322_720	0x04
+#define VGA_MIS_ENB_PLL_LOAD	(0x04 | 0x08)
+#define VGA_MIS_SEL_HIGH_PAGE	0x20
+
+/* VGA CRT controller register indices */
+#define VGA_CRTC_H_TOTAL	0
+#define VGA_CRTC_H_DISP		1
+#define VGA_CRTC_H_BLANK_START	2
+#define VGA_CRTC_H_BLANK_END	3
+#define VGA_CRTC_H_SYNC_START	4
+#define VGA_CRTC_H_SYNC_END	5
+#define VGA_CRTC_V_TOTAL	6
+#define VGA_CRTC_OVERFLOW	7
+#define VGA_CRTC_PRESET_ROW	8
+#define VGA_CRTC_MAX_SCAN	9
+#define VGA_CRTC_CURSOR_START	0x0A
+#define VGA_CRTC_CURSOR_END	0x0B
+#define VGA_CRTC_START_HI	0x0C
+#define VGA_CRTC_START_LO	0x0D
+#define VGA_CRTC_CURSOR_HI	0x0E
+#define VGA_CRTC_CURSOR_LO	0x0F
+#define VGA_CRTC_V_SYNC_START	0x10
+#define VGA_CRTC_V_SYNC_END	0x11
+#define VGA_CRTC_V_DISP_END	0x12
+#define VGA_CRTC_OFFSET		0x13
+#define VGA_CRTC_UNDERLINE	0x14
+#define VGA_CRTC_V_BLANK_START	0x15
+#define VGA_CRTC_V_BLANK_END	0x16
+#define VGA_CRTC_MODE		0x17
+#define VGA_CRTC_LINE_COMPARE	0x18
+#define VGA_CRTC_REGS		VGA_CRT_C
+
+/* VGA CRT controller bit masks */
+#define VGA_CR11_LOCK_CR0_CR7	0x80 /* lock writes to CR0 - CR7 */
+#define VGA_CR17_H_V_SIGNALS_ENABLED 0x80
+
+/* VGA attribute controller register indices */
+#define VGA_ATC_PALETTE0	0x00
+#define VGA_ATC_PALETTE1	0x01
+#define VGA_ATC_PALETTE2	0x02
+#define VGA_ATC_PALETTE3	0x03
+#define VGA_ATC_PALETTE4	0x04
+#define VGA_ATC_PALETTE5	0x05
+#define VGA_ATC_PALETTE6	0x06
+#define VGA_ATC_PALETTE7	0x07
+#define VGA_ATC_PALETTE8	0x08
+#define VGA_ATC_PALETTE9	0x09
+#define VGA_ATC_PALETTEA	0x0A
+#define VGA_ATC_PALETTEB	0x0B
+#define VGA_ATC_PALETTEC	0x0C
+#define VGA_ATC_PALETTED	0x0D
+#define VGA_ATC_PALETTEE	0x0E
+#define VGA_ATC_PALETTEF	0x0F
+#define VGA_ATC_MODE		0x10
+#define VGA_ATC_OVERSCAN	0x11
+#define VGA_ATC_PLANE_ENABLE	0x12
+#define VGA_ATC_PEL		0x13
+#define VGA_ATC_COLOR_PAGE	0x14
+
+#define VGA_AR_ENABLE_DISPLAY	0x20
+
+/* VGA sequencer register indices */
+#define VGA_SEQ_RESET		0x00
+#define VGA_SEQ_CLOCK_MODE	0x01
+#define VGA_SEQ_PLANE_WRITE	0x02
+#define VGA_SEQ_CHARACTER_MAP	0x03
+#define VGA_SEQ_MEMORY_MODE	0x04
+
+/* VGA sequencer register bit masks */
+#define VGA_SR01_CHAR_CLK_8DOTS	0x01 /* bit 0: character clocks 8 dots wide are generated */
+#define VGA_SR01_SCREEN_OFF	0x20 /* bit 5: Screen is off */
+#define VGA_SR02_ALL_PLANES	0x0F /* bits 3-0: enable access to all planes */
+#define VGA_SR04_EXT_MEM	0x02 /* bit 1: allows complete mem access to 256K */
+#define VGA_SR04_SEQ_MODE	0x04 /* bit 2: directs system to use a sequential addressing mode */
+#define VGA_SR04_CHN_4M		0x08 /* bit 3: selects modulo 4 addressing for CPU access to display memory */
+
+/* VGA graphics controller register indices */
+#define VGA_GFX_SR_VALUE	0x00
+#define VGA_GFX_SR_ENABLE	0x01
+#define VGA_GFX_COMPARE_VALUE	0x02
+#define VGA_GFX_DATA_ROTATE	0x03
+#define VGA_GFX_PLANE_READ	0x04
+#define VGA_GFX_MODE		0x05
+#define VGA_GFX_MISC		0x06
+#define VGA_GFX_COMPARE_MASK	0x07
+#define VGA_GFX_BIT_MASK	0x08
+
+/* VGA graphics controller bit masks */
+#define VGA_GR06_GRAPHICS_MODE	0x01
+
+/* macro for composing an 8-bit VGA register index and value
+ * into a single 16-bit quantity */
+#define VGA_OUT16VAL(v, r)       (((v) << 8) | (r))
+
+/* decide whether we should enable the faster 16-bit VGA register writes */
+#ifdef __LITTLE_ENDIAN
+#define VGA_OUTW_WRITE
+#endif
+
+
+/*
+ * generic VGA port read/write
+ */
+ 
+extern inline unsigned char vga_io_r (unsigned short port)
+{
+	return inb (port);
+}
+
+extern inline void vga_io_w (unsigned short port, unsigned char val)
+{
+	outb (val, port);
+}
+
+extern inline void vga_io_w_fast (unsigned short port, unsigned char reg,
+				  unsigned char val)
+{
+	outw (VGA_OUT16VAL (val, reg), port);
+}
+
+extern inline unsigned char vga_mm_r (caddr_t regbase, unsigned short port)
+{
+	return readb (regbase + port);
+}
+
+extern inline void vga_mm_w (caddr_t regbase, unsigned short port, unsigned char val)
+{
+	writeb (val, regbase + port);
+}
+
+extern inline void vga_mm_w_fast (caddr_t regbase, unsigned short port,
+				  unsigned char reg, unsigned char val)
+{
+	writew (VGA_OUT16VAL (val, reg), regbase + port);
+}
+
+extern inline unsigned char vga_r (caddr_t regbase, unsigned short port)
+{
+	if (regbase)
+		return vga_mm_r (regbase, port);
+	else
+		return vga_io_r (port);
+}
+
+extern inline void vga_w (caddr_t regbase, unsigned short port, unsigned char val)
+{
+	if (regbase)
+		vga_mm_w (regbase, port, val);
+	else
+		vga_io_w (port, val);
+}
+
+
+extern inline void vga_w_fast (caddr_t regbase, unsigned short port,
+			       unsigned char reg, unsigned char val)
+{
+	if (regbase)
+		vga_mm_w_fast (regbase, port, reg, val);
+	else
+		vga_io_w_fast (port, reg, val);
+}
+
+
+/*
+ * VGA CRTC register read/write
+ */
+ 
+extern inline unsigned char vga_rcrt (caddr_t regbase, unsigned char reg)
+{
+        vga_w (regbase, VGA_CRT_IC, reg);
+        return vga_r (regbase, VGA_CRT_DC);
+}
+
+extern inline void vga_wcrt (caddr_t regbase, unsigned char reg, unsigned char val)
+{
+#ifdef VGA_OUTW_WRITE
+	vga_w_fast (regbase, VGA_CRT_IC, reg, val);
+#else
+        vga_w (regbase, VGA_CRT_IC, reg);
+        vga_w (regbase, VGA_CRT_DC, val);
+#endif /* VGA_OUTW_WRITE */
+}
+
+extern inline unsigned char vga_io_rcrt (unsigned char reg)
+{
+        vga_io_w (VGA_CRT_IC, reg);
+        return vga_io_r (VGA_CRT_DC);
+}
+
+extern inline void vga_io_wcrt (unsigned char reg, unsigned char val)
+{
+#ifdef VGA_OUTW_WRITE
+	vga_io_w_fast (VGA_CRT_IC, reg, val);
+#else
+        vga_io_w (VGA_CRT_IC, reg);
+        vga_io_w (VGA_CRT_DC, val);
+#endif /* VGA_OUTW_WRITE */
+}
+
+extern inline unsigned char vga_mm_rcrt (caddr_t regbase, unsigned char reg)
+{
+        vga_mm_w (regbase, VGA_CRT_IC, reg);
+        return vga_mm_r (regbase, VGA_CRT_DC);
+}
+
+extern inline void vga_mm_wcrt (caddr_t regbase, unsigned char reg, unsigned char val)
+{
+#ifdef VGA_OUTW_WRITE
+	vga_mm_w_fast (regbase, VGA_CRT_IC, reg, val);
+#else
+        vga_mm_w (regbase, VGA_CRT_IC, reg);
+        vga_mm_w (regbase, VGA_CRT_DC, val);
+#endif /* VGA_OUTW_WRITE */
+}
+
+
+/*
+ * VGA sequencer register read/write
+ */
+ 
+extern inline unsigned char vga_rseq (caddr_t regbase, unsigned char reg)
+{
+        vga_w (regbase, VGA_SEQ_I, reg);
+        return vga_r (regbase, VGA_SEQ_D);
+}
+
+extern inline void vga_wseq (caddr_t regbase, unsigned char reg, unsigned char val)
+{
+#ifdef VGA_OUTW_WRITE
+	vga_w_fast (regbase, VGA_SEQ_I, reg, val);
+#else
+        vga_w (regbase, VGA_SEQ_I, reg);
+        vga_w (regbase, VGA_SEQ_D, val);
+#endif /* VGA_OUTW_WRITE */
+}
+
+extern inline unsigned char vga_io_rseq (unsigned char reg)
+{
+        vga_io_w (VGA_SEQ_I, reg);
+        return vga_io_r (VGA_SEQ_D);
+}
+
+extern inline void vga_io_wseq (unsigned char reg, unsigned char val)
+{
+#ifdef VGA_OUTW_WRITE
+	vga_io_w_fast (VGA_SEQ_I, reg, val);
+#else
+        vga_io_w (VGA_SEQ_I, reg);
+        vga_io_w (VGA_SEQ_D, val);
+#endif /* VGA_OUTW_WRITE */
+}
+
+extern inline unsigned char vga_mm_rseq (caddr_t regbase, unsigned char reg)
+{
+        vga_mm_w (regbase, VGA_SEQ_I, reg);
+        return vga_mm_r (regbase, VGA_SEQ_D);
+}
+
+extern inline void vga_mm_wseq (caddr_t regbase, unsigned char reg, unsigned char val)
+{
+#ifdef VGA_OUTW_WRITE
+	vga_mm_w_fast (regbase, VGA_SEQ_I, reg, val);
+#else
+        vga_mm_w (regbase, VGA_SEQ_I, reg);
+        vga_mm_w (regbase, VGA_SEQ_D, val);
+#endif /* VGA_OUTW_WRITE */
+}
+
+
+
+/*
+ * VGA graphics controller register read/write
+ */
+ 
+extern inline unsigned char vga_rgfx (caddr_t regbase, unsigned char reg)
+{
+        vga_w (regbase, VGA_GFX_I, reg);
+        return vga_r (regbase, VGA_GFX_D);
+}
+
+extern inline void vga_wgfx (caddr_t regbase, unsigned char reg, unsigned char val)
+{
+#ifdef VGA_OUTW_WRITE
+	vga_w_fast (regbase, VGA_GFX_I, reg, val);
+#else
+        vga_w (regbase, VGA_GFX_I, reg);
+        vga_w (regbase, VGA_GFX_D, val);
+#endif /* VGA_OUTW_WRITE */
+}
+
+extern inline unsigned char vga_io_rgfx (unsigned char reg)
+{
+        vga_io_w (VGA_GFX_I, reg);
+        return vga_io_r (VGA_GFX_D);
+}
+
+extern inline void vga_io_wgfx (unsigned char reg, unsigned char val)
+{
+#ifdef VGA_OUTW_WRITE
+	vga_io_w_fast (VGA_GFX_I, reg, val);
+#else
+        vga_io_w (VGA_GFX_I, reg);
+        vga_io_w (VGA_GFX_D, val);
+#endif /* VGA_OUTW_WRITE */
+}
+
+extern inline unsigned char vga_mm_rgfx (caddr_t regbase, unsigned char reg)
+{
+        vga_mm_w (regbase, VGA_GFX_I, reg);
+        return vga_mm_r (regbase, VGA_GFX_D);
+}
+
+extern inline void vga_mm_wgfx (caddr_t regbase, unsigned char reg, unsigned char val)
+{
+#ifdef VGA_OUTW_WRITE
+	vga_mm_w_fast (regbase, VGA_GFX_I, reg, val);
+#else
+        vga_mm_w (regbase, VGA_GFX_I, reg);
+        vga_mm_w (regbase, VGA_GFX_D, val);
+#endif /* VGA_OUTW_WRITE */
+}
+
+
+/*
+ * VGA attribute controller register read/write
+ */
+ 
+extern inline unsigned char vga_rattr (caddr_t regbase, unsigned char reg)
+{
+        vga_w (regbase, VGA_ATT_IW, reg);
+        return vga_r (regbase, VGA_ATT_R);
+}
+
+extern inline void vga_wattr (caddr_t regbase, unsigned char reg, unsigned char val)
+{
+        vga_w (regbase, VGA_ATT_IW, reg);
+        vga_w (regbase, VGA_ATT_W, val);
+}
+
+extern inline unsigned char vga_io_rattr (unsigned char reg)
+{
+        vga_io_w (VGA_ATT_IW, reg);
+        return vga_io_r (VGA_ATT_R);
+}
+
+extern inline void vga_io_wattr (unsigned char reg, unsigned char val)
+{
+        vga_io_w (VGA_ATT_IW, reg);
+        vga_io_w (VGA_ATT_W, val);
+}
+
+extern inline unsigned char vga_mm_rattr (caddr_t regbase, unsigned char reg)
+{
+        vga_mm_w (regbase, VGA_ATT_IW, reg);
+        return vga_mm_r (regbase, VGA_ATT_R);
+}
+
+extern inline void vga_mm_wattr (caddr_t regbase, unsigned char reg, unsigned char val)
+{
+        vga_mm_w (regbase, VGA_ATT_IW, reg);
+        vga_mm_w (regbase, VGA_ATT_W, val);
+}
+
+
+
+
+#endif /* __linux_video_vga_h__ */
diff -u --recursive --new-file v2.3.13/linux/drivers/video/vga16fb.c linux/drivers/video/vga16fb.c
--- v2.3.13/linux/drivers/video/vga16fb.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/vga16fb.c	Wed Aug 18 10:10:06 1999
@@ -27,6 +27,7 @@
 
 #include <video/fbcon.h>
 #include <video/fbcon-vga-planes.h>
+#include "vga.h"
 
 #define dac_reg	(0x3c8)
 #define dac_val	(0x3c9)
@@ -63,104 +64,12 @@
 	int vesa_blanked;
 } vga16fb;
 
-/* Some of the code below is taken from SVGAlib.  The original,
-   unmodified copyright notice for that code is below. */
-/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen                    */
-/*                                                                 */
-/* This library is free software; you can redistribute it and/or   */
-/* modify it without any restrictions. This library is distributed */
-/* in the hope that it will be useful, but without any warranty.   */
-
-/* Multi-chipset support Copyright 1993 Harm Hanemaayer */
-/* partially copyrighted (C) 1993 by Hartmut Schirmer */
-
-/* VGA data register ports */
-#define CRT_DC  0x3D5		/* CRT Controller Data Register - color emulation */
-#define CRT_DM  0x3B5		/* CRT Controller Data Register - mono emulation */
-#define ATT_R   0x3C1		/* Attribute Controller Data Read Register */
-#define GRA_D   0x3CF		/* Graphics Controller Data Register */
-#define SEQ_D   0x3C5		/* Sequencer Data Register */
-#define MIS_R   0x3CC		/* Misc Output Read Register */
-#define MIS_W   0x3C2		/* Misc Output Write Register */
-#define IS1_RC  0x3DA		/* Input Status Register 1 - color emulation */
-#define IS1_RM  0x3BA		/* Input Status Register 1 - mono emulation */
-#define PEL_D   0x3C9		/* PEL Data Register */
-#define PEL_MSK 0x3C6		/* PEL mask register */
-
-/* EGA-specific registers */
-#define GRA_E0	0x3CC		/* Graphics enable processor 0 */
-#define GRA_E1	0x3CA		/* Graphics enable processor 1 */
-
-
-/* VGA index register ports */
-#define CRT_IC  0x3D4		/* CRT Controller Index - color emulation */
-#define CRT_IM  0x3B4		/* CRT Controller Index - mono emulation */
-#define ATT_IW  0x3C0		/* Attribute Controller Index & Data Write Register */
-#define GRA_I   0x3CE		/* Graphics Controller Index */
-#define SEQ_I   0x3C4		/* Sequencer Index */
-#define PEL_IW  0x3C8		/* PEL Write Index */
-#define PEL_IR  0x3C7		/* PEL Read Index */
-
-/* standard VGA indexes max counts */
-#define CRT_C   24		/* 24 CRT Controller Registers */
-#define ATT_C   21		/* 21 Attribute Controller Registers */
-#define GRA_C   9		/* 9  Graphics Controller Registers */
-#define SEQ_C   5		/* 5  Sequencer Registers */
-#define MIS_C   1		/* 1  Misc Output Register */
-
-#define CRTC_H_TOTAL		0
-#define CRTC_H_DISP		1
-#define CRTC_H_BLANK_START	2
-#define CRTC_H_BLANK_END	3
-#define CRTC_H_SYNC_START	4
-#define CRTC_H_SYNC_END		5
-#define CRTC_V_TOTAL		6
-#define CRTC_OVERFLOW		7
-#define CRTC_PRESET_ROW		8
-#define CRTC_MAX_SCAN		9
-#define CRTC_CURSOR_START	0x0A
-#define CRTC_CURSOR_END		0x0B
-#define CRTC_START_HI		0x0C
-#define CRTC_START_LO		0x0D
-#define CRTC_CURSOR_HI		0x0E
-#define CRTC_CURSOR_LO		0x0F
-#define CRTC_V_SYNC_START	0x10
-#define CRTC_V_SYNC_END		0x11
-#define CRTC_V_DISP_END		0x12
-#define CRTC_OFFSET		0x13
-#define CRTC_UNDERLINE		0x14
-#define CRTC_V_BLANK_START	0x15
-#define CRTC_V_BLANK_END	0x16
-#define CRTC_MODE		0x17
-#define CRTC_LINE_COMPARE	0x18
-#define CRTC_REGS		0x19
-
-#define ATC_MODE		0x10
-#define ATC_OVERSCAN		0x11
-#define ATC_PLANE_ENABLE	0x12
-#define ATC_PEL			0x13
-#define ATC_COLOR_PAGE		0x14
-
-#define SEQ_CLOCK_MODE		0x01
-#define SEQ_PLANE_WRITE		0x02
-#define SEQ_CHARACTER_MAP	0x03
-#define SEQ_MEMORY_MODE		0x04
-
-#define GDC_SR_VALUE		0x00
-#define GDC_SR_ENABLE		0x01
-#define GDC_COMPARE_VALUE	0x02
-#define GDC_DATA_ROTATE		0x03
-#define GDC_PLANE_READ		0x04
-#define GDC_MODE		0x05
-#define GDC_MISC		0x06
-#define GDC_COMPARE_MASK	0x07
-#define GDC_BIT_MASK		0x08
 
 struct vga16fb_par {
-	u8 crtc[CRTC_REGS];
-	u8 atc[ATT_C];
-	u8 gdc[GRA_C];
-	u8 seq[SEQ_C];
+	u8 crtc[VGA_CRT_C];
+	u8 atc[VGA_ATT_C];
+	u8 gdc[VGA_GFX_C];
+	u8 seq[VGA_SEQ_C];
 	u8 misc;
 	u8 vss;
 	struct fb_var_screeninfo var;
@@ -216,17 +125,17 @@
 static void vga16fb_pan_var(struct fb_info *info, struct fb_var_screeninfo *var)
 {
 	u32 pos = (var->xres_virtual * var->yoffset + var->xoffset) >> 3;
-	outb(CRTC_START_HI, CRT_IC);
-	outb(pos >> 8, CRT_DC);
-	outb(CRTC_START_LO, CRT_IC);
-	outb(pos & 0xFF, CRT_DC);
+	outb(VGA_CRTC_START_HI, VGA_CRT_IC);
+	outb(pos >> 8, VGA_CRT_DC);
+	outb(VGA_CRTC_START_LO, VGA_CRT_IC);
+	outb(pos & 0xFF, VGA_CRT_DC);
 #if 0
 	/* if someone supports xoffset in bit resolution */
-	inb(IS1_RC);		/* reset flip-flop */
-	outb(ATC_PEL, ATT_IW);
-	outb(xoffset & 7, ATT_IW);
-	inb(IS1_RC);
-	outb(0x20, ATT_IW);
+	inb(VGA_IS1_RC);		/* reset flip-flop */
+	outb(VGA_ATC_PEL, VGA_ATT_IW);
+	outb(xoffset & 7, VGA_ATT_IW);
+	inb(VGA_IS1_RC);
+	outb(0x20, VGA_ATT_IW);
 #endif
 }
 
@@ -338,7 +247,7 @@
 		}
 	}
 	par->misc |= best->misc;
-	par->seq[SEQ_CLOCK_MODE] |= best->seq_clock_mode;
+	par->seq[VGA_SEQ_CLOCK_MODE] |= best->seq_clock_mode;
 	par->var.pixclock = best->pixclock;		
 }
 			       
@@ -388,17 +297,17 @@
 		FAIL("hslen too big");
 	if (right + hslen + left > 64)
 		FAIL("hblank too big");
-	par->crtc[CRTC_H_TOTAL] = xtotal - 5;
-	par->crtc[CRTC_H_BLANK_START] = xres - 1;
-	par->crtc[CRTC_H_DISP] = xres - 1;
+	par->crtc[VGA_CRTC_H_TOTAL] = xtotal - 5;
+	par->crtc[VGA_CRTC_H_BLANK_START] = xres - 1;
+	par->crtc[VGA_CRTC_H_DISP] = xres - 1;
 	pos = xres + right;
-	par->crtc[CRTC_H_SYNC_START] = pos;
+	par->crtc[VGA_CRTC_H_SYNC_START] = pos;
 	pos += hslen;
-	par->crtc[CRTC_H_SYNC_END] = pos & 0x1F;
+	par->crtc[VGA_CRTC_H_SYNC_END] = pos & 0x1F;
 	pos += left - 2; /* blank_end + 2 <= total + 5 */
-	par->crtc[CRTC_H_BLANK_END] = (pos & 0x1F) | 0x80;
+	par->crtc[VGA_CRTC_H_BLANK_END] = (pos & 0x1F) | 0x80;
 	if (pos & 0x20)
-		par->crtc[CRTC_H_SYNC_END] |= 0x80;
+		par->crtc[VGA_CRTC_H_SYNC_END] |= 0x80;
 
 	yres = var->yres;
 	lower = var->lower_margin;
@@ -443,59 +352,59 @@
 		FAIL("ytotal too big");
 	if (vslen > 16)
 		FAIL("vslen too big");
-	par->crtc[CRTC_V_TOTAL] = ytotal - 2;
+	par->crtc[VGA_CRTC_V_TOTAL] = ytotal - 2;
 	r7 = 0x10;	/* disable linecompare */
 	if (ytotal & 0x100) r7 |= 0x01;
 	if (ytotal & 0x200) r7 |= 0x20;
-	par->crtc[CRTC_PRESET_ROW] = 0;
-	par->crtc[CRTC_MAX_SCAN] = 0x40;	/* 1 scanline, no linecmp */
+	par->crtc[VGA_CRTC_PRESET_ROW] = 0;
+	par->crtc[VGA_CRTC_MAX_SCAN] = 0x40;	/* 1 scanline, no linecmp */
 	par->var.vmode = var->vmode;
 	if (var->vmode & FB_VMODE_DOUBLE)
-		par->crtc[CRTC_MAX_SCAN] |= 0x80;
-	par->crtc[CRTC_CURSOR_START] = 0x20;
-	par->crtc[CRTC_CURSOR_END]   = 0x00;
+		par->crtc[VGA_CRTC_MAX_SCAN] |= 0x80;
+	par->crtc[VGA_CRTC_CURSOR_START] = 0x20;
+	par->crtc[VGA_CRTC_CURSOR_END]   = 0x00;
 	pos = yoffset * vxres + (xoffset >> 3);
-	par->crtc[CRTC_START_HI]     = pos >> 8;
-	par->crtc[CRTC_START_LO]     = pos & 0xFF;
-	par->crtc[CRTC_CURSOR_HI]    = 0x00;
-	par->crtc[CRTC_CURSOR_LO]    = 0x00;
+	par->crtc[VGA_CRTC_START_HI]     = pos >> 8;
+	par->crtc[VGA_CRTC_START_LO]     = pos & 0xFF;
+	par->crtc[VGA_CRTC_CURSOR_HI]    = 0x00;
+	par->crtc[VGA_CRTC_CURSOR_LO]    = 0x00;
 	pos = yres - 1;
-	par->crtc[CRTC_V_DISP_END] = pos & 0xFF;
-	par->crtc[CRTC_V_BLANK_START] = pos & 0xFF;
+	par->crtc[VGA_CRTC_V_DISP_END] = pos & 0xFF;
+	par->crtc[VGA_CRTC_V_BLANK_START] = pos & 0xFF;
 	if (pos & 0x100)
 		r7 |= 0x0A;	/* 0x02 -> DISP_END, 0x08 -> BLANK_START */
 	if (pos & 0x200) {
 		r7 |= 0x40;	/* 0x40 -> DISP_END */
-		par->crtc[CRTC_MAX_SCAN] |= 0x20; /* BLANK_START */
+		par->crtc[VGA_CRTC_MAX_SCAN] |= 0x20; /* BLANK_START */
 	}
 	pos += lower;
-	par->crtc[CRTC_V_SYNC_START] = pos & 0xFF;
+	par->crtc[VGA_CRTC_V_SYNC_START] = pos & 0xFF;
 	if (pos & 0x100)
 		r7 |= 0x04;
 	if (pos & 0x200)
 		r7 |= 0x80;
 	pos += vslen;
-	par->crtc[CRTC_V_SYNC_END] = (pos & 0x0F) | 0x10; /* disabled IRQ */
+	par->crtc[VGA_CRTC_V_SYNC_END] = (pos & 0x0F) | 0x10; /* disabled IRQ */
 	pos += upper - 1; /* blank_end + 1 <= ytotal + 2 */
-	par->crtc[CRTC_V_BLANK_END] = pos & 0xFF; /* 0x7F for original VGA,
+	par->crtc[VGA_CRTC_V_BLANK_END] = pos & 0xFF; /* 0x7F for original VGA,
                      but some SVGA chips requires all 8 bits to set */
 	if (vxres >= 512)
 		FAIL("vxres too long");
-	par->crtc[CRTC_OFFSET] = vxres >> 1;
-	par->crtc[CRTC_UNDERLINE] = 0x1F;
-	par->crtc[CRTC_MODE] = rMode | 0xE3;
-	par->crtc[CRTC_LINE_COMPARE] = 0xFF;
-	par->crtc[CRTC_OVERFLOW] = r7;
+	par->crtc[VGA_CRTC_OFFSET] = vxres >> 1;
+	par->crtc[VGA_CRTC_UNDERLINE] = 0x1F;
+	par->crtc[VGA_CRTC_MODE] = rMode | 0xE3;
+	par->crtc[VGA_CRTC_LINE_COMPARE] = 0xFF;
+	par->crtc[VGA_CRTC_OVERFLOW] = r7;
 
 	par->vss = 0x00;	/* 3DA */
 
 	for (i = 0x00; i < 0x10; i++)
 		par->atc[i] = i;
-	par->atc[ATC_MODE] = 0x81;
-	par->atc[ATC_OVERSCAN] = 0x00;	/* 0 for EGA, 0xFF for VGA */
-	par->atc[ATC_PLANE_ENABLE] = 0x0F;
-	par->atc[ATC_PEL] = xoffset & 7;
-	par->atc[ATC_COLOR_PAGE] = 0x00;
+	par->atc[VGA_ATC_MODE] = 0x81;
+	par->atc[VGA_ATC_OVERSCAN] = 0x00;	/* 0 for EGA, 0xFF for VGA */
+	par->atc[VGA_ATC_PLANE_ENABLE] = 0x0F;
+	par->atc[VGA_ATC_PEL] = xoffset & 7;
+	par->atc[VGA_ATC_COLOR_PAGE] = 0x00;
 	
 	par->misc = 0xC3;	/* enable CPU, ports 0x3Dx, positive sync */
 	par->var.sync = var->sync;
@@ -504,20 +413,20 @@
 	if (var->sync & FB_SYNC_VERT_HIGH_ACT)
 		par->misc &= ~0x80;
 	
-	par->seq[SEQ_CLOCK_MODE] = 0x01;
-	par->seq[SEQ_PLANE_WRITE] = 0x0F;
-	par->seq[SEQ_CHARACTER_MAP] = 0x00;
-	par->seq[SEQ_MEMORY_MODE] = 0x06;
-	
-	par->gdc[GDC_SR_VALUE] = 0x00;
-	par->gdc[GDC_SR_ENABLE] = 0x0F;
-	par->gdc[GDC_COMPARE_VALUE] = 0x00;
-	par->gdc[GDC_DATA_ROTATE] = 0x20;
-	par->gdc[GDC_PLANE_READ] = 0;
-	par->gdc[GDC_MODE] = 0x00;
-	par->gdc[GDC_MISC] = 0x05;
-	par->gdc[GDC_COMPARE_MASK] = 0x0F;
-	par->gdc[GDC_BIT_MASK] = 0xFF;
+	par->seq[VGA_SEQ_CLOCK_MODE] = 0x01;
+	par->seq[VGA_SEQ_PLANE_WRITE] = 0x0F;
+	par->seq[VGA_SEQ_CHARACTER_MAP] = 0x00;
+	par->seq[VGA_SEQ_MEMORY_MODE] = 0x06;
+	
+	par->gdc[VGA_GFX_SR_VALUE] = 0x00;
+	par->gdc[VGA_GFX_SR_ENABLE] = 0x0F;
+	par->gdc[VGA_GFX_COMPARE_VALUE] = 0x00;
+	par->gdc[VGA_GFX_DATA_ROTATE] = 0x20;
+	par->gdc[VGA_GFX_PLANE_READ] = 0;
+	par->gdc[VGA_GFX_MODE] = 0x00;
+	par->gdc[VGA_GFX_MISC] = 0x05;
+	par->gdc[VGA_GFX_COMPARE_MASK] = 0x0F;
+	par->gdc[VGA_GFX_BIT_MASK] = 0xFF;
 
 	vga16fb_clock_chip(par, var->pixclock, info);
 
@@ -543,64 +452,64 @@
 {
 	int i;
 
-	outb(inb(MIS_R) | 0x01, MIS_W);
+	outb(inb(VGA_MIS_R) | 0x01, VGA_MIS_W);
 
 	/* Enable graphics register modification */
 	if (!info->isVGA) {
-		outb(0x00, GRA_E0);
-		outb(0x01, GRA_E1);
+		outb(0x00, EGA_GFX_E0);
+		outb(0x01, EGA_GFX_E1);
 	}
 	
 	/* update misc output register */
-	outb(par->misc, MIS_W);
+	outb(par->misc, VGA_MIS_W);
 	
 	/* synchronous reset on */
-	outb(0x00, SEQ_I);
-	outb(0x01, SEQ_D);
+	outb(0x00, VGA_SEQ_I);
+	outb(0x01, VGA_SEQ_D);
 	
 	/* write sequencer registers */
-	outb(1, SEQ_I);
-	outb(par->seq[1] | 0x20, SEQ_D);
-	for (i = 2; i < SEQ_C; i++) {
-		outb(i, SEQ_I);
-		outb(par->seq[i], SEQ_D);
+	outb(1, VGA_SEQ_I);
+	outb(par->seq[1] | 0x20, VGA_SEQ_D);
+	for (i = 2; i < VGA_SEQ_C; i++) {
+		outb(i, VGA_SEQ_I);
+		outb(par->seq[i], VGA_SEQ_D);
 	}
 	
 	/* synchronous reset off */
-	outb(0x00, SEQ_I);
-	outb(0x03, SEQ_D);
+	outb(0x00, VGA_SEQ_I);
+	outb(0x03, VGA_SEQ_D);
 	
 	/* deprotect CRT registers 0-7 */
-	outb(0x11, CRT_IC);
-	outb(par->crtc[0x11], CRT_DC);
+	outb(0x11, VGA_CRT_IC);
+	outb(par->crtc[0x11], VGA_CRT_DC);
 
 	/* write CRT registers */
-	for (i = 0; i < CRTC_REGS; i++) {
-		outb(i, CRT_IC);
-		outb(par->crtc[i], CRT_DC);
+	for (i = 0; i < VGA_CRT_C; i++) {
+		outb(i, VGA_CRT_IC);
+		outb(par->crtc[i], VGA_CRT_DC);
 	}
 	
 	/* write graphics controller registers */
-	for (i = 0; i < GRA_C; i++) {
-		outb(i, GRA_I);
-		outb(par->gdc[i], GRA_D);
+	for (i = 0; i < VGA_GFX_C; i++) {
+		outb(i, VGA_GFX_I);
+		outb(par->gdc[i], VGA_GFX_D);
 	}
 	
 	/* write attribute controller registers */
-	for (i = 0; i < ATT_C; i++) {
-		inb_p(IS1_RC);		/* reset flip-flop */
-		outb_p(i, ATT_IW);
-		outb_p(par->atc[i], ATT_IW);
+	for (i = 0; i < VGA_ATT_C; i++) {
+		inb_p(VGA_IS1_RC);		/* reset flip-flop */
+		outb_p(i, VGA_ATT_IW);
+		outb_p(par->atc[i], VGA_ATT_IW);
 	}
 
 	/* Wait for screen to stabilize. */
 	mdelay(50);
 
-	outb(0x01, SEQ_I);
-	outb(par->seq[1], SEQ_D);
+	outb(0x01, VGA_SEQ_I);
+	outb(par->seq[1], VGA_SEQ_D);
 
-	inb(IS1_RC);
-	outb(0x20, ATT_IW);
+	inb(VGA_IS1_RC);
+	outb(0x20, VGA_ATT_IW);
 	
 	return 0;
 }
@@ -799,14 +708,14 @@
 	vga16fb_ioctl
 };
 
-void vga16fb_setup(char *options, int *ints)
+int vga16fb_setup(char *options)
 {
 	char *this_opt;
 	
 	vga16fb.fb_info.fontname[0] = '\0';
 	
 	if (!options || !*options)
-		return;
+		return 0;
 	
 	for(this_opt=strtok(options,","); this_opt; this_opt=strtok(NULL,",")) {
 		if (!*this_opt) continue;
@@ -814,6 +723,7 @@
 		if (!strncmp(this_opt, "font:", 5))
 			strcpy(vga16fb.fb_info.fontname, this_opt+5);
 	}
+	return 0;
 }
 
 static int vga16fb_switch(int con, struct fb_info *fb)
@@ -1003,14 +913,14 @@
 	}
 }
 
-void __init vga16_init(void)
+int __init vga16_init(void)
 {
 	int i,j;
 
-	printk("vga16fb: initializing\n");
+	printk(KERN_DEBUG "vga16fb: initializing\n");
 
         vga16fb.video_vbase = ioremap((unsigned long)0xa0000, 65536);
-	printk("vga16fb: mapped to 0x%p\n", vga16fb.video_vbase);
+	printk(KERN_INFO "vga16fb: mapped to 0x%p\n", vga16fb.video_vbase);
 
 	vga16fb.isVGA = ORIG_VIDEO_ISVGA;
 	vga16fb.palette_blanked = 0;
@@ -1049,21 +959,21 @@
 	if (register_framebuffer(&vga16fb.fb_info)<0)
 		return -EINVAL;
 
-	printk("fb%d: %s frame buffer device\n",
+	printk(KERN_INFO "fb%d: %s frame buffer device\n",
 	       GET_FB_IDX(vga16fb.fb_info.node), vga16fb.fb_info.modename);
 
 	return 0;
 }
 
 #ifndef MODULE
-__initfunc(void vga16fb_init(void))
+int __init vga16fb_init(void)
 {
-    vga16_init();
+    return vga16_init();
 }
 
 #else /* MODULE */
 
-__initfunc(int init_module(void))
+int init_module(void)
 {
     return vga16_init();
 }
diff -u --recursive --new-file v2.3.13/linux/drivers/video/vgacon.c linux/drivers/video/vgacon.c
--- v2.3.13/linux/drivers/video/vgacon.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/vgacon.c	Tue Aug 17 10:15:42 1999
@@ -277,6 +277,7 @@
 			vga_video_font_height = 8;
 		}
 	}
+
 	vga_vram_base = VGA_MAP_MEM(vga_vram_base);
 	vga_vram_end = VGA_MAP_MEM(vga_vram_end);
 
diff -u --recursive --new-file v2.3.13/linux/drivers/video/virgefb.c linux/drivers/video/virgefb.c
--- v2.3.13/linux/drivers/video/virgefb.c	Mon Aug  9 14:59:23 1999
+++ linux/drivers/video/virgefb.c	Thu Aug 12 10:22:33 1999
@@ -297,7 +297,7 @@
  *    Interface used by the world
  */
 
-void virgefb_setup(char *options, int *ints);
+int virgefb_setup(char*);
 
 static int virgefb_open(struct fb_info *info, int user);
 static int virgefb_release(struct fb_info *info, int user);
@@ -321,7 +321,7 @@
  *    Interface to the low level console driver
  */
 
-void virgefb_init(void);
+int virgefb_init(void);
 static int Cyberfb_switch(int con, struct fb_info *info);
 static int Cyberfb_updatevar(int con, struct fb_info *info);
 static void Cyberfb_blank(int blank, struct fb_info *info);
@@ -816,7 +816,7 @@
 #if 0
 static void Cyber_MoveCursor (u_short x, u_short y)
 {
-	printk("Yuck .... MoveCursor on a 3D\n");
+	printk(KERN_DEBUG "Yuck .... MoveCursor on a 3D\n");
 	return;
 }
 #endif
@@ -1128,14 +1128,14 @@
 };
 
 
-void __init virgefb_setup(char *options, int *ints)
+int __init virgefb_setup(char *options)
 {
 	char *this_opt;
 
 	fb_info.fontname[0] = '\0';
 
 	if (!options || !*options)
-		return;
+		return 0;
 
 	for (this_opt = strtok(options, ","); this_opt; this_opt = strtok(NULL, ","))
 		if (!strcmp(this_opt, "inverse")) {
@@ -1155,6 +1155,7 @@
 	DPRINTK("default mode: xres=%d, yres=%d, bpp=%d\n",virgefb_default.xres,
                                                            virgefb_default.yres,
 		                                           virgefb_default.bits_per_pixel);
+	return 0;
 }
 
 
@@ -1169,7 +1170,7 @@
 	const struct ConfigDev *cd;
 
 	if (!(CyberKey = zorro_find(ZORRO_PROD_PHASE5_CYBERVISION64_3D, 0, 0)))
-		return;
+		return -ENXIO;
 
 	cd = zorro_get_board (CyberKey);
 	zorro_config_board (CyberKey, 0);
@@ -1193,7 +1194,7 @@
 		Cyber_vcode_switch_base = (unsigned long) \
 			ZTWO_VADDR(board_addr + 0x003a0000);
 		cv3d_on_zorro2 = 1;
-		printk("CV3D detected running in Z2 mode.\n");
+		printk(KERN_INFO "CV3D detected running in Z2 mode.\n");
 	}
 	else
 	{
@@ -1203,7 +1204,7 @@
 		CyberRegs = ioremap(CyberRegs_phys, 0x00010000);
 		CyberMem = (unsigned long)ioremap(CyberMem_phys, 0x01000000);	/* was 0x00400000 */
 		cv3d_on_zorro2 = 0;
-		printk("CV3D detected running in Z3 mode\n");
+		printk(KERN_INFO "CV3D detected running in Z3 mode.\n");
 	}
 
 	fbhw = &Cyber_switch;
@@ -1228,15 +1229,16 @@
 	do_install_cmap(0, &fb_info);
 
 	if (register_framebuffer(&fb_info) < 0) {
-		printk("virgefb.c: register_framebuffer failed\n");
-		return;
+		printk(KERN_ERR "virgefb.c: register_framebuffer failed\n");
+		return -EINVAL;
 	}
 
-	printk("fb%d: %s frame buffer device, using %ldK of video memory\n",
+	printk(KERN_INFO "fb%d: %s frame buffer device, using %ldK of video memory\n",
 	       GET_FB_IDX(fb_info.node), fb_info.modename, CyberSize>>10);
 
 	/* TODO: This driver cannot be unloaded yet */
 	MOD_INC_USE_COUNT;
+	return 0;
 }
 
 
@@ -1425,8 +1427,7 @@
 #ifdef MODULE
 int init_module(void)
 {
-	virgefb_init();
-	return 0;
+	return virgefb_init();
 }
 
 void cleanup_module(void)
diff -u --recursive --new-file v2.3.13/linux/fs/Config.in linux/fs/Config.in
--- v2.3.13/linux/fs/Config.in	Wed Jun 16 19:26:27 1999
+++ linux/fs/Config.in	Thu Aug 12 12:26:06 1999
@@ -103,21 +103,7 @@
 
 mainmenu_option next_comment
 comment 'Partition Types'
-
-bool 'BSD disklabel (BSD partition tables) support' CONFIG_BSD_DISKLABEL
-bool 'Macintosh partition map support' CONFIG_MAC_PARTITION
-bool 'SMD disklabel (Sun partition tables) support' CONFIG_SMD_DISKLABEL
-bool 'Solaris (x86) partition table support' CONFIG_SOLARIS_X86_PARTITION
-bool 'SGI disklabel support' CONFIG_SGI_DISKLABEL
-if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-  bool 'Unixware slices support (EXPERIMENTAL)' CONFIG_UNIXWARE_DISKLABEL
-fi
+source fs/partitions/Config.in
 endmenu
-
-if [ "$CONFIG_AFFS_FS" != "n" ]; then
-  define_bool CONFIG_AMIGA_PARTITION y
-fi
-
 source fs/nls/Config.in
-
 endmenu
diff -u --recursive --new-file v2.3.13/linux/fs/Makefile linux/fs/Makefile
--- v2.3.13/linux/fs/Makefile	Wed Jul 28 14:47:42 1999
+++ linux/fs/Makefile	Thu Aug 12 12:26:06 1999
@@ -18,7 +18,9 @@
 MOD_LIST_NAME := FS_MODULES
 ALL_SUB_DIRS = coda minix ext2 fat msdos vfat proc isofs nfs umsdos ntfs \
 		hpfs sysv smbfs ncpfs ufs efs affs romfs autofs hfs lockd \
-		nfsd nls devpts adfs qnx4
+		nfsd nls devpts adfs partitions qnx4
+
+SUB_DIRS := partitions
 
 ifeq ($(CONFIG_QUOTA),y)
 O_OBJS += dquot.o
diff -u --recursive --new-file v2.3.13/linux/fs/exec.c linux/fs/exec.c
--- v2.3.13/linux/fs/exec.c	Mon Aug  9 14:59:23 1999
+++ linux/fs/exec.c	Thu Aug 12 11:53:18 1999
@@ -811,6 +811,7 @@
 	if (!binfmt || !binfmt->core_dump)
 		goto fail;
 	if (!current->dumpable || atomic_read(&current->mm->mm_users) != 1)
+		goto fail;
 	current->dumpable = 0;
 	if (current->rlim[RLIMIT_CORE].rlim_cur < binfmt->min_coredump)
 		goto fail;
diff -u --recursive --new-file v2.3.13/linux/fs/minix/truncate.c linux/fs/minix/truncate.c
--- v2.3.13/linux/fs/minix/truncate.c	Mon Aug  9 14:59:23 1999
+++ linux/fs/minix/truncate.c	Wed Aug 18 10:15:19 1999
@@ -62,10 +62,7 @@
 		}
 		*p = 0;
 		mark_inode_dirty(inode);
-		if (bh) {
-			mark_buffer_clean(bh);
-			brelse(bh);
-		}
+		bforget(bh);
 		minix_free_block(inode,tmp);
 	}
 	return retry;
@@ -113,7 +110,7 @@
 		}
 		*ind = 0;
 		mark_buffer_dirty(ind_bh, 1);
-		brelse(bh);
+		bforget(bh);
 		minix_free_block(inode,tmp);
 	}
 	ind = (unsigned short *) ind_bh->b_data;
@@ -226,10 +223,7 @@
 		}
 		*p = 0;
 		mark_inode_dirty(inode);
-		if (bh) {
-			mark_buffer_clean(bh);
-			brelse(bh);
-		}
+		bforget(bh);
 		minix_free_block(inode,tmp);
 	}
 	return retry;
@@ -277,7 +271,7 @@
 		}
 		*ind = 0;
 		mark_buffer_dirty(ind_bh, 1);
-		brelse(bh);
+		bforget(bh);
 		minix_free_block(inode,tmp);
 	}
 	ind = (unsigned long *) ind_bh->b_data;
@@ -406,7 +400,8 @@
 			(unsigned long *) inode->u.minix_i.u.i2_data + 9);
 		if (!retry)
 			break;
-		current->counter = 0;
+		run_task_queue(&tq_disk);
+		current->policy |= SCHED_YIELD;
 		schedule();
 	}
 	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
diff -u --recursive --new-file v2.3.13/linux/fs/msdos/namei.c linux/fs/msdos/namei.c
--- v2.3.13/linux/fs/msdos/namei.c	Mon Aug  9 14:59:23 1999
+++ linux/fs/msdos/namei.c	Wed Aug 18 10:03:52 1999
@@ -8,7 +8,6 @@
 
 
 #define __NO_VERSION__
-#include <linux/config.h>
 #include <linux/module.h>
 
 #include <linux/sched.h>
@@ -26,23 +25,18 @@
 /* MS-DOS "device special files" */
 
 static const char *reserved_names[] = {
-#ifndef CONFIG_ATARI /* GEMDOS is less stupid */
     "CON     ","PRN     ","NUL     ","AUX     ",
     "LPT1    ","LPT2    ","LPT3    ","LPT4    ",
     "COM1    ","COM2    ","COM3    ","COM4    ",
-#endif
     NULL };
 
 
 /* Characters that are undesirable in an MS-DOS file name */
   
 static char bad_chars[] = "*?<>|\"";
-#ifdef CONFIG_ATARI
-/* GEMDOS is less restrictive */
-static char bad_if_strict[] = " ";
-#else
-static char bad_if_strict[] = "+=,; ";
-#endif
+static char bad_if_strict_pc[] = "+=,; ";
+static char bad_if_strict_atari[] = " "; /* GEMDOS is less restrictive */
+#define	bad_if_strict(opts) ((opts)->atari ? bad_if_strict_atari : bad_if_strict_pc)
 
 /* Must die */
 void msdos_put_super(struct super_block *sb)
@@ -51,8 +45,8 @@
 }
 
 /***** Formats an MS-DOS file name. Rejects invalid names. */
-static int msdos_format_name(char conv,const char *name,int len,
-	char *res,char dotsOK)
+static int msdos_format_name(const char *name,int len,
+	char *res,struct fat_mount_options *opts)
 	/* conv is relaxed/normal/strict, name is proposed name,
 	 * len is the length of the proposed name, res is the result name,
 	 * dotsOK is if hidden files get dots.
@@ -62,23 +56,27 @@
 	const char **reserved;
 	unsigned char c;
 	int space;
+
 	if (name[0] == '.') {  /* dotfile because . and .. already done */
-		if (!dotsOK) return -EINVAL;
-		/* Get rid of dot - test for it elsewhere */
-		name++; len--;
+		if (opts->dotsOK) {
+			/* Get rid of dot - test for it elsewhere */
+			name++; len--;
+		}
+		else if (!opts->atari) return -EINVAL;
 	}
-#ifndef CONFIG_ATARI
-	space = 1; /* disallow names that _really_ start with a dot */
-#else
-	space = 0; /* GEMDOS does not care */
-#endif
+	/* disallow names that _really_ start with a dot for MS-DOS, GEMDOS does
+	 * not care */
+	space = !opts->atari;
 	c = 0;
 	for (walk = res; len && walk-res < 8; walk++) {
 	    	c = *name++;
 		len--;
-		if (conv != 'r' && strchr(bad_chars,c)) return -EINVAL;
-		if (conv == 's' && strchr(bad_if_strict,c)) return -EINVAL;
-  		if (c >= 'A' && c <= 'Z' && conv == 's') return -EINVAL;
+		if (opts->conversion != 'r' && strchr(bad_chars,c))
+			return -EINVAL;
+		if (opts->conversion == 's' && strchr(bad_if_strict(opts),c))
+			return -EINVAL;
+  		if (c >= 'A' && c <= 'Z' && opts->conversion == 's')
+			return -EINVAL;
 		if (c < ' ' || c == ':' || c == '\\') return -EINVAL;
 /*  0xE5 is legal as a first character, but we must substitute 0x05     */
 /*  because 0xE5 marks deleted files.  Yes, DOS really does this.       */
@@ -90,7 +88,7 @@
 		*walk = (c >= 'a' && c <= 'z') ? c-32 : c;
 	}
 	if (space) return -EINVAL;
-	if (conv == 's' && len && c != '.') {
+	if (opts->conversion == 's' && len && c != '.') {
 		c = *name++;
 		len--;
 		if (c != '.') return -EINVAL;
@@ -101,26 +99,31 @@
 		while (len > 0 && walk-res < MSDOS_NAME) {
 			c = *name++;
 			len--;
-			if (conv != 'r' && strchr(bad_chars,c)) return -EINVAL;
-			if (conv == 's' && strchr(bad_if_strict,c))
+			if (opts->conversion != 'r' && strchr(bad_chars,c))
+				return -EINVAL;
+			if (opts->conversion == 's' &&
+			    strchr(bad_if_strict(opts),c))
 				return -EINVAL;
 			if (c < ' ' || c == ':' || c == '\\')
 				return -EINVAL;
 			if (c == '.') {
-				if (conv == 's')
+				if (opts->conversion == 's')
 					return -EINVAL;
 				break;
 			}
-			if (c >= 'A' && c <= 'Z' && conv == 's') return -EINVAL;
+			if (c >= 'A' && c <= 'Z' && opts->conversion == 's')
+				return -EINVAL;
 			space = c == ' ';
 			*walk++ = c >= 'a' && c <= 'z' ? c-32 : c;
 		}
 		if (space) return -EINVAL;
-		if (conv == 's' && len) return -EINVAL;
+		if (opts->conversion == 's' && len) return -EINVAL;
 	}
 	while (walk-res < MSDOS_NAME) *walk++ = ' ';
-	for (reserved = reserved_names; *reserved; reserved++)
-		if (!strncmp(res,*reserved,8)) return -EINVAL;
+	if (!opts->atari)
+		/* GEMDOS is less stupid and has no reserved names */
+		for (reserved = reserved_names; *reserved; reserved++)
+			if (!strncmp(res,*reserved,8)) return -EINVAL;
 	return 0;
 }
 
@@ -133,8 +136,7 @@
 	char msdos_name[MSDOS_NAME];
 
 	dotsOK = MSDOS_SB(dir->i_sb)->options.dotsOK;
-	res = msdos_format_name(MSDOS_SB(dir->i_sb)->options.name_check,
-				name,len, msdos_name,dotsOK);
+	res = msdos_format_name(name,len, msdos_name,&MSDOS_SB(dir->i_sb)->options);
 	if (res < 0)
 		return -ENOENT;
 	res = fat_scan(dir,msdos_name,bh,de,ino);
@@ -163,8 +165,7 @@
 	int error;
 	char msdos_name[MSDOS_NAME];
 	
-	error = msdos_format_name(options->name_check, qstr->name, qstr->len,
-					msdos_name, options->dotsOK);
+	error = msdos_format_name(qstr->name, qstr->len, msdos_name, options);
 	if (!error)
 		qstr->hash = full_name_hash(msdos_name, MSDOS_NAME);
 	return 0;
@@ -180,12 +181,10 @@
 	int error;
 	char a_msdos_name[MSDOS_NAME], b_msdos_name[MSDOS_NAME];
 
-	error = msdos_format_name(options->name_check, a->name, a->len,
-					a_msdos_name, options->dotsOK);
+	error = msdos_format_name(a->name, a->len, a_msdos_name, options);
 	if (error)
 		goto old_compare;
-	error = msdos_format_name(options->name_check, b->name, b->len,
-					b_msdos_name, options->dotsOK);
+	error = msdos_format_name(b->name, b->len, b_msdos_name, options);
 	if (error)
 		goto old_compare;
 	error = memcmp(a_msdos_name, b_msdos_name, MSDOS_NAME);
@@ -288,9 +287,8 @@
 	int ino,res,is_hid;
 	char msdos_name[MSDOS_NAME];
 
-	res = msdos_format_name(MSDOS_SB(sb)->options.name_check,
-				dentry->d_name.name,dentry->d_name.len,
-				msdos_name, MSDOS_SB(sb)->options.dotsOK);
+	res = msdos_format_name(dentry->d_name.name,dentry->d_name.len,
+				msdos_name, &MSDOS_SB(sb)->options);
 	if (res < 0)
 		return res;
 	is_hid = (dentry->d_name.name[0]=='.') && (msdos_name[0]!='.');
@@ -367,9 +365,8 @@
 	struct msdos_dir_entry *de1;
 	int ino;
 
-	res = msdos_format_name(MSDOS_SB(sb)->options.name_check,
-				dentry->d_name.name,dentry->d_name.len,
-				msdos_name,MSDOS_SB(sb)->options.dotsOK);
+	res = msdos_format_name(dentry->d_name.name,dentry->d_name.len,
+				msdos_name, &MSDOS_SB(sb)->options);
 	if (res < 0)
 		return res;
 	is_hid = (dentry->d_name.name[0]=='.') && (msdos_name[0]!='.');
@@ -561,14 +558,14 @@
 	int is_hid,old_hid; /* if new file and old file are hidden */
 	char old_msdos_name[MSDOS_NAME], new_msdos_name[MSDOS_NAME];
 
-	error = msdos_format_name(MSDOS_SB(sb)->options.name_check,
-				old_dentry->d_name.name, old_dentry->d_name.len,
-				old_msdos_name,MSDOS_SB(sb)->options.dotsOK);
+	error = msdos_format_name(old_dentry->d_name.name,
+				  old_dentry->d_name.len,old_msdos_name,
+				  &MSDOS_SB(old_dir->i_sb)->options);
 	if (error < 0)
 		goto rename_done;
-	error = msdos_format_name(MSDOS_SB(sb)->options.name_check,
-				new_dentry->d_name.name, new_dentry->d_name.len,
-				new_msdos_name,MSDOS_SB(sb)->options.dotsOK);
+	error = msdos_format_name(new_dentry->d_name.name,
+				  new_dentry->d_name.len,new_msdos_name,
+				  &MSDOS_SB(new_dir->i_sb)->options);
 	if (error < 0)
 		goto rename_done;
 
diff -u --recursive --new-file v2.3.13/linux/fs/partitions/Config.in linux/fs/partitions/Config.in
--- v2.3.13/linux/fs/partitions/Config.in	Wed Dec 31 16:00:00 1969
+++ linux/fs/partitions/Config.in	Sun Aug 15 11:44:29 1999
@@ -0,0 +1,54 @@
+#
+# Partition configuration
+#
+bool 'Advanced partition selection' CONFIG_PARTITION_ADVANCED
+if [ "$CONFIG_PARTITION_ADVANCED" = "n" ]; then
+  define_bool CONFIG_MSDOS_PARTITION y
+  if [ "$ARCH" = "alpha" ]; then
+    define_bool CONFIG_OSF_PARTITION y
+  fi
+  if [ "$CONFIG_AMIGA" = "y" ]; then
+    define_bool CONFIG_AMIGA_PARTITION y
+  fi
+  if [ "$CONFIG_ARM" = "y" ]; then
+    if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
+      define_bool CONFIG_ACORN_PARTITION y
+      define_bool CONFIG_ACORN_PARTITION_ADFS y
+#      define_bool CONFIG_ACORN_PARTITION_CUMANA y
+      define_bool CONFIG_ACORN_PARTITION_ICS y
+      define_bool CONFIG_ACORN_PARTITION_POWERTEC y
+      define_bool CONFIG_ACORN_PARTITION_RISCIX y
+    fi
+  fi
+  if [ "$CONFIG_ATARI" = "y" ]; then
+    define_bool CONFIG_ATARI_PARTITION y
+  fi
+  bool 'SMD disklabel (Sun partition tables) support' CONFIG_SMD_DISKLABEL
+  if [ "$ARCH" = "sparc" -o "$CONFIG_SMD_DISKLABEL" = "y" ]; then
+    define_bool CONFIG_SUN_PARTITION y
+  fi
+  bool 'SGI disklabel support' CONFIG_SGI_DISKLABEL
+  if [ "$CONFIG_SGI" = "y" -o "$CONFIG_SGI_DISKLABEL" = "y" ]; then
+    define_bool CONFIG_SGI_PARTITION y
+  fi
+else
+  bool 'Alpha OSF partition support' CONFIG_OSF_PARTITION
+  bool 'Macintosh partition map support' CONFIG_MAC_PARTITION
+  bool 'PC BIOS (MSDOS partition tables) support' CONFIG_MSDOS_PARTITION
+  bool 'SGI partition support' CONFIG_SGI_PARTITION
+  bool 'BSD disklabel (FreeBSD partition tables) support' CONFIG_BSD_DISKLABEL
+  bool 'SMD disklabel (Sun partition tables) support' CONFIG_SMD_DISKLABEL
+  bool 'Solaris (x86) partition table support' CONFIG_SOLARIS_X86_PARTITION
+  bool 'SGI disklabel support' CONFIG_SGI_DISKLABEL
+
+  bool 'SPARC partition support' CONFIG_SUN_PARTITION
+  bool 'Amiga partition table support' CONFIG_AMIGA_PARTITION
+  bool 'Acorn partition support' CONFIG_ACORN_PARTITION
+  if [ "$CONFIG_ACORN_PARTITION" != "n" ]; then
+    bool '  Native filecore partition support' CONFIG_ACORN_PARTITION_ADFS
+#    bool '  Cumana partition support' CONFIG_ACORN_PARTITION_CUMANA
+    bool '  ICS partition support' CONFIG_ACORN_PARTITION_ICS
+    bool '  PowerTec partition support' CONFIG_ACORN_PARTITION_POWERTEC
+    bool '  RISCiX partition support' CONFIG_ACORN_PARTITION_RISCIX
+  fi
+fi
diff -u --recursive --new-file v2.3.13/linux/fs/partitions/Makefile linux/fs/partitions/Makefile
--- v2.3.13/linux/fs/partitions/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/fs/partitions/Makefile	Thu Aug 12 12:26:06 1999
@@ -0,0 +1,49 @@
+#
+# Makefile for the linux kernel.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+O_TARGET := partitions.o
+O_OBJS   := check.o
+
+ifeq ($(CONFIG_ACORN_PARTITION),y)
+O_OBJS += acorn.o
+endif
+
+ifeq ($(CONFIG_AMIGA_PARTITION),y)
+O_OBJS += amiga.o
+endif
+
+ifeq ($(CONFIG_ATARI_PARTITION),y)
+O_OBJS += atari.o
+endif
+
+ifeq ($(CONFIG_MAC_PARTITION),y)
+O_OBJS += mac.o
+endif
+
+ifeq ($(CONFIG_MSDOS_PARTITION),y)
+O_OBJS += msdos.o
+endif
+
+ifeq ($(CONFIG_OSF_PARTITION),y)
+O_OBJS += osf.o
+endif
+
+ifeq ($(CONFIG_SGI_PARTITION),y)
+O_OBJS += sgi.o
+endif
+
+ifeq ($(CONFIG_SUN_PARTITION),y)
+O_OBJS += sun.o
+endif
+
+ifeq ($(CONFIG_ULTRIX_PARTITION),y)
+O_OBJS += ultrix.o
+endif
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.13/linux/fs/partitions/acorn.c linux/fs/partitions/acorn.c
--- v2.3.13/linux/fs/partitions/acorn.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/partitions/acorn.c	Thu Aug 12 12:26:06 1999
@@ -0,0 +1,454 @@
+/*
+ * linux/arch/arm/drivers/block/adfspart.c
+ *
+ * Copyright (c) 1996,1997 Russell King.
+ *
+ * Scan ADFS partitions on hard disk drives.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/genhd.h>
+#include <linux/fs.h>
+
+#include "acorn.h"
+
+extern void add_gd_partition(struct gendisk *hd, unsigned int minor, unsigned int start, unsigned int size);
+
+static void
+adfspart_setgeometry(kdev_t dev, unsigned int secspertrack, unsigned int heads,
+		     unsigned long totalblocks)
+{
+	extern void xd_set_geometry(kdev_t dev, unsigned char, unsigned char,
+				    unsigned long, unsigned int);
+
+#ifdef CONFIG_BLK_DEV_MFM
+	if (MAJOR(dev) == MFM_ACORN_MAJOR)
+		xd_set_geometry(dev, secspertrack, heads, totalblocks, 1);
+#endif
+}
+
+#define LINUX_NATIVE_MAGIC 0xdeafa1de
+#define LINUX_SWAP_MAGIC   0xdeafab1e
+
+struct linux_part {
+	unsigned long magic;
+	unsigned long start_sect;
+	unsigned long nr_sects;
+};
+
+static struct disc_record *adfs_partition(struct gendisk *hd, char *name, char *data,
+					   unsigned long first_sector, unsigned int minor)
+{
+	struct disc_record *dr;
+	unsigned int nr_sects;
+
+	if (adfs_checkbblk(data))
+		return NULL;
+
+	dr = (struct disc_record *)(data + 0x1c0);
+
+	if (dr->disc_size == 0 && dr->disc_size_high == 0)
+		return NULL;
+
+	nr_sects = (dr->disc_size_high << 23) | (dr->disc_size >> 9);
+
+	if (name)
+		printk(" [%s]", name);
+	add_gd_partition(hd, minor, first_sector, nr_sects);
+	return dr;
+}
+
+#ifdef CONFIG_ACORN_PARTITION_RISCIX
+static int riscix_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sect,
+			     unsigned int minor, unsigned long nr_sects)
+{
+	struct buffer_head *bh;
+	struct riscix_record *rr;
+	unsigned int riscix_minor;
+
+	printk(" [RISCiX]");
+
+	add_gd_partition(hd, riscix_minor = minor++, first_sect, nr_sects);
+	hd->sizes[riscix_minor] = hd->part[riscix_minor].nr_sects >> (BLOCK_SIZE_BITS - 9);
+	dev = MKDEV(hd->major, riscix_minor);
+
+	if (!(bh = bread(dev, 0, 1024)))
+		return -1;
+
+	rr = (struct riscix_record *)bh->b_data;
+	if (rr->magic == RISCIX_MAGIC) {
+		int part;
+
+		printk(" <");
+
+		for (part = 0; part < 8; part++) {
+			if (rr->part[part].one &&
+			    memcmp(rr->part[part].name, "All\0", 4)) {
+				add_gd_partition(hd, minor++,
+						rr->part[part].start,
+						rr->part[part].length);
+				printk("(%s)", rr->part[part].name);
+			}
+		}
+
+		printk(" >");
+
+		if (hd->part[riscix_minor].nr_sects > 2)
+			hd->part[riscix_minor].nr_sects = 2;
+	}
+
+	brelse(bh);
+	return minor;
+}
+#endif
+
+static int linux_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sect,
+			    unsigned int minor, unsigned long nr_sects)
+{
+	struct buffer_head *bh;
+	struct linux_part *linuxp;
+	unsigned int linux_minor, mask = (1 << hd->minor_shift) - 1;
+
+	printk(" [Linux]");
+
+	add_gd_partition(hd, linux_minor = minor++, first_sect, nr_sects);
+	hd->sizes[linux_minor] = hd->part[linux_minor].nr_sects >> (BLOCK_SIZE_BITS - 9);
+	dev = MKDEV(hd->major, linux_minor);
+
+	if (!(bh = bread(dev, 0, 1024)))
+		return -1;
+
+	linuxp = (struct linux_part *)bh->b_data;
+	printk(" <");
+	while (linuxp->magic == LINUX_NATIVE_MAGIC || linuxp->magic == LINUX_SWAP_MAGIC) {
+		if (!(minor & mask))
+			break;
+		add_gd_partition(hd, minor++, first_sect + linuxp->start_sect,
+			linuxp->nr_sects);
+		linuxp ++;
+	}
+	printk(" >");
+	/*
+	 * Prevent someone doing a mkswap or mkfs on this partition
+	 */
+	if(hd->part[linux_minor].nr_sects > 2)
+		hd->part[linux_minor].nr_sects = 2;
+
+	brelse(bh);
+	return minor;
+}
+
+#ifdef CONFIG_ACORN_PARTITION_CUMANA
+static int adfspart_check_CUMANA(struct gendisk *hd, kdev_t dev, unsigned long first_sector,
+				  unsigned int minor)
+{
+	unsigned int start_blk = 0, mask = (1 << hd->minor_shift) - 1;
+	struct buffer_head *bh = NULL;
+	char *name = "CUMANA/ADFS";
+	int first = 1;
+
+	/*
+	 * Try Cumana style partitions - sector 3 contains ADFS boot block with pointer
+	 * to next 'drive'.
+	 *
+	 * There are unknowns in this code - is the 'cylinder number' of the next
+	 * partition relative to the start of this one - I'm assuming it is.
+	 *
+	 * Also, which ID did Cumana use?
+	 *
+	 * This is totally unfinished, and will require more work to get it going.
+	 * Hence it is totally untested.
+	 */
+	do {
+		struct disc_record *dr;
+		unsigned int nr_sects;
+
+		if (!(minor & mask))
+			break;
+
+		if (!(bh = bread(dev, start_blk + 3, 1024)))
+			return -1;
+
+		dr = adfs_partition(hd, name, bh->b_data, first_sector, minor++);
+		if (!dr)
+			break;
+		name = NULL;
+
+		nr_sects = (bh->b_data[0x1fd] + (bh->b_data[0x1fe] << 8)) *
+			 (dr->heads + (dr->lowsector & 0x40 ? 1 : 0)) * dr->secspertrack;
+
+		if (!nr_sects)
+			break;
+
+		first = 0;
+		first_sector += nr_sects;
+		start_blk += nr_sects >> (BLOCK_SIZE_BITS - 9);
+		nr_sects = 0; /* hmm - should be partition size */
+
+		switch (bh->b_data[0x1fc] & 15) {
+		case 0: /* No partition / ADFS? */
+			break;
+
+#ifdef CONFIG_ACORN_PARTITION_RISCIX
+		case PARTITION_RISCIX_SCSI: /* RiscIX - we don't know how to find the next one. */
+			minor = riscix_partition(hd, dev, first_sector, minor, nr_sects);
+			break;
+#endif
+
+		case PARTITION_LINUX:
+			minor = linux_partition(hd, dev, first_sector, minor, nr_sects);
+			break;
+		}
+		brelse(bh);
+		bh = NULL;
+		if (minor == -1)
+			return minor;
+	} while (1);
+	if (bh)
+		brelse(bh);
+	return first ? 0 : 1;
+}
+#endif
+
+#ifdef CONFIG_ACORN_PARTITION_ADFS
+/*
+ * Purpose: allocate ADFS partitions.
+ *
+ * Params : hd		- pointer to gendisk structure to store partition info.
+ *	    dev		- device number to access.
+ *	    first_sector- first readable sector on the device.
+ *	    minor	- first available minor on device.
+ *
+ * Returns: -1 on error, 0 for no ADFS boot sector, 1 for ok.
+ *
+ * Alloc  : hda  = whole drive
+ *	    hda1 = ADFS partition on first drive.
+ *	    hda2 = non-ADFS partition.
+ */
+static int adfspart_check_ADFS(struct gendisk *hd, kdev_t dev, unsigned long first_sector,
+				unsigned int minor)
+{
+	unsigned long start_sect, nr_sects, sectscyl, heads;
+	struct buffer_head *bh;
+	struct disc_record *dr;
+
+	if (!(bh = bread(dev, 3, 1024)))
+		return -1;
+
+	dr = adfs_partition(hd, "ADFS", bh->b_data, first_sector, minor++);
+	if (!dr) {
+	    	brelse(bh);
+    		return 0;
+	}
+
+	heads = dr->heads + ((dr->lowsector >> 6) & 1);
+	adfspart_setgeometry(dev, dr->secspertrack, heads, hd->part[MINOR(dev)].nr_sects);
+	sectscyl = dr->secspertrack * heads;
+
+	/*
+	 * Work out start of non-adfs partition.
+	 */
+	start_sect = ((bh->b_data[0x1fe] << 8) + bh->b_data[0x1fd]) * sectscyl;
+	nr_sects = hd->part[MINOR(dev)].nr_sects - start_sect;
+
+	if (start_sect) {
+		first_sector += start_sect;
+		/*
+		 * we now have a problem - how to set the origional disk size if the
+		 * disk doesn't report it, since there is no standard way of getting
+		 * that info.
+		 */
+		switch (bh->b_data[0x1fc] & 15) {
+#ifdef CONFIG_ACORN_PARTITION_RISCIX
+		case PARTITION_RISCIX_SCSI:
+		case PARTITION_RISCIX_MFM:
+			minor = riscix_partition(hd, dev, first_sector, minor, nr_sects);
+			break;
+#endif
+
+		case PARTITION_LINUX:
+			minor = linux_partition(hd, dev, first_sector, minor, nr_sects);
+			break;
+		}
+	}
+	brelse(bh);
+	return 1;
+}
+#endif
+
+#ifdef CONFIG_ACORN_PARTITION_ICS
+static int adfspart_check_ICSLinux(kdev_t dev, unsigned long block)
+{
+	struct buffer_head *bh;
+	unsigned int offset = block & 1 ? 512 : 0;
+	int result = 0;
+
+	bh = bread(dev, block >> 1, 1024);
+
+	if (bh != NULL) {
+		if (memcmp(bh->b_data + offset, "LinuxPart", 9) == 0)
+			result = 1;
+
+		brelse(bh);
+	}
+
+	return result;
+}
+
+/*
+ * Purpose: allocate ICS partitions.
+ * Params : hd		- pointer to gendisk structure to store partition info.
+ *	    dev		- device number to access.
+ *	    first_sector- first readable sector on the device.
+ *	    minor	- first available minor on device.
+ * Returns: -1 on error, 0 for no ICS table, 1 for partitions ok.
+ * Alloc  : hda  = whole drive
+ *	    hda1 = ADFS partition 0 on first drive.
+ *	    hda2 = ADFS partition 1 on first drive.
+ *		..etc..
+ */
+static int adfspart_check_ICS(struct gendisk *hd, kdev_t dev, unsigned long first_sector,
+			       unsigned int minor)
+{
+	struct buffer_head *bh;
+	unsigned long sum;
+	unsigned int i, mask = (1 << hd->minor_shift) - 1;
+	struct ics_part { unsigned long start; signed long size; } *p;
+
+	/*
+	 * Try ICS style partitions - sector 0 contains partition info.
+	 */
+	if (!(bh = bread(dev, 0, 1024)))
+	    	return -1;
+
+	/*
+	 * check for a valid checksum
+	 */
+	for (i = 0, sum = 0x50617274; i < 508; i++)
+		sum += bh->b_data[i];
+
+	if (sum != *(unsigned long *)(&bh->b_data[508])) {
+	    	brelse(bh);
+		return 0; /* not ICS partition table */
+	}
+
+	printk(" [ICS]");
+
+	for (p = (struct ics_part *)bh->b_data; p->size; p++) {
+		if ((minor & mask) == 0)
+			break;
+
+		if (p->size < 0 && adfspart_check_ICSLinux(dev, p->start)) {
+			/*
+			 * We use the first sector to identify what type
+			 * this partition is...
+			 */
+			if (-p->size > 1)
+				add_gd_partition(hd, minor, first_sector + p->start + 1, -p->size - 1);
+		} else
+			add_gd_partition(hd, minor, first_sector + p->start, p->size);
+		minor++;
+	}
+
+	brelse(bh);
+	return 1;
+}
+#endif
+
+#ifdef CONFIG_ACORN_PARTITION_POWERTEC
+struct ptec_partition {
+	u32 unused1;
+	u32 unused2;
+	u32 start;
+	u32 size;
+	u32 unused5;
+	char type[8];
+};
+	
+/*
+ * Purpose: allocate ICS partitions.
+ * Params : hd		- pointer to gendisk structure to store partition info.
+ *	    dev		- device number to access.
+ *	    first_sector- first readable sector on the device.
+ *	    minor	- first available minor on device.
+ * Returns: -1 on error, 0 for no ICS table, 1 for partitions ok.
+ * Alloc  : hda  = whole drive
+ *	    hda1 = ADFS partition 0 on first drive.
+ *	    hda2 = ADFS partition 1 on first drive.
+ *		..etc..
+ */
+static int adfspart_check_POWERTEC(struct gendisk *hd, kdev_t dev, unsigned long first_sector,
+				   unsigned int minor)
+{
+	struct buffer_head *bh;
+	struct ptec_partition *p;
+	unsigned char checksum;
+	int i;
+
+	if (!(bh = bread(dev, 0, 1024)))
+		return -1;
+
+	for (checksum = 0x2a, i = 0; i < 511; i++)
+		checksum += bh->b_data[i];
+
+	if (checksum != bh->b_data[511]) {
+		brelse(bh);
+		return 0;
+	}
+
+	printk(" [POWERTEC]");
+
+	for (i = 0, p = (struct ptec_partition *)bh->b_data; i < 12; i++, p++) {
+		if (p->size)
+			add_gd_partition(hd, minor, first_sector + p->start, p->size);
+		minor++;
+	}
+
+	brelse(bh);
+	return 1;
+}
+#endif
+
+/*
+ * Purpose: initialise all the partitions on an ADFS drive.
+ *          These may be other ADFS partitions or a Linux/RiscBSD/RiscIX
+ *	    partition.
+ *
+ * Params : hd		 - pointer to gendisk structure to store devices partitions.
+ *          dev		 - device number to access
+ *	    first_sector - first available sector on the disk.
+ *	    minor	 - first available minor on this device.
+ *
+ * Returns: -1 on error, 0 if not ADFS format, 1 if ok.
+ */
+int acorn_partition(struct gendisk *hd, kdev_t dev,
+		    unsigned long first_sector, int first_part_minor)
+{
+	int r = 0;
+
+#ifdef CONFIG_ACORN_PARTITION_ICS
+	if (r == 0)
+		r = adfspart_check_ICS(hd, dev, first_sector, first_part_minor);
+#endif
+#ifdef CONFIG_ACORN_PARTITION_CUMANA
+	if (r == 0)    
+		r = adfspart_check_CUMANA(hd, dev, first_sector, first_part_minor);
+#endif
+#ifdef CONFIG_ACORN_PARTITION_ADFS
+	if (r == 0)
+		r = adfspart_check_ADFS(hd, dev, first_sector, first_part_minor);
+#endif
+#ifdef CONFIG_ACORN_PARTITION_POWERTEC
+	if (r == 0)
+		r = adfspart_check_POWERTEC(hd, dev, first_sector, first_part_minor);
+#endif
+	if (r < 0)
+		printk(" unable to read boot sectors / partition sectors\n");
+	else if (r)
+		printk("\n");
+	return r;
+}
diff -u --recursive --new-file v2.3.13/linux/fs/partitions/acorn.h linux/fs/partitions/acorn.h
--- v2.3.13/linux/fs/partitions/acorn.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/partitions/acorn.h	Thu Aug 12 12:26:06 1999
@@ -0,0 +1,68 @@
+/*
+ * fs/partitions/acorn.h
+ *
+ * Copyright (C) 1996-1998 Russell King
+ */
+#include <linux/adfs_fs.h>
+
+/*
+ * Offset in bytes of the boot block on the disk.
+ */
+#define BOOT_SECTOR_ADDRESS 0xc00
+
+/*
+ * Disc record size
+ */
+#define RECSIZE 60
+
+/*
+ * Disc record
+ */
+struct disc_record {
+	unsigned char  log2secsize;
+	unsigned char  secspertrack;
+	unsigned char  heads;
+	unsigned char  density;
+	unsigned char  idlen;
+	unsigned char  log2bpmb;
+	unsigned char  skew;
+	unsigned char  bootoption;
+	unsigned char  lowsector;
+	unsigned char  nzones;
+	unsigned short zone_spare;
+	unsigned long  root;
+	unsigned long  disc_size;
+	unsigned short disc_id;
+	unsigned char  disc_name[10];
+	unsigned long  disc_type;
+	unsigned long  disc_size_high;
+	unsigned char  log2sharesize:4;
+	unsigned char  unused:4;
+	unsigned char  big_flag:1;
+};
+
+/*
+ * Partition types. (Oh for reusability)
+ */
+#define PARTITION_RISCIX_MFM	1
+#define PARTITION_RISCIX_SCSI	2
+#define PARTITION_LINUX		9
+
+struct riscix_part {
+	unsigned long  start;
+	unsigned long  length;
+	unsigned long  one;
+	char name[16];
+};
+
+struct riscix_record {
+	unsigned long  magic;
+#define RISCIX_MAGIC	(0x4a657320)
+	unsigned long  date;
+	struct riscix_part part[8];
+};
+
+int
+acorn_partition(struct gendisk *hd, kdev_t dev,
+		unsigned long first_sector, int first_part_minor);
+
diff -u --recursive --new-file v2.3.13/linux/fs/partitions/amiga.c linux/fs/partitions/amiga.c
--- v2.3.13/linux/fs/partitions/amiga.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/partitions/amiga.c	Sun Aug 15 11:44:29 1999
@@ -0,0 +1,120 @@
+/*
+ *  fs/partitions/amiga.c
+ *
+ *  Code extracted from drivers/block/genhd.c
+ *
+ *  Copyright (C) 1991-1998  Linus Torvalds
+ *  Re-organised Feb 1998 Russell King
+ */
+
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/blk.h>
+
+#include <asm/byteorder.h>
+#include <linux/affs_hardblocks.h>
+
+#include "check.h"
+#include "amiga.h"
+
+static __inline__ u32
+checksum_block(u32 *m, int size)
+{
+	u32 sum = 0;
+
+	while (size--)
+		sum += be32_to_cpu(*m++);
+	return sum;
+}
+
+int
+amiga_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, int first_part_minor)
+{
+	struct buffer_head	*bh;
+	struct RigidDiskBlock	*rdb;
+	struct PartitionBlock	*pb;
+	int			 start_sect;
+	int			 nr_sects;
+	int			 blk;
+	int			 part, res;
+	int			 old_blocksize;
+	int			 blocksize;
+
+	old_blocksize = get_ptable_blocksize(dev);
+	blocksize = get_hardsect_size(dev);
+
+	if (blocksize < 512)
+		blocksize = 512;
+
+	set_blocksize(dev,blocksize);
+	res = 0;
+
+	for (blk = 0; blk < RDB_ALLOCATION_LIMIT; blk++) {
+		if(!(bh = bread(dev,blk,blocksize))) {
+			printk("Dev %s: unable to read RDB block %d\n",
+			       kdevname(dev),blk);
+			goto rdb_done;
+		}
+		if (*(u32 *)bh->b_data == cpu_to_be32(IDNAME_RIGIDDISK)) {
+			rdb = (struct RigidDiskBlock *)bh->b_data;
+			if (checksum_block((u32 *)bh->b_data,be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F)) {
+				/* Try again with 0xdc..0xdf zeroed, Windows might have
+				 * trashed it.
+				 */
+				*(u32 *)(&bh->b_data[0xdc]) = 0;
+				if (checksum_block((u32 *)bh->b_data,
+						be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F)) {
+					brelse(bh);
+					printk("Dev %s: RDB in block %d has bad checksum\n",
+					       kdevname(dev),blk);
+					continue;
+				}
+				printk("Warning: Trashed word at 0xd0 in block %d "
+					"ignored in checksum calculation\n",blk);
+			}
+			printk(" RDSK");
+			blk = be32_to_cpu(rdb->rdb_PartitionList);
+			brelse(bh);
+			for (part = 1; blk > 0 && part <= 16; part++) {
+				if (!(bh = bread(dev,blk,blocksize))) {
+					printk("Dev %s: unable to read partition block %d\n",
+						       kdevname(dev),blk);
+					goto rdb_done;
+				}
+				pb  = (struct PartitionBlock *)bh->b_data;
+				blk = be32_to_cpu(pb->pb_Next);
+				if (pb->pb_ID == cpu_to_be32(IDNAME_PARTITION) && checksum_block(
+				    (u32 *)pb,be32_to_cpu(pb->pb_SummedLongs) & 0x7F) == 0 ) {
+
+					/* Tell Kernel about it */
+
+					if (!(nr_sects = (be32_to_cpu(pb->pb_Environment[10]) + 1 -
+							  be32_to_cpu(pb->pb_Environment[9])) *
+							 be32_to_cpu(pb->pb_Environment[3]) *
+							 be32_to_cpu(pb->pb_Environment[5]))) {
+						brelse(bh);
+						continue;
+ 					}
+					start_sect = be32_to_cpu(pb->pb_Environment[9]) *
+						     be32_to_cpu(pb->pb_Environment[3]) *
+						     be32_to_cpu(pb->pb_Environment[5]);
+					add_gd_partition(hd,first_part_minor,start_sect,nr_sects);
+					first_part_minor++;
+					res = 1;
+				}
+				brelse(bh);
+			}
+			printk("\n");
+			break;
+		}
+		else
+			brelse(bh);
+	}
+
+rdb_done:
+	set_blocksize(dev,old_blocksize);
+	return res;
+}
diff -u --recursive --new-file v2.3.13/linux/fs/partitions/amiga.h linux/fs/partitions/amiga.h
--- v2.3.13/linux/fs/partitions/amiga.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/partitions/amiga.h	Thu Aug 12 12:26:06 1999
@@ -0,0 +1,8 @@
+/*
+ *  fs/partitions/amiga.h
+ */
+
+int
+amiga_partition(struct gendisk *hd, kdev_t dev,
+		unsigned long first_sector, int first_part_minor);
+
diff -u --recursive --new-file v2.3.13/linux/fs/partitions/atari.c linux/fs/partitions/atari.c
--- v2.3.13/linux/fs/partitions/atari.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/partitions/atari.c	Thu Aug 12 12:26:06 1999
@@ -0,0 +1,163 @@
+/*
+ *  fs/partitions/atari.c
+ *
+ *  Code extracted from drivers/block/genhd.c
+ *
+ *  Copyright (C) 1991-1998  Linus Torvalds
+ *  Re-organised Feb 1998 Russell King
+ */
+
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/blk.h>
+
+#include <asm/system.h>
+
+#include "check.h"
+#include "atari.h"
+
+/* ++guenther: this should be settable by the user ("make config")?.
+ */
+#define ICD_PARTS
+
+int atari_partition (struct gendisk *hd, kdev_t dev,
+		     unsigned long first_sector, int first_part_minor)
+{
+  int minor = first_part_minor, m_lim = first_part_minor + hd->max_p;
+  struct buffer_head *bh;
+  struct rootsector *rs;
+  struct partition_info *pi;
+  ulong extensect;
+  unsigned int psum;
+  int i;
+#ifdef ICD_PARTS
+  int part_fmt = 0; /* 0:unknown, 1:AHDI, 2:ICD/Supra */
+#endif
+
+  bh = bread (dev, 0, get_ptable_blocksize(dev));
+  if (!bh) {
+      printk (" unable to read block 0 (partition table)\n");
+      return -1;
+  }
+
+  /* Verify this is an Atari rootsector: */
+  psum = 0;
+  for (i=0;i<256;i++) {
+    psum+=ntohs(((__u16 *) (bh->b_data))[i]);
+  }
+  if ((psum & 0xFFFF) != 0x1234) {
+    brelse(bh);
+    return 0;
+  }
+
+  rs = (struct rootsector *) bh->b_data;
+  pi = &rs->part[0];
+  printk (" AHDI");
+  for (; pi < &rs->part[4] && minor < m_lim; minor++, pi++)
+    {
+      if (pi->flg & 1)
+	/* active partition */
+	{
+	  if (memcmp (pi->id, "XGM", 3) == 0)
+	    /* extension partition */
+	    {
+	      struct rootsector *xrs;
+	      struct buffer_head *xbh;
+	      ulong partsect;
+
+#ifdef ICD_PARTS
+	      part_fmt = 1;
+#endif
+	      printk(" XGM<");
+	      partsect = extensect = ntohl(pi->st);
+	      while (1)
+		{
+		  xbh = bread (dev, partsect / 2, get_ptable_blocksize(dev));
+		  if (!xbh)
+		    {
+		      printk (" block %ld read failed\n", partsect);
+		      brelse(bh);
+		      return 0;
+		    }
+		  if (partsect & 1)
+		    xrs = (struct rootsector *) &xbh->b_data[512];
+		  else
+		    xrs = (struct rootsector *) &xbh->b_data[0];
+
+		  /* ++roman: sanity check: bit 0 of flg field must be set */
+		  if (!(xrs->part[0].flg & 1)) {
+		    printk( "\nFirst sub-partition in extended partition is not valid!\n" );
+		    break;
+		  }
+
+		  add_gd_partition(hd, minor, partsect + ntohl(xrs->part[0].st),
+				ntohl(xrs->part[0].siz));
+
+		  if (!(xrs->part[1].flg & 1)) {
+		    /* end of linked partition list */
+		    brelse( xbh );
+		    break;
+		  }
+		  if (memcmp( xrs->part[1].id, "XGM", 3 ) != 0) {
+		    printk( "\nID of extended partition is not XGM!\n" );
+		    brelse( xbh );
+		    break;
+		  }
+
+		  partsect = ntohl(xrs->part[1].st) + extensect;
+		  brelse (xbh);
+		  minor++;
+		  if (minor >= m_lim) {
+		    printk( "\nMaximum number of partitions reached!\n" );
+		    break;
+		  }
+		}
+	      printk(" >");
+	    }
+	  else
+	    {
+	      /* we don't care about other id's */
+	      add_gd_partition (hd, minor, ntohl(pi->st), ntohl(pi->siz));
+	    }
+	}
+    }
+#ifdef ICD_PARTS
+  if ( part_fmt!=1 ) /* no extended partitions -> test ICD-format */
+  {
+    pi = &rs->icdpart[0];
+    /* sanity check: no ICD format if first partition invalid */
+    if (memcmp (pi->id, "GEM", 3) == 0 ||
+        memcmp (pi->id, "BGM", 3) == 0 ||
+        memcmp (pi->id, "LNX", 3) == 0 ||
+        memcmp (pi->id, "SWP", 3) == 0 ||
+        memcmp (pi->id, "RAW", 3) == 0 )
+    {
+      printk(" ICD<");
+      for (; pi < &rs->icdpart[8] && minor < m_lim; minor++, pi++)
+      {
+        /* accept only GEM,BGM,RAW,LNX,SWP partitions */
+        if (pi->flg & 1 && 
+            (memcmp (pi->id, "GEM", 3) == 0 ||
+             memcmp (pi->id, "BGM", 3) == 0 ||
+             memcmp (pi->id, "LNX", 3) == 0 ||
+             memcmp (pi->id, "SWP", 3) == 0 ||
+             memcmp (pi->id, "RAW", 3) == 0) )
+        {
+          part_fmt = 2;
+	  add_gd_partition (hd, minor, ntohl(pi->st), ntohl(pi->siz));
+        }
+      }
+      printk(" >");
+    }
+  }
+#endif
+  brelse (bh);
+
+  printk ("\n");
+
+  return 1;
+}
+
diff -u --recursive --new-file v2.3.13/linux/fs/partitions/atari.h linux/fs/partitions/atari.h
--- v2.3.13/linux/fs/partitions/atari.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/partitions/atari.h	Thu Aug 12 12:26:06 1999
@@ -0,0 +1,36 @@
+/*
+ *  fs/partitions/atari.h
+ *  Moved by Russell King from:
+ *
+ * linux/include/linux/atari_rootsec.h
+ * definitions for Atari Rootsector layout
+ * by Andreas Schwab (schwab@ls5.informatik.uni-dortmund.de)
+ *
+ * modified for ICD/Supra partitioning scheme restricted to at most 12
+ * partitions
+ * by Guenther Kelleter (guenther@pool.informatik.rwth-aachen.de)
+ */
+
+struct partition_info
+{
+  u_char flg;			/* bit 0: active; bit 7: bootable */
+  char id[3];			/* "GEM", "BGM", "XGM", or other */
+  u_long st;			/* start of partition */
+  u_long siz;			/* length of partition */
+};
+
+struct rootsector
+{
+  char unused[0x156];		/* room for boot code */
+  struct partition_info icdpart[8];	/* info for ICD-partitions 5..12 */
+  char unused2[0xc];
+  u_long hd_siz;		/* size of disk in blocks */
+  struct partition_info part[4];
+  u_long bsl_st;		/* start of bad sector list */
+  u_long bsl_cnt;		/* length of bad sector list */
+  u_short checksum;		/* checksum for bootable disks */
+} __attribute__((__packed__));
+
+int atari_partition (struct gendisk *hd, kdev_t dev,
+		     unsigned long first_sector, int first_part_minor);
+
diff -u --recursive --new-file v2.3.13/linux/fs/partitions/check.c linux/fs/partitions/check.c
--- v2.3.13/linux/fs/partitions/check.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/partitions/check.c	Wed Aug 18 09:38:29 1999
@@ -0,0 +1,324 @@
+/*
+ *  Code extracted from drivers/block/genhd.c
+ *  Copyright (C) 1991-1998  Linus Torvalds
+ *  Re-organised Feb 1998 Russell King
+ *
+ *  We now have independent partition support from the
+ *  block drivers, which allows all the partition code to
+ *  be grouped in one location, and it to be mostly self
+ *  contained.
+ *
+ *  Added needed MAJORS for new pairs, {hdi,hdj}, {hdk,hdl}
+ */
+
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/blk.h>
+#include <linux/init.h>
+
+#include "check.h"
+
+#include "acorn.h"
+#include "amiga.h"
+#include "atari.h"
+#include "mac.h"
+#include "msdos.h"
+#include "osf.h"
+#include "sgi.h"
+#include "sun.h"
+
+extern void device_init(void);
+extern void md_setup_drive(void);
+extern int *blk_size[];
+extern void rd_load(void);
+extern void initrd_load(void);
+
+struct gendisk *gendisk_head;
+
+static int (*check_part[])(struct gendisk *hd, kdev_t dev, unsigned long first_sect, int first_minor) = {
+#ifdef CONFIG_ACORN_PARTITION
+	acorn_partition,
+#endif
+#ifdef CONFIG_MSDOS_PARTITION
+	msdos_partition,
+#endif
+#ifdef CONFIG_OSF_PARTITION
+	osf_partition,
+#endif
+#ifdef CONFIG_SUN_PARTITION
+	sun_partition,
+#endif
+#ifdef CONFIG_AMIGA_PARTITION
+	amiga_partition,
+#endif
+#ifdef CONFIG_ATARI_PARTITION
+	atari_partition,
+#endif
+#ifdef CONFIG_MAC_PARTITION
+	mac_partition,
+#endif
+#ifdef CONFIG_SGI_PARTITION
+	sgi_partition,
+#endif
+#ifdef CONFIG_ULTRIX_PARTITION
+	ultrix_partition,
+#endif
+	NULL
+};
+
+/*
+ * disk_name() is used by genhd.c and blkpg.c.
+ * It formats the devicename of the indicated disk into
+ * the supplied buffer (of size at least 32), and returns
+ * a pointer to that same buffer (for convenience).
+ */
+char *disk_name (struct gendisk *hd, int minor, char *buf)
+{
+	unsigned int part;
+	const char *maj = hd->major_name;
+	int unit = (minor >> hd->minor_shift) + 'a';
+
+	/*
+	 * IDE devices use multiple major numbers, but the drives
+	 * are named as:  {hda,hdb}, {hdc,hdd}, {hde,hdf}, {hdg,hdh}..
+	 * This requires special handling here.
+	 */
+	switch (hd->major) {
+		case IDE9_MAJOR:
+			unit += 2;
+		case IDE8_MAJOR:
+			unit += 2;
+		case IDE7_MAJOR:
+			unit += 2;
+		case IDE6_MAJOR:
+			unit += 2;
+		case IDE5_MAJOR:
+			unit += 2;
+		case IDE4_MAJOR:
+			unit += 2;
+		case IDE3_MAJOR:
+			unit += 2;
+		case IDE2_MAJOR:
+			unit += 2;
+		case IDE1_MAJOR:
+			unit += 2;
+		case IDE0_MAJOR:
+			maj = "hd";
+			break;
+	}
+	part = minor & ((1 << hd->minor_shift) - 1);
+	if (hd->major >= SCSI_DISK1_MAJOR && hd->major <= SCSI_DISK7_MAJOR) {
+		unit = unit + (hd->major - SCSI_DISK1_MAJOR + 1) * 16;
+		if (unit > 'z') {
+			unit -= 'z' + 1;
+			sprintf(buf, "sd%c%c", 'a' + unit / 26, 'a' + unit % 26);
+			if (part)
+				sprintf(buf + 4, "%d", part);
+			return buf;
+		}
+	}
+	if (hd->major >= COMPAQ_SMART2_MAJOR && hd->major <= COMPAQ_SMART2_MAJOR+7) {
+		int ctlr = hd->major - COMPAQ_SMART2_MAJOR;
+ 		int disk = minor >> hd->minor_shift;
+ 		int part = minor & (( 1 << hd->minor_shift) - 1);
+ 		if (part == 0)
+ 			sprintf(buf, "%s/c%dd%d", maj, ctlr, disk);
+ 		else
+ 			sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, disk, part);
+ 		return buf;
+ 	}
+	if (part)
+		sprintf(buf, "%s%c%d", maj, unit, part);
+	else
+		sprintf(buf, "%s%c", maj, unit);
+	return buf;
+}
+
+/*
+ * Add a partitions details to the devices partition description.
+ */
+void add_gd_partition(struct gendisk *hd, int minor, int start, int size)
+{
+	char buf[40];
+	hd->part[minor].start_sect = start;
+	hd->part[minor].nr_sects   = size;
+	if (hd->major >= COMPAQ_SMART2_MAJOR+0 && hd->major <= COMPAQ_SMART2_MAJOR+7)
+		printk(" p%d", (minor & ((1 << hd->minor_shift) - 1)));
+	else
+		printk(" %s", disk_name(hd, minor, buf));
+}
+
+int get_hardsect_size(kdev_t dev)
+{
+	if (hardsect_size[MAJOR(dev)] != NULL)
+		return hardsect_size[MAJOR(dev)][MINOR(dev)];
+	else
+		return 512;
+}
+
+unsigned int get_ptable_blocksize(kdev_t dev)
+{
+	int ret = 1024;
+
+	/*
+	 * See whether the low-level driver has given us a minumum blocksize.
+	 * If so, check to see whether it is larger than the default of 1024.
+	 */
+	if (!blksize_size[MAJOR(dev)])
+		return ret;
+
+	/*
+	 * Check for certain special power of two sizes that we allow.
+	 * With anything larger than 1024, we must force the blocksize up to
+	 * the natural blocksize for the device so that we don't have to try
+	 * and read partial sectors.  Anything smaller should be just fine.
+	 */
+
+	switch (blksize_size[MAJOR(dev)][MINOR(dev)]) {
+		case 2048:
+			ret = 2048;
+			break;
+		case 4096:
+			ret = 4096;
+			break;
+		case 8192:
+			ret = 8192;
+			break;
+		case 1024:
+		case 512:
+		case 256:
+		case 0:
+			/*
+			 * These are all OK.
+			 */
+			break;
+		default:
+			panic("Strange blocksize for partition table\n");
+	}
+
+	return ret;
+}
+
+#ifdef CONFIG_PROC_FS
+int get_partition_list(char * page)
+{
+	struct gendisk *p;
+	char buf[40];
+	int n, len;
+
+	len = sprintf(page, "major minor  #blocks  name\n\n");
+	for (p = gendisk_head; p; p = p->next) {
+		for (n=0; n < (p->nr_real << p->minor_shift); n++) {
+			if (p->part[n].nr_sects && len < PAGE_SIZE - 80) {
+				len += sprintf(page+len,
+					       "%4d  %4d %10d %s\n",
+					       p->major, n, p->sizes[n],
+					       disk_name(p, n, buf));
+			}
+		}
+	}
+	return len;
+}
+#endif
+
+void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor)
+{
+	static int first_time = 1;
+	unsigned long first_sector;
+	char buf[40];
+	int i;
+
+	if (first_time)
+		printk(KERN_INFO "Partition check:\n");
+	first_time = 0;
+	first_sector = hd->part[MINOR(dev)].start_sect;
+
+	/*
+	 * This is a kludge to allow the partition check to be
+	 * skipped for specific drives (e.g. IDE CD-ROM drives)
+	 */
+	if ((int)first_sector == -1) {
+		hd->part[MINOR(dev)].start_sect = 0;
+		return;
+	}
+
+	printk(KERN_INFO " %s:", disk_name(hd, MINOR(dev), buf));
+	for (i = 0; check_part[i]; i++)
+		if (check_part[i](hd, dev, first_sector, first_part_minor))
+			return;
+
+	printk(" unknown partition table\n");
+}
+
+/*
+ * This function will re-read the partition tables for a given device,
+ * and set things back up again.  There are some important caveats,
+ * however.  You must ensure that no one is using the device, and no one
+ * can start using the device while this function is being executed.
+ *
+ * Much of the cleanup from the old partition tables should have already been
+ * done
+ */
+void resetup_one_dev(struct gendisk *dev, int drive)
+{
+	int i;
+	int first_minor	= drive << dev->minor_shift;
+	int end_minor	= first_minor + dev->max_p;
+
+	blk_size[dev->major] = NULL;
+	check_partition(dev, MKDEV(dev->major, first_minor), 1 + first_minor);
+
+ 	/*
+ 	 * We need to set the sizes array before we will be able to access
+ 	 * any of the partitions on this device.
+ 	 */
+	if (dev->sizes != NULL) {	/* optional safeguard in ll_rw_blk.c */
+		for (i = first_minor; i < end_minor; i++)
+			dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
+		blk_size[dev->major] = dev->sizes;
+	}
+}
+
+static inline void setup_dev(struct gendisk *dev)
+{
+	int i, drive;
+	int end_minor	= dev->max_nr * dev->max_p;
+
+	blk_size[dev->major] = NULL;
+	for (i = 0; i < end_minor; i++) {
+		dev->part[i].start_sect = 0;
+		dev->part[i].nr_sects = 0;
+		dev->sizes[i] = 0;
+	}
+	dev->init(dev);	
+	for (drive = 0 ; drive < dev->nr_real ; drive++)
+		resetup_one_dev(dev, drive);
+}
+
+int __init partition_setup(void)
+{
+	struct gendisk *p;
+
+	device_init();
+
+	for (p = gendisk_head ; p ; p=p->next)
+		setup_dev(p);
+
+#ifdef CONFIG_BLK_DEV_RAM
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start && mount_initrd) initrd_load();
+	else
+#endif
+	rd_load();
+#endif
+#ifdef CONFIG_MD_BOOT
+	md_setup_drive();
+#endif
+
+	return 0;
+}
+
+__initcall(partition_setup);
diff -u --recursive --new-file v2.3.13/linux/fs/partitions/check.h linux/fs/partitions/check.h
--- v2.3.13/linux/fs/partitions/check.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/partitions/check.h	Thu Aug 12 12:26:06 1999
@@ -0,0 +1,10 @@
+/*
+ * add_partition adds a partitions details to the devices partition
+ * description.
+ */
+void add_gd_partition(struct gendisk *hd, int minor, int start, int size);
+
+/*
+ * Get the default block size for this device
+ */
+unsigned int get_ptable_blocksize(kdev_t dev);
diff -u --recursive --new-file v2.3.13/linux/fs/partitions/mac.c linux/fs/partitions/mac.c
--- v2.3.13/linux/fs/partitions/mac.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/partitions/mac.c	Thu Aug 12 12:26:06 1999
@@ -0,0 +1,110 @@
+/*
+ *  fs/partitions/msdos.c
+ *
+ *  Code extracted from drivers/block/genhd.c
+ *  Copyright (C) 1991-1998  Linus Torvalds
+ *  Re-organised Feb 1998 Russell King
+ */
+
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/blk.h>
+#include <linux/ctype.h>
+
+#include <asm/system.h>
+
+#include "check.h"
+#include "mac.h"
+
+#ifdef CONFIG_PPC
+extern void note_bootable_part(kdev_t dev, int part);
+#endif
+
+/*
+ * Code to understand MacOS partition tables.
+ */
+
+int mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec, int first_part_minor)
+{
+	struct buffer_head *bh;
+	int blk, blocks_in_map;
+	int dev_bsize, dev_pos, pos;
+	unsigned secsize;
+#ifdef CONFIG_PPC
+	int first_bootable = 1;
+#endif
+	struct mac_partition *part;
+	struct mac_driver_desc *md;
+
+	dev_bsize = get_ptable_blocksize(dev);
+	dev_pos = 0;
+	/* Get 0th block and look at the first partition map entry. */
+	if ((bh = bread(dev, 0, dev_bsize)) == 0) {
+	    printk("%s: error reading partition table\n",
+		   kdevname(dev));
+	    return -1;
+	}
+	md = (struct mac_driver_desc *) bh->b_data;
+	if (be16_to_cpu(md->signature) != MAC_DRIVER_MAGIC) {
+		brelse(bh);
+		return 0;
+	}
+	secsize = be16_to_cpu(md->block_size);
+	if (secsize >= dev_bsize) {
+		brelse(bh);
+		dev_pos = secsize;
+		if ((bh = bread(dev, secsize/dev_bsize, dev_bsize)) == 0) {
+			printk("%s: error reading partition table\n",
+			       kdevname(dev));
+			return -1;
+		}
+	}
+	part = (struct mac_partition *) (bh->b_data + secsize - dev_pos);
+	if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) {
+		brelse(bh);
+		return 0;		/* not a MacOS disk */
+	}
+	blocks_in_map = be32_to_cpu(part->map_count);
+	for (blk = 1; blk <= blocks_in_map; ++blk) {
+		pos = blk * secsize;
+		if (pos >= dev_pos + dev_bsize) {
+			brelse(bh);
+			dev_pos = pos;
+			if ((bh = bread(dev, pos/dev_bsize, dev_bsize)) == 0) {
+				printk("%s: error reading partition table\n",
+				       kdevname(dev));
+				return -1;
+			}
+		}
+		part = (struct mac_partition *) (bh->b_data + pos - dev_pos);
+		if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC)
+			break;
+		blocks_in_map = be32_to_cpu(part->map_count);
+		add_gd_partition(hd, first_part_minor,
+			fsec + be32_to_cpu(part->start_block) * (secsize/512),
+			be32_to_cpu(part->block_count) * (secsize/512));
+
+#ifdef CONFIG_PPC
+		/*
+		 * If this is the first bootable partition, tell the
+		 * setup code, in case it wants to make this the root.
+		 */
+		if ( (_machine == _MACH_Pmac) && first_bootable
+		    && (be32_to_cpu(part->status) & MAC_STATUS_BOOTABLE)
+		    && strcasecmp(part->processor, "powerpc") == 0) {
+			note_bootable_part(dev, blk);
+			first_bootable = 0;
+		}
+#endif /* CONFIG_PPC */
+
+		++first_part_minor;
+	}
+	brelse(bh);
+	printk("\n");
+	return 1;
+}
+
diff -u --recursive --new-file v2.3.13/linux/fs/partitions/mac.h linux/fs/partitions/mac.h
--- v2.3.13/linux/fs/partitions/mac.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/partitions/mac.h	Thu Aug 12 12:26:06 1999
@@ -0,0 +1,44 @@
+/*
+ *  fs/partitions/mac.h
+ */
+
+#define MAC_PARTITION_MAGIC	0x504d
+
+/* type field value for A/UX or other Unix partitions */
+#define APPLE_AUX_TYPE	"Apple_UNIX_SVR2"
+
+struct mac_partition {
+	__u16	signature;	/* expected to be MAC_PARTITION_MAGIC */
+	__u16	res1;
+	__u32	map_count;	/* # blocks in partition map */
+	__u32	start_block;	/* absolute starting block # of partition */
+	__u32	block_count;	/* number of blocks in partition */
+	char	name[32];	/* partition name */
+	char	type[32];	/* string type description */
+	__u32	data_start;	/* rel block # of first data block */
+	__u32	data_count;	/* number of data blocks */
+	__u32	status;		/* partition status bits */
+	__u32	boot_start;
+	__u32	boot_size;
+	__u32	boot_load;
+	__u32	boot_load2;
+	__u32	boot_entry;
+	__u32	boot_entry2;
+	__u32	boot_cksum;
+	char	processor[16];	/* identifies ISA of boot */
+	/* there is more stuff after this that we don't need */
+};
+
+#define MAC_STATUS_BOOTABLE	8	/* partition is bootable */
+
+#define MAC_DRIVER_MAGIC	0x4552
+
+/* Driver descriptor structure, in block 0 */
+struct mac_driver_desc {
+	__u16	signature;	/* expected to be MAC_DRIVER_MAGIC */
+	__u16	block_size;
+	__u32	block_count;
+    /* ... more stuff */
+};
+
+int mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec, int first_part_minor);
diff -u --recursive --new-file v2.3.13/linux/fs/partitions/msdos.c linux/fs/partitions/msdos.c
--- v2.3.13/linux/fs/partitions/msdos.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/partitions/msdos.c	Thu Aug 12 12:26:06 1999
@@ -0,0 +1,494 @@
+/*
+ *  fs/partitions/msdos.c
+ *
+ *  Code extracted from drivers/block/genhd.c
+ *  Copyright (C) 1991-1998  Linus Torvalds
+ *
+ *  Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
+ *  in the early extended-partition checks and added DM partitions
+ *
+ *  Support for DiskManager v6.0x added by Mark Lord,
+ *  with information provided by OnTrack.  This now works for linux fdisk
+ *  and LILO, as well as loadlin and bootln.  Note that disks other than
+ *  /dev/hda *must* have a "DOS" type 0x51 partition in the first slot (hda1).
+ *
+ *  More flexible handling of extended partitions - aeb, 950831
+ *
+ *  Check partition table on IDE disks for common CHS translations
+ *
+ *  Re-organised Feb 1998 Russell King
+ */
+
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/blk.h>
+
+#include <asm/system.h>
+
+#include "check.h"
+#include "msdos.h"
+
+static int current_minor;
+
+/*
+ * Many architectures don't like unaligned accesses, which is
+ * frequently the case with the nr_sects and start_sect partition
+ * table entries.
+ */
+#include <asm/unaligned.h>
+
+#define SYS_IND(p)	(get_unaligned(&p->sys_ind))
+#define NR_SECTS(p)	({ __typeof__(p->nr_sects) __a =	\
+				get_unaligned(&p->nr_sects);	\
+				le32_to_cpu(__a); \
+			})
+
+#define START_SECT(p)	({ __typeof__(p->start_sect) __a =	\
+				get_unaligned(&p->start_sect);	\
+				le32_to_cpu(__a); \
+			})
+
+static inline int is_extended_partition(struct partition *p)
+{
+	return (SYS_IND(p) == DOS_EXTENDED_PARTITION ||
+		SYS_IND(p) == WIN98_EXTENDED_PARTITION ||
+		SYS_IND(p) == LINUX_EXTENDED_PARTITION);
+}
+
+/*
+ * Create devices for each logical partition in an extended partition.
+ * The logical partitions form a linked list, with each entry being
+ * a partition table with two entries.  The first entry
+ * is the real data partition (with a start relative to the partition
+ * table start).  The second is a pointer to the next logical partition
+ * (with a start relative to the entire extended partition).
+ * We do not create a Linux partition for the partition tables, but
+ * only for the actual data partitions.
+ */
+
+static void extended_partition(struct gendisk *hd, kdev_t dev)
+{
+	struct buffer_head *bh;
+	struct partition *p;
+	unsigned long first_sector, first_size, this_sector, this_size;
+	int mask = (1 << hd->minor_shift) - 1;
+	int sector_size = get_hardsect_size(dev) / 512;
+	int i;
+
+	first_sector = hd->part[MINOR(dev)].start_sect;
+	first_size = hd->part[MINOR(dev)].nr_sects;
+	this_sector = first_sector;
+
+	while (1) {
+		if ((current_minor & mask) == 0)
+			return;
+		if (!(bh = bread(dev,0,get_ptable_blocksize(dev))))
+			return;
+
+		if ((*(__u16 *) (bh->b_data+510)) != cpu_to_le16(MSDOS_LABEL_MAGIC))
+			goto done;
+
+		p = (struct partition *) (0x1BE + bh->b_data);
+
+		this_size = hd->part[MINOR(dev)].nr_sects;
+
+		/*
+		 * Usually, the first entry is the real data partition,
+		 * the 2nd entry is the next extended partition, or empty,
+		 * and the 3rd and 4th entries are unused.
+		 * However, DRDOS sometimes has the extended partition as
+		 * the first entry (when the data partition is empty),
+		 * and OS/2 seems to use all four entries.
+		 */
+
+		/* 
+		 * First process the data partition(s)
+		 */
+		for (i=0; i<4; i++, p++) {
+			if (!NR_SECTS(p) || is_extended_partition(p))
+				continue;
+
+			/* Check the 3rd and 4th entries -
+			   these sometimes contain random garbage */
+			if (i >= 2
+				&& START_SECT(p) + NR_SECTS(p) > this_size
+				&& (this_sector + START_SECT(p) < first_sector ||
+				    this_sector + START_SECT(p) + NR_SECTS(p) >
+				     first_sector + first_size))
+				continue;
+
+			add_gd_partition(hd, current_minor, this_sector+START_SECT(p)*sector_size, NR_SECTS(p)*sector_size);
+			current_minor++;
+			if ((current_minor & mask) == 0)
+				goto done;
+		}
+		/*
+		 * Next, process the (first) extended partition, if present.
+		 * (So far, there seems to be no reason to make
+		 *  extended_partition()  recursive and allow a tree
+		 *  of extended partitions.)
+		 * It should be a link to the next logical partition.
+		 * Create a minor for this just long enough to get the next
+		 * partition table.  The minor will be reused for the next
+		 * data partition.
+		 */
+		p -= 4;
+		for (i=0; i<4; i++, p++)
+			if(NR_SECTS(p) && is_extended_partition(p))
+				break;
+		if (i == 4)
+			goto done;	 /* nothing left to do */
+
+		hd->part[current_minor].nr_sects = NR_SECTS(p) * sector_size; /* JSt */
+		hd->part[current_minor].start_sect = first_sector + START_SECT(p) * sector_size;
+		this_sector = first_sector + START_SECT(p) * sector_size;
+		dev = MKDEV(hd->major, current_minor);
+
+		/* Use bforget(), as we have changed the disk geometry */
+		bforget(bh);
+	}
+done:
+	bforget(bh);
+}
+
+#ifdef CONFIG_SOLARIS_X86_PARTITION
+static void
+solaris_x86_partition(struct gendisk *hd, kdev_t dev, long offset) {
+
+	struct buffer_head *bh;
+	struct solaris_x86_vtoc *v;
+	struct solaris_x86_slice *s;
+	int i;
+
+	if(!(bh = bread(dev, 0, get_ptable_blocksize(dev))))
+		return;
+	v = (struct solaris_x86_vtoc *)(bh->b_data + 512);
+	if(v->v_sanity != SOLARIS_X86_VTOC_SANE) {
+		brelse(bh);
+		return;
+	}
+	printk(" <solaris:");
+	if(v->v_version != 1) {
+		printk("  cannot handle version %ld vtoc>", v->v_version);
+		brelse(bh);
+		return;
+	}
+	for(i=0; i<SOLARIS_X86_NUMSLICE; i++) {
+		s = &v->v_slice[i];
+
+		if (s->s_size == 0)
+			continue;
+		printk(" [s%d]", i);
+		/* solaris partitions are relative to current MS-DOS
+		 * one but add_gd_partition starts relative to sector
+		 * zero of the disk.  Therefore, must add the offset
+		 * of the current partition */
+		add_gd_partition(hd, current_minor, s->s_start+offset, s->s_size);
+		current_minor++;
+	}
+	brelse(bh);
+	printk(" >");
+}
+#endif
+
+#ifdef CONFIG_BSD_DISKLABEL
+static void check_and_add_bsd_partition(struct gendisk *hd,
+					struct bsd_partition *bsd_p, kdev_t dev)
+{
+	struct hd_struct *lin_p;
+		/* check relative position of partitions.  */
+	for (lin_p = hd->part + 1 + MINOR(dev);
+	     lin_p - hd->part - MINOR(dev) < current_minor; lin_p++) {
+			/* no relationship -> try again */
+		if (lin_p->start_sect + lin_p->nr_sects <= bsd_p->p_offset 
+			|| lin_p->start_sect >= bsd_p->p_offset + bsd_p->p_size)
+			continue;	
+			/* equal -> no need to add */
+		if (lin_p->start_sect == bsd_p->p_offset && 
+			lin_p->nr_sects == bsd_p->p_size) 
+			return;
+			/* bsd living within dos partition */
+		if (lin_p->start_sect <= bsd_p->p_offset && lin_p->start_sect 
+			+ lin_p->nr_sects >= bsd_p->p_offset + bsd_p->p_size) {
+#ifdef DEBUG_BSD_DISKLABEL
+			printk("w: %d %ld+%ld,%d+%d", 
+				lin_p - hd->part, 
+				lin_p->start_sect, lin_p->nr_sects, 
+				bsd_p->p_offset, bsd_p->p_size);
+#endif
+			break;
+		}
+	 /* ouch: bsd and linux overlap. Don't even try for that partition */
+#ifdef DEBUG_BSD_DISKLABEL
+		printk("???: %d %ld+%ld,%d+%d",
+			lin_p - hd->part, lin_p->start_sect, lin_p->nr_sects,
+			bsd_p->p_offset, bsd_p->p_size);
+#endif
+		printk("???");
+		return;
+	} /* if the bsd partition is not currently known to linux, we end
+	   * up here 
+	   */
+	add_gd_partition(hd, current_minor, bsd_p->p_offset, bsd_p->p_size);
+	current_minor++;
+}
+/* 
+ * Create devices for BSD partitions listed in a disklabel, under a
+ * dos-like partition. See extended_partition() for more information.
+ */
+static void bsd_disklabel_partition(struct gendisk *hd, kdev_t dev, 
+   int max_partitions)
+{
+	struct buffer_head *bh;
+	struct bsd_disklabel *l;
+	struct bsd_partition *p;
+	int mask = (1 << hd->minor_shift) - 1;
+
+	if (!(bh = bread(dev,0,get_ptable_blocksize(dev))))
+		return;
+	l = (struct bsd_disklabel *) (bh->b_data+512);
+	if (l->d_magic != BSD_DISKMAGIC) {
+		brelse(bh);
+		return;
+	}
+
+	if (l->d_npartitions < max_partitions)
+		max_partitions = l->d_npartitions;
+	for (p = l->d_partitions; p - l->d_partitions <  max_partitions; p++) {
+		if ((current_minor & mask) >= (4 + hd->max_p))
+			break;
+
+		if (p->p_fstype != BSD_FS_UNUSED) 
+			check_and_add_bsd_partition(hd, p, dev);
+	}
+
+	/* Use bforget(), as we have changed the disk setup */
+	bforget(bh);
+
+}
+#endif
+
+#ifdef CONFIG_UNIXWARE_DISKLABEL
+/*
+ * Create devices for Unixware partitions listed in a disklabel, under a
+ * dos-like partition. See extended_partition() for more information.
+ */
+static void unixware_partition(struct gendisk *hd, kdev_t dev)
+{
+	struct buffer_head *bh;
+	struct unixware_disklabel *l;
+	struct unixware_slice *p;
+	int mask = (1 << hd->minor_shift) - 1;
+
+	if (!(bh = bread(dev, 14, get_ptable_blocksize(dev))))
+		return;
+	l = (struct unixware_disklabel *) (bh->b_data+512);
+	if (le32_to_cpu(l->d_magic) != UNIXWARE_DISKMAGIC ||
+	    le32_to_cpu(l->vtoc.v_magic) != UNIXWARE_DISKMAGIC2) {
+		brelse(bh);
+		return;
+	}
+	printk(" <unixware:");
+	p = &l->vtoc.v_slice[1];
+	/* I omit the 0th slice as it is the same as whole disk. */
+	while (p - &l->vtoc.v_slice[0] < UNIXWARE_NUMSLICE) {
+		if ((current_minor & mask) == 0)
+			break;
+
+		if (p->s_label != UNIXWARE_FS_UNUSED) {
+			add_gd_partition(hd, current_minor, START_SECT(p), NR_SECTS(p));
+			current_minor++;
+		}
+		p++;
+	}
+	/* Use bforget, as we have changed the disk setup */
+	bforget(bh);
+	printk(" >");
+}
+#endif
+
+int msdos_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, int first_part_minor)
+{
+	int i, minor = current_minor = first_part_minor;
+	struct buffer_head *bh;
+	struct partition *p;
+	unsigned char *data;
+	int mask = (1 << hd->minor_shift) - 1;
+	int sector_size = get_hardsect_size(dev) / 512;
+#ifdef CONFIG_BSD_DISKLABEL
+	/* no bsd disklabel as a default */
+	kdev_t bsd_kdev = 0;
+	int bsd_maxpart = BSD_MAXPARTITIONS;
+#endif
+#ifdef CONFIG_BLK_DEV_IDE
+	int tested_for_xlate = 0;
+
+read_mbr:
+#endif
+	if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) {
+		printk(" unable to read partition table\n");
+		return -1;
+	}
+	data = bh->b_data;
+#ifdef CONFIG_BLK_DEV_IDE
+check_table:
+#endif
+	/* Use bforget(), because we have potentially changed the disk geometry */
+	if (*(unsigned short *)  (0x1fe + data) != cpu_to_le16(MSDOS_LABEL_MAGIC)) {
+		bforget(bh);
+		return 0;
+	}
+	p = (struct partition *) (0x1be + data);
+
+#ifdef CONFIG_BLK_DEV_IDE
+	if (!tested_for_xlate++) {	/* Do this only once per disk */
+		/*
+		 * Look for various forms of IDE disk geometry translation
+		 */
+		extern int ide_xlate_1024(kdev_t, int, const char *);
+		unsigned int sig = le16_to_cpu(*(unsigned short *)(data + 2));
+		if (SYS_IND(p) == EZD_PARTITION) {
+			/*
+			 * The remainder of the disk must be accessed using
+			 * a translated geometry that reduces the number of 
+			 * apparent cylinders to less than 1024 if possible.
+			 *
+			 * ide_xlate_1024() will take care of the necessary
+			 * adjustments to fool fdisk/LILO and partition check.
+			 */
+			if (ide_xlate_1024(dev, -1, " [EZD]")) {
+				data += 512;
+				goto check_table;
+			}
+		} else if (SYS_IND(p) == DM6_PARTITION) {
+
+			/*
+			 * Everything on the disk is offset by 63 sectors,
+			 * including a "new" MBR with its own partition table,
+			 * and the remainder of the disk must be accessed using
+			 * a translated geometry that reduces the number of 
+			 * apparent cylinders to less than 1024 if possible.
+			 *
+			 * ide_xlate_1024() will take care of the necessary
+			 * adjustments to fool fdisk/LILO and partition check.
+			 */
+			if (ide_xlate_1024(dev, 1, " [DM6:DDO]")) {
+				bforget(bh);
+				goto read_mbr;	/* start over with new MBR */
+			}
+		} else if (sig <= 0x1ae &&
+			   *(unsigned short *)(data + sig) == cpu_to_le16(0x55AA) &&
+			   (1 & *(unsigned char *)(data + sig + 2))) {
+			/* DM6 signature in MBR, courtesy of OnTrack */
+			(void) ide_xlate_1024 (dev, 0, " [DM6:MBR]");
+		} else if (SYS_IND(p) == DM6_AUX1PARTITION || SYS_IND(p) == DM6_AUX3PARTITION) {
+			/*
+			 * DM6 on other than the first (boot) drive
+			 */
+			(void) ide_xlate_1024(dev, 0, " [DM6:AUX]");
+		} else {
+			/*
+			 * Examine the partition table for common translations.
+			 * This is useful for drives in situations where the
+			 * translated geometry is unavailable from the BIOS.
+			 */
+			for (i = 0; i < 4; i++) {
+				struct partition *q = &p[i];
+				if (NR_SECTS(q)
+				   && (q->sector & 63) == 1
+				   && (q->end_sector & 63) == 63) {
+					unsigned int heads = q->end_head + 1;
+					if (heads == 32 || heads == 64 ||
+					    heads == 128 || heads == 240 ||
+					    heads == 255) {
+						(void) ide_xlate_1024(dev, heads, " [PTBL]");
+						break;
+					}
+				}
+			}
+		}
+	}
+#endif	/* CONFIG_BLK_DEV_IDE */
+
+	current_minor += 4;  /* first "extra" minor (for extended partitions) */
+	for (i=1 ; i<=4 ; minor++,i++,p++) {
+		if (!NR_SECTS(p))
+			continue;
+		add_gd_partition(hd, minor, first_sector+START_SECT(p)*sector_size, NR_SECTS(p)*sector_size);
+		if (is_extended_partition(p)) {
+			printk(" <");
+			/*
+			 * If we are rereading the partition table, we need
+			 * to set the size of the partition so that we will
+			 * be able to bread the block containing the extended
+			 * partition info.
+			 */
+			hd->sizes[minor] = hd->part[minor].nr_sects 
+			  	>> (BLOCK_SIZE_BITS - 9);
+			extended_partition(hd, MKDEV(hd->major, minor));
+			printk(" >");
+			/* prevent someone doing mkfs or mkswap on an
+			   extended partition, but leave room for LILO */
+			if (hd->part[minor].nr_sects > 2)
+				hd->part[minor].nr_sects = 2;
+		}
+#ifdef CONFIG_BSD_DISKLABEL
+			/* tag first disklabel for late recognition */
+		if (SYS_IND(p) == BSD_PARTITION || SYS_IND(p) == NETBSD_PARTITION) {
+			printk("!");
+			if (!bsd_kdev)
+				bsd_kdev = MKDEV(hd->major, minor);
+		} else if (SYS_IND(p) == OPENBSD_PARTITION) {
+			printk("!");
+			if (!bsd_kdev) {
+				bsd_kdev = MKDEV(hd->major, minor);
+				bsd_maxpart = OPENBSD_MAXPARTITIONS;
+			}
+		}
+#endif
+#ifdef CONFIG_UNIXWARE_DISKLABEL
+		if (SYS_IND(p) == UNIXWARE_PARTITION)
+			unixware_partition(hd, MKDEV(hd->major, minor));
+#endif
+#ifdef CONFIG_SOLARIS_X86_PARTITION
+
+		/* james@bpgc.com: Solaris has a nasty indicator: 0x82
+		 * which also means linux swap.  For that reason, all
+		 * of the prints are done inside the
+		 * solaris_x86_partition routine */
+
+		if(SYS_IND(p) == SOLARIS_X86_PARTITION) {
+			solaris_x86_partition(hd, MKDEV(hd->major, minor),
+					      first_sector+START_SECT(p));
+		}
+#endif
+	}
+#ifdef CONFIG_BSD_DISKLABEL
+	if (bsd_kdev) {
+		printk(" <");
+		bsd_disklabel_partition(hd, bsd_kdev, bsd_maxpart);
+		printk(" >");
+	}
+#endif
+	/*
+	 *  Check for old-style Disk Manager partition table
+	 */
+	if (*(unsigned short *) (data+0xfc) == cpu_to_le16(MSDOS_LABEL_MAGIC)) {
+		p = (struct partition *) (0x1be + data);
+		for (i = 4 ; i < 16 ; i++, current_minor++) {
+			p--;
+			if ((current_minor & mask) == 0)
+				break;
+			if (!(START_SECT(p) && NR_SECTS(p)))
+				continue;
+			add_gd_partition(hd, current_minor, START_SECT(p), NR_SECTS(p));
+		}
+	}
+	printk("\n");
+	bforget(bh);
+	return 1;
+}
diff -u --recursive --new-file v2.3.13/linux/fs/partitions/msdos.h linux/fs/partitions/msdos.h
--- v2.3.13/linux/fs/partitions/msdos.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/partitions/msdos.h	Thu Aug 12 12:26:06 1999
@@ -0,0 +1,9 @@
+/*
+ *  fs/partitions/msdos.h
+ */
+
+#define MSDOS_LABEL_MAGIC		0xAA55
+
+int msdos_partition(struct gendisk *hd, kdev_t dev,
+		    unsigned long first_sector, int first_part_minor);
+
diff -u --recursive --new-file v2.3.13/linux/fs/partitions/osf.c linux/fs/partitions/osf.c
--- v2.3.13/linux/fs/partitions/osf.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/partitions/osf.c	Thu Aug 12 12:26:06 1999
@@ -0,0 +1,86 @@
+/*
+ *  fs/partitions/osf.c
+ *
+ *  Code extracted from drivers/block/genhd.c
+ *
+ *  Copyright (C) 1991-1998  Linus Torvalds
+ *  Re-organised Feb 1998 Russell King
+ */
+
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/blk.h>
+
+#include "check.h"
+#include "osf.h"
+
+int osf_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector,
+		  int current_minor)
+{
+	int i;
+	int mask = (1 << hd->minor_shift) - 1;
+	struct buffer_head *bh;
+	struct disklabel {
+		u32 d_magic;
+		u16 d_type,d_subtype;
+		u8 d_typename[16];
+		u8 d_packname[16];
+		u32 d_secsize;
+		u32 d_nsectors;
+		u32 d_ntracks;
+		u32 d_ncylinders;
+		u32 d_secpercyl;
+		u32 d_secprtunit;
+		u16 d_sparespertrack;
+		u16 d_sparespercyl;
+		u32 d_acylinders;
+		u16 d_rpm, d_interleave, d_trackskew, d_cylskew;
+		u32 d_headswitch, d_trkseek, d_flags;
+		u32 d_drivedata[5];
+		u32 d_spare[5];
+		u32 d_magic2;
+		u16 d_checksum;
+		u16 d_npartitions;
+		u32 d_bbsize, d_sbsize;
+		struct d_partition {
+			u32 p_size;
+			u32 p_offset;
+			u32 p_fsize;
+			u8  p_fstype;
+			u8  p_frag;
+			u16 p_cpg;
+		} d_partitions[8];
+	} * label;
+	struct d_partition * partition;
+
+	if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) {
+		printk("unable to read partition table\n");
+		return -1;
+	}
+	label = (struct disklabel *) (bh->b_data+64);
+	partition = label->d_partitions;
+	if (label->d_magic != DISKLABELMAGIC) {
+		brelse(bh);
+		return 0;
+	}
+	if (label->d_magic2 != DISKLABELMAGIC) {
+		brelse(bh);
+		return 0;
+	}
+	for (i = 0 ; i < label->d_npartitions; i++, partition++) {
+		if ((current_minor & mask) == 0)
+		        break;
+		if (partition->p_size)
+			add_gd_partition(hd, current_minor,
+				first_sector+partition->p_offset,
+				partition->p_size);
+		current_minor++;
+	}
+	printk("\n");
+	brelse(bh);
+	return 1;
+}
+
diff -u --recursive --new-file v2.3.13/linux/fs/partitions/osf.h linux/fs/partitions/osf.h
--- v2.3.13/linux/fs/partitions/osf.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/partitions/osf.h	Thu Aug 12 12:26:06 1999
@@ -0,0 +1,9 @@
+/*
+ *  fs/partitions/osf.h
+ */
+
+#define DISKLABELMAGIC (0x82564557UL)
+
+int osf_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector,
+		  int current_minor);
+
diff -u --recursive --new-file v2.3.13/linux/fs/partitions/sgi.c linux/fs/partitions/sgi.c
--- v2.3.13/linux/fs/partitions/sgi.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/partitions/sgi.c	Thu Aug 12 12:26:06 1999
@@ -0,0 +1,86 @@
+/*
+ *  fs/partitions/sgi.c
+ *
+ *  Code extracted from drivers/block/genhd.c
+ */
+
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/blk.h>
+
+#include <asm/byteorder.h>
+#include <asm/system.h>
+
+#include "check.h"
+#include "sgi.h"
+
+int sgi_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, int first_part_minor)
+{
+	int i, csum, magic, current_minor = first_part_minor;
+	unsigned int *ui, start, blocks, cs;
+	struct buffer_head *bh;
+	struct sgi_disklabel {
+		int magic_mushroom;         /* Big fat spliff... */
+		short root_part_num;        /* Root partition number */
+		short swap_part_num;        /* Swap partition number */
+		char boot_file[16];         /* Name of boot file for ARCS */
+		unsigned char _unused0[48]; /* Device parameter useless crapola.. */
+		struct sgi_volume {
+			char name[8];       /* Name of volume */
+			int  block_num;     /* Logical block number */
+			int  num_bytes;     /* How big, in bytes */
+		} volume[15];
+		struct sgi_partition {
+			int num_blocks;     /* Size in logical blocks */
+			int first_block;    /* First logical block */
+			int type;           /* Type of this partition */
+		} partitions[16];
+		int csum;                   /* Disk label checksum */
+		int _unused1;               /* Padding */
+	} *label;
+	struct sgi_partition *p;
+
+	if(!(bh = bread(dev, 0, get_ptable_blocksize(dev)))) {
+		printk("Dev %s: unable to read partition table\n", kdevname(dev));
+		return -1;
+	}
+	label = (struct sgi_disklabel *) bh->b_data;
+	p = &label->partitions[0];
+	magic = label->magic_mushroom;
+	if(be32_to_cpu(magic) != SGI_LABEL_MAGIC) {
+		printk("Dev %s SGI disklabel: bad magic %08x\n",
+		       kdevname(dev), magic);
+		brelse(bh);
+		return 0;
+	}
+	ui = ((unsigned int *) (label + 1)) - 1;
+	for(csum = 0; ui >= ((unsigned int *) label);) {
+		cs = *ui--;
+		csum += be32_to_cpu(cs);
+	}
+	if(csum) {
+		printk("Dev %s SGI disklabel: csum bad, label corrupted\n",
+		       kdevname(dev));
+		brelse(bh);
+		return 0;
+	}
+	/* All SGI disk labels have 16 partitions, disks under Linux only
+	 * have 15 minor's.  Luckily there are always a few zero length
+	 * partitions which we don't care about so we never overflow the
+	 * current_minor.
+	 */
+	for(i = 0; i < 16; i++, p++) {
+		blocks = be32_to_cpu(p->num_blocks);
+		start  = be32_to_cpu(p->first_block);
+		if(!blocks)
+			continue;
+		add_gd_partition(hd, current_minor, start, blocks);
+		current_minor++;
+	}
+	printk("\n");
+	brelse(bh);
+	return 1;
+}
diff -u --recursive --new-file v2.3.13/linux/fs/partitions/sgi.h linux/fs/partitions/sgi.h
--- v2.3.13/linux/fs/partitions/sgi.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/partitions/sgi.h	Thu Aug 12 12:26:06 1999
@@ -0,0 +1,9 @@
+/*
+ *  fs/partitions/sgi.h
+ */
+
+extern int sgi_partition(struct gendisk *hd, kdev_t dev,
+	 unsigned long first_sector, int first_part_minor);
+
+#define SGI_LABEL_MAGIC 0x0be5a941
+
diff -u --recursive --new-file v2.3.13/linux/fs/partitions/sun.c linux/fs/partitions/sun.c
--- v2.3.13/linux/fs/partitions/sun.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/partitions/sun.c	Thu Aug 12 12:26:06 1999
@@ -0,0 +1,89 @@
+/*
+ *  fs/partitions/sun.c
+ *
+ *  Code extracted from drivers/block/genhd.c
+ *
+ *  Copyright (C) 1991-1998  Linus Torvalds
+ *  Re-organised Feb 1998 Russell King
+ */
+
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/blk.h>
+
+#include <asm/system.h>
+
+#include "check.h"
+#include "sun.h"
+
+int sun_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, int first_part_minor)
+{
+	int i, csum;
+	unsigned short *ush;
+	struct buffer_head *bh;
+	struct sun_disklabel {
+		unsigned char info[128];   /* Informative text string */
+		unsigned char spare[292];  /* Boot information etc. */
+		unsigned short rspeed;     /* Disk rotational speed */
+		unsigned short pcylcount;  /* Physical cylinder count */
+		unsigned short sparecyl;   /* extra sects per cylinder */
+		unsigned char spare2[4];   /* More magic... */
+		unsigned short ilfact;     /* Interleave factor */
+		unsigned short ncyl;       /* Data cylinder count */
+		unsigned short nacyl;      /* Alt. cylinder count */
+		unsigned short ntrks;      /* Tracks per cylinder */
+		unsigned short nsect;      /* Sectors per track */
+		unsigned char spare3[4];   /* Even more magic... */
+		struct sun_partition {
+			__u32 start_cylinder;
+			__u32 num_sectors;
+		} partitions[8];
+		unsigned short magic;      /* Magic number */
+		unsigned short csum;       /* Label xor'd checksum */
+	} * label;		
+	struct sun_partition *p;
+	unsigned long spc;
+
+	if(!(bh = bread(dev, 0, get_ptable_blocksize(dev)))) {
+		printk("Dev %s: unable to read partition table\n",
+		       kdevname(dev));
+		return -1;
+	}
+	label = (struct sun_disklabel *) bh->b_data;
+	p = label->partitions;
+	if (be16_to_cpu(label->magic) != SUN_LABEL_MAGIC) {
+		printk("Dev %s Sun disklabel: bad magic %04x\n",
+		       kdevname(dev), be16_to_cpu(label->magic));
+		brelse(bh);
+		return 0;
+	}
+	/* Look at the checksum */
+	ush = ((unsigned short *) (label+1)) - 1;
+	for(csum = 0; ush >= ((unsigned short *) label);)
+		csum ^= *ush--;
+	if(csum) {
+		printk("Dev %s Sun disklabel: Csum bad, label corrupted\n",
+		       kdevname(dev));
+		brelse(bh);
+		return 0;
+	}
+	/* All Sun disks have 8 partition entries */
+	spc = be16_to_cpu(label->ntrks) * be16_to_cpu(label->nsect);
+	for(i=0; i < 8; i++, p++) {
+		unsigned long st_sector;
+		int num_sectors;
+
+		st_sector = first_sector + be32_to_cpu(p->start_cylinder) * spc;
+		num_sectors = be32_to_cpu(p->num_sectors);
+		if (num_sectors)
+			add_gd_partition(hd, first_part_minor, st_sector, num_sectors);
+		first_part_minor++;
+	}
+	printk("\n");
+	brelse(bh);
+	return 1;
+}
+
diff -u --recursive --new-file v2.3.13/linux/fs/partitions/sun.h linux/fs/partitions/sun.h
--- v2.3.13/linux/fs/partitions/sun.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/partitions/sun.h	Thu Aug 12 12:26:06 1999
@@ -0,0 +1,9 @@
+/*
+ *  fs/partitions/sun.h
+ */
+
+#define SUN_LABEL_MAGIC          0xDABE
+
+int sun_partition(struct gendisk *hd, kdev_t dev,
+		  unsigned long first_sector, int first_part_minor);
+
diff -u --recursive --new-file v2.3.13/linux/fs/partitions/ultrix.c linux/fs/partitions/ultrix.c
--- v2.3.13/linux/fs/partitions/ultrix.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/partitions/ultrix.c	Thu Aug 12 12:26:06 1999
@@ -0,0 +1,60 @@
+/*
+ *  fs/partitions/ultrix.c
+ *
+ *  Code extracted from drivers/block/genhd.c
+ *
+ *  Re-organised Jul 1999 Russell King
+ */
+
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/blk.h>
+
+#include "check.h"
+
+static int ultrix_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
+{
+	int i, minor = current_minor;
+	struct buffer_head *bh;
+	struct ultrix_disklabel {
+		s32	pt_magic;	/* magic no. indicating part. info exits */
+		s32	pt_valid;	/* set by driver if pt is current */
+		struct  pt_info {
+			s32		pi_nblocks; /* no. of sectors */
+			u32		pi_blkoff;  /* block offset for start */
+		} pt_part[8];
+	} *label;
+
+#define PT_MAGIC	0x032957	/* Partition magic number */
+#define PT_VALID	1		/* Indicates if struct is valid */
+
+#define	SBLOCK	((unsigned long)((16384 - sizeof(struct ultrix_disklabel)) \
+                  /get_ptable_blocksize(dev)))
+
+	bh = bread (dev, SBLOCK, get_ptable_blocksize(dev));
+	if (!bh) {
+		printk (" unable to read block 0x%lx\n", SBLOCK);
+		return -1;
+	}
+	
+	label = (struct ultrix_disklabel *)(bh->b_data
+                                            + get_ptable_blocksize(dev)
+                                            - sizeof(struct ultrix_disklabel));
+
+	if (label->pt_magic == PT_MAGIC && label->pt_valid == PT_VALID) {
+		for (i=0; i<8; i++, minor++)
+			if (label->pt_part[i].pi_nblocks)
+				add_gd_partition(hd, minor, 
+					      label->pt_part[i].pi_blkoff,
+					      label->pt_part[i].pi_nblocks);
+		brelse(bh);
+		printk ("\n");
+		return 1;
+	} else {
+		brelse(bh);
+		return 0;
+	}
+}
+
diff -u --recursive --new-file v2.3.13/linux/fs/proc/array.c linux/fs/proc/array.c
--- v2.3.13/linux/fs/proc/array.c	Mon Aug  9 14:59:23 1999
+++ linux/fs/proc/array.c	Wed Aug 18 10:00:52 1999
@@ -78,6 +78,11 @@
 #endif
 
 
+static int open_kcore(struct inode * inode, struct file * filp)
+{
+	return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
+}
+
 static ssize_t read_core(struct file * file, char * buf,
 			 size_t count, loff_t *ppos)
 {
@@ -139,6 +144,12 @@
 static struct file_operations proc_kcore_operations = {
 	NULL,           /* lseek */
 	read_core,
+	NULL,		/* write */
+	NULL,		/* readdir */
+	NULL,		/* poll */
+	NULL,		/* ioctl */
+	NULL,		/* mmap */
+	open_kcore
 };
 
 struct inode_operations proc_kcore_inode_operations = {
@@ -546,7 +557,7 @@
 	    int count = 0;
 
 	    stack_page = (unsigned long)p;
-	    fp = ((struct switch_stack *)p->tss.ksp)->a6;
+	    fp = ((struct switch_stack *)p->thread.ksp)->a6;
 	    do {
 		    if (fp < stack_page+sizeof(struct task_struct) ||
 			fp >= 8184+stack_page)
@@ -639,11 +650,11 @@
 #define	KSTK_EIP(tsk)	\
     ({			\
 	unsigned long eip = 0;	 \
-	if ((tsk)->tss.esp0 > PAGE_SIZE && \
-	    MAP_NR((tsk)->tss.esp0) < max_mapnr) \
-	      eip = ((struct pt_regs *) (tsk)->tss.esp0)->pc;	 \
+	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)->tss.usp)
+#define	KSTK_ESP(tsk)	((tsk) == current ? rdusp() : (tsk)->thread.usp)
 #elif defined(__powerpc__)
 #define KSTK_EIP(tsk)	((tsk)->tss.regs->nip)
 #define KSTK_ESP(tsk)	((tsk)->tss.regs->gpr[1])
diff -u --recursive --new-file v2.3.13/linux/fs/ufs/truncate.c linux/fs/ufs/truncate.c
--- v2.3.13/linux/fs/ufs/truncate.c	Wed Jun 30 13:38:20 1999
+++ linux/fs/ufs/truncate.c	Wed Aug 18 10:15:19 1999
@@ -455,7 +455,8 @@
 			break;
 		if (IS_SYNC(inode) && (inode->i_state & I_DIRTY))
 			ufs_sync_inode (inode);
-		current->counter = 0;
+		run_task_queue(&tq_disk);
+		current->policy |= SCHED_YIELD;
 		schedule ();
 
 
diff -u --recursive --new-file v2.3.13/linux/include/asm-alpha/compiler.h linux/include/asm-alpha/compiler.h
--- v2.3.13/linux/include/asm-alpha/compiler.h	Sun Aug  9 12:09:06 1998
+++ linux/include/asm-alpha/compiler.h	Mon Aug 16 10:33:58 1999
@@ -13,7 +13,7 @@
  * EGCS (of varying versions) does a good job of using insxl and extxl.
  */
 
-#if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
+#if 0 && (__GNUC__ > 2 || __GNUC_MINOR__ >= 91)
 #define __kernel_insbl(val, shift) \
   (((unsigned long)(val) & 0xfful) << ((shift) * 8))
 #define __kernel_inswl(val, shift) \
@@ -29,7 +29,7 @@
      __kir; })
 #endif
 
-#if __GNUC__ > 2 || __GNUC_MINOR__ >= 92
+#if 0 && (__GNUC__ > 2 || __GNUC_MINOR__ >= 92)
 #define __kernel_extbl(val, shift)  (((val) >> (((shift) & 7) * 8)) & 0xfful)
 #define __kernel_extwl(val, shift)  (((val) >> (((shift) & 7) * 8)) & 0xfffful)
 #else
diff -u --recursive --new-file v2.3.13/linux/include/asm-alpha/core_apecs.h linux/include/asm-alpha/core_apecs.h
--- v2.3.13/linux/include/asm-alpha/core_apecs.h	Sun Dec 27 15:21:50 1998
+++ linux/include/asm-alpha/core_apecs.h	Mon Aug 16 10:33:58 1999
@@ -426,12 +426,12 @@
 	 * detect null "pointers" (the NCR driver is much simpler if
 	 * NULL pointers are preserved).
 	 */
-        if (address < APECS_XL_DMA_WIN1_BASE)
-                return 0;
-        else if (address < (APECS_XL_DMA_WIN1_BASE + APECS_XL_DMA_WIN1_SIZE))
-                address -= APECS_XL_DMA_WIN1_BASE;
+	if (address < APECS_XL_DMA_WIN1_BASE)
+		return 0;
+	else if (address < (APECS_XL_DMA_WIN1_BASE + APECS_XL_DMA_WIN1_SIZE))
+		address -= APECS_XL_DMA_WIN1_BASE;
 	else /* should be more checking here, maybe? */
-                address -= APECS_XL_DMA_WIN2_BASE;
+		address -= APECS_XL_DMA_WIN2_BASE;
 	return phys_to_virt(address);
 }
 
@@ -501,6 +501,15 @@
 {
 	unsigned long result, msb;
 
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "apecs: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += APECS_DENSE_MEM;
+	}
+#endif
+
+	addr -= APECS_DENSE_MEM;
 	if (addr >= (1UL << 24)) {
 		msb = addr & 0xf8000000;
 		addr -= msb;
@@ -514,6 +523,15 @@
 {
 	unsigned long result, msb;
 
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "apecs: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += APECS_DENSE_MEM;
+	}
+#endif
+
+	addr -= APECS_DENSE_MEM;
 	if (addr >= (1UL << 24)) {
 		msb = addr & 0xf8000000;
 		addr -= msb;
@@ -525,18 +543,43 @@
 
 __EXTERN_INLINE unsigned long apecs_readl(unsigned long addr)
 {
-	return *(vuip) (addr + APECS_DENSE_MEM);
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "apecs: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += APECS_DENSE_MEM;
+	}
+#endif
+
+	return *(vuip)addr;
 }
 
 __EXTERN_INLINE unsigned long apecs_readq(unsigned long addr)
 {
-	return *(vulp) (addr + APECS_DENSE_MEM);
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "apecs: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += APECS_DENSE_MEM;
+	}
+#endif
+
+	return *(vulp)addr;
 }
 
 __EXTERN_INLINE void apecs_writeb(unsigned char b, unsigned long addr)
 {
 	unsigned long msb;
 
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "apecs: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += APECS_DENSE_MEM;
+	}
+#endif
+
+	addr -= APECS_DENSE_MEM;
 	if (addr >= (1UL << 24)) {
 		msb = addr & 0xf8000000;
 		addr -= msb;
@@ -549,6 +592,15 @@
 {
 	unsigned long msb;
 
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "apecs: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += APECS_DENSE_MEM;
+	}
+#endif
+
+	addr -= APECS_DENSE_MEM;
 	if (addr >= (1UL << 24)) {
 		msb = addr & 0xf8000000;
 		addr -= msb;
@@ -559,19 +611,38 @@
 
 __EXTERN_INLINE void apecs_writel(unsigned int b, unsigned long addr)
 {
-	*(vuip) (addr + APECS_DENSE_MEM) = b;
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "apecs: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += APECS_DENSE_MEM;
+	}
+#endif
+
+	*(vuip)addr = b;
 }
 
 __EXTERN_INLINE void apecs_writeq(unsigned long b, unsigned long addr)
 {
-	*(vulp) (addr + APECS_DENSE_MEM) = b;
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "apecs: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += APECS_DENSE_MEM;
+	}
+#endif
+
+	*(vulp)addr = b;
 }
 
-/* Find the DENSE memory area for a given bus address.  */
+__EXTERN_INLINE unsigned long apecs_ioremap(unsigned long addr)
+{
+	return APECS_DENSE_MEM + addr;
+}
 
-__EXTERN_INLINE unsigned long apecs_dense_mem(unsigned long addr)
+__EXTERN_INLINE int apecs_is_ioaddr(unsigned long addr)
 {
-	return APECS_DENSE_MEM;
+	return addr >= IDENT_ADDR + 0x100000000UL;
 }
 
 #undef vip
@@ -602,7 +673,8 @@
 #define __writew	apecs_writew
 #define __writel	apecs_writel
 #define __writeq	apecs_writeq
-#define dense_mem	apecs_dense_mem
+#define __ioremap	apecs_ioremap
+#define __is_ioaddr	apecs_is_ioaddr
 
 #define inb(port) \
 (__builtin_constant_p((port))?__inb(port):_inb(port))
@@ -610,10 +682,12 @@
 #define outb(x, port) \
 (__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port)))
 
-#define readl(a)	__readl((unsigned long)(a))
-#define readq(a)	__readq((unsigned long)(a))
-#define writel(v,a)	__writel((v),(unsigned long)(a))
-#define writeq(v,a)	__writeq((v),(unsigned long)(a))
+#if !__DEBUG_IOREMAP
+#define __raw_readl(a)		__readl((unsigned long)(a))
+#define __raw_readq(a)		__readq((unsigned long)(a))
+#define __raw_writel(v,a)	__writel((v),(unsigned long)(a))
+#define __raw_writeq(v,a)	__writeq((v),(unsigned long)(a))
+#endif
 
 #endif /* __WANT_IO_DEF */
 
diff -u --recursive --new-file v2.3.13/linux/include/asm-alpha/core_cia.h linux/include/asm-alpha/core_cia.h
--- v2.3.13/linux/include/asm-alpha/core_cia.h	Wed Jan 13 10:42:49 1999
+++ linux/include/asm-alpha/core_cia.h	Wed Aug 18 17:12:15 1999
@@ -39,17 +39,15 @@
 
 /* CIA ADDRESS BIT DEFINITIONS
  *
- *  3 3 3 3|3 3 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 
- *  9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |1| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |0|0|0|
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
- *  |                                                                        \_/ \_/
- *  |                                                                         |   |
- *  +-- IO space, not cached.                                   Byte Enable --+   |
- *                                                              Transfer Length --+
- *
- *
+ *  3333 3333 3322 2222 2222 1111 1111 11 
+ *  9876 5432 1098 7654 3210 9876 5432 1098 7654 3210
+ *  ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
+ *  1                                             000
+ *  ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
+ *  |                                             |\|
+ *  |                               Byte Enable --+ |
+ *  |                             Transfer Length --+
+ *  +-- IO space, not cached
  *
  *   Byte      Transfer
  *   Enable    Length    Transfer  Byte    Address
@@ -77,14 +75,25 @@
 #define CIA_MEM_R2_MASK 0x07ffffff  /* SPARSE Mem region 2 mask is 27 bits */
 #define CIA_MEM_R3_MASK 0x03ffffff  /* SPARSE Mem region 3 mask is 26 bits */
 
-#define CIA_DMA_WIN_BASE_DEFAULT	(1024*1024*1024)
-#define CIA_DMA_WIN_SIZE_DEFAULT	(1024*1024*1024)
+#define CIA_DMA_WIN_BASE_DEFAULT	(1UL*1024*1024*1024)
+#define CIA_DMA_WIN_SIZE_DEFAULT	(2UL*1024*1024*1024)
+
+/* Window 0 at 1GB size 1GB mapping to 0.  */
+#define CIA_DMA_WIN0_BASE_DEFAULT      (1UL*1024*1024*1024)
+#define CIA_DMA_WIN0_SIZE_DEFAULT      (1UL*1024*1024*1024)
+#define CIA_DMA_WIN0_TRAN_DEFAULT      (0UL)
+
+/* Window 1 at 2GB size 1GB mapping to 1GB.  */
+#define CIA_DMA_WIN1_BASE_DEFAULT      (2UL*1024*1024*1024)
+#define CIA_DMA_WIN1_SIZE_DEFAULT      (1UL*1024*1024*1024)
+#define CIA_DMA_WIN1_TRAN_DEFAULT      (1UL*1024*1024*1024)
+
 
 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
 #define CIA_DMA_WIN_BASE		alpha_mv.dma_win_base
 #define CIA_DMA_WIN_SIZE		alpha_mv.dma_win_size
 #else
-#define CIA_DMA_WIN_BASE		CIA_DMA_WIN_SIZE_DEFAULT
+#define CIA_DMA_WIN_BASE		CIA_DMA_WIN_BASE_DEFAULT
 #define CIA_DMA_WIN_SIZE		CIA_DMA_WIN_SIZE_DEFAULT
 #endif
 
@@ -393,6 +402,15 @@
 {
 	unsigned long mask, base;
 
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "cia: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += CIA_DENSE_MEM;
+	}
+#endif
+
+	addr -= CIA_DENSE_MEM;
 	if (addr >= alpha_mv.sm_base_r1
 	    && addr <= alpha_mv.sm_base_r1 + CIA_MEM_R1_MASK) {
 		mask = CIA_MEM_R1_MASK;
@@ -411,7 +429,8 @@
 	else
 	{
 #if 0
-		printk("cia: address 0x%lx not covered by HAE\n", addr);
+		printk(KERN_CRIT "cia: address 0x%lx not covered by HAE\n",
+		       addr);
 #endif
 		return 0;
 	}
@@ -445,8 +464,9 @@
 
 __EXTERN_INLINE void cia_srm_writeb(unsigned char b, unsigned long addr)
 {
-	unsigned long work = cia_srm_base(addr), w;
-	if (work) {
+	unsigned long work, w;
+
+	if ((work = cia_srm_base(addr)) != 0) {
 		work += 0x00;	/* add transfer length */
 		w = __kernel_insbl(b, addr & 3);
 		*(vuip) work = w;
@@ -455,8 +475,10 @@
 
 __EXTERN_INLINE void cia_srm_writew(unsigned short b, unsigned long addr)
 {
-	unsigned long work = cia_srm_base(addr), w;
-	if (work) {
+	unsigned long work, w;
+
+	addr -= CIA_DENSE_MEM;
+	if ((work = cia_srm_base(addr)) != 0) {
 		work += 0x08;	/* add transfer length */
 		w = __kernel_inswl(b, addr & 3);
 		*(vuip) work = w;
@@ -467,6 +489,15 @@
 {
 	unsigned long result, msb;
 
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "cia: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+	}
+#endif
+
+	/* Note that CIA_DENSE_MEM has no bits not masked in these 
+	   operations, so we don't have to subtract it back out.  */
 	msb = addr & 0xE0000000;
 	addr &= CIA_MEM_R1_MASK;
 	set_hae(msb);
@@ -479,6 +510,15 @@
 {
 	unsigned long result, msb;
 
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "cia: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+	}
+#endif
+
+	/* Note that CIA_DENSE_MEM has no bits not masked in these 
+	   operations, so we don't have to subtract it back out.  */
 	msb = addr & 0xE0000000;
 	addr &= CIA_MEM_R1_MASK;
 	set_hae(msb);
@@ -489,8 +529,17 @@
 
 __EXTERN_INLINE void cia_writeb(unsigned char b, unsigned long addr)
 {
-        unsigned long msb, w; 
+	unsigned long msb, w; 
+
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "cia: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+	}
+#endif
 
+	/* Note that CIA_DENSE_MEM has no bits not masked in these 
+	   operations, so we don't have to subtract it back out.  */
 	msb = addr & 0xE0000000;
 	addr &= CIA_MEM_R1_MASK;
 	set_hae(msb);
@@ -501,8 +550,17 @@
 
 __EXTERN_INLINE void cia_writew(unsigned short b, unsigned long addr)
 {
-        unsigned long msb, w; 
+	unsigned long msb, w; 
 
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "cia: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+	}
+#endif
+
+	/* Note that CIA_DENSE_MEM has no bits not masked in these 
+	   operations, so we don't have to subtract it back out.  */
 	msb = addr & 0xE0000000;
 	addr &= CIA_MEM_R1_MASK;
 	set_hae(msb);
@@ -513,29 +571,60 @@
 
 __EXTERN_INLINE unsigned long cia_readl(unsigned long addr)
 {
-	return *(vuip) (addr + CIA_DENSE_MEM);
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "cia: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+	}
+#endif
+
+	return *(vuip)addr;
 }
 
 __EXTERN_INLINE unsigned long cia_readq(unsigned long addr)
 {
-	return *(vulp) (addr + CIA_DENSE_MEM);
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "cia: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+	}
+#endif
+
+	return *(vulp)addr;
 }
 
 __EXTERN_INLINE void cia_writel(unsigned int b, unsigned long addr)
 {
-	*(vuip) (addr + CIA_DENSE_MEM) = b;
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "cia: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+	}
+#endif
+
+	*(vuip)addr = b;
 }
 
 __EXTERN_INLINE void cia_writeq(unsigned long b, unsigned long addr)
 {
-	*(vulp) (addr + CIA_DENSE_MEM) = b;
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "cia: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+	}
+#endif
+
+	*(vulp)addr = b;
 }
 
-/* Find the DENSE memory area for a given bus address.  */
+__EXTERN_INLINE unsigned long cia_ioremap(unsigned long addr)
+{
+	return CIA_DENSE_MEM + addr;
+}
 
-__EXTERN_INLINE unsigned long cia_dense_mem(unsigned long addr)
+__EXTERN_INLINE int cia_is_ioaddr(unsigned long addr)
 {
-	return CIA_DENSE_MEM;
+	return addr >= IDENT_ADDR + 0x8000000000UL;
 }
 
 #undef vip
@@ -569,7 +658,8 @@
 #define __readq		cia_readq
 #define __writel	cia_writel
 #define __writeq	cia_writeq
-#define dense_mem	cia_dense_mem
+#define __ioremap	cia_ioremap
+#define __is_ioaddr	cia_is_ioaddr
 
 #define inb(port) \
 (__builtin_constant_p((port))?__inb(port):_inb(port))
@@ -584,10 +674,12 @@
 #define inl(port)	__inl(port)
 #define outl(x,port)	__outl((x),(port))
 
-#define readl(a)	__readl((unsigned long)(a))
-#define readq(a)	__readq((unsigned long)(a))
-#define writel(v,a)	__writel((v),(unsigned long)(a))
-#define writeq(v,a)	__writeq((v),(unsigned long)(a))
+#if !__DEBUG_IOREMAP
+#define __raw_readl(a)		__readl((unsigned long)(a))
+#define __raw_readq(a)		__readq((unsigned long)(a))
+#define __raw_writel(v,a)	__writel((v),(unsigned long)(a))
+#define __raw_writeq(v,a)	__writeq((v),(unsigned long)(a))
+#endif
 
 #endif /* __WANT_IO_DEF */
 
diff -u --recursive --new-file v2.3.13/linux/include/asm-alpha/core_lca.h linux/include/asm-alpha/core_lca.h
--- v2.3.13/linux/include/asm-alpha/core_lca.h	Sun Dec 27 15:21:50 1998
+++ linux/include/asm-alpha/core_lca.h	Mon Aug 16 10:33:58 1999
@@ -305,6 +305,15 @@
 {
 	unsigned long result, msb;
 
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "lca: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += LCA_DENSE_MEM;
+	}
+#endif
+
+	addr -= LCA_DENSE_MEM;
 	if (addr >= (1UL << 24)) {
 		msb = addr & 0xf8000000;
 		addr -= msb;
@@ -318,6 +327,15 @@
 {
 	unsigned long result, msb;
 
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "lca: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += LCA_DENSE_MEM;
+	}
+#endif
+
+	addr -= LCA_DENSE_MEM;
 	if (addr >= (1UL << 24)) {
 		msb = addr & 0xf8000000;
 		addr -= msb;
@@ -329,12 +347,28 @@
 
 __EXTERN_INLINE unsigned long lca_readl(unsigned long addr)
 {
-	return *(vuip) (addr + LCA_DENSE_MEM);
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "lca: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += LCA_DENSE_MEM;
+	}
+#endif
+
+	return *(vuip)addr;
 }
 
 __EXTERN_INLINE unsigned long lca_readq(unsigned long addr)
 {
-	return *(vulp) (addr + LCA_DENSE_MEM);
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "lca: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += LCA_DENSE_MEM;
+	}
+#endif
+
+	return *(vulp)addr;
 }
 
 __EXTERN_INLINE void lca_writeb(unsigned char b, unsigned long addr)
@@ -342,6 +376,15 @@
 	unsigned long msb;
 	unsigned long w;
 
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "lca: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += LCA_DENSE_MEM;
+	}
+#endif
+
+	addr -= LCA_DENSE_MEM;
 	if (addr >= (1UL << 24)) {
 		msb = addr & 0xf8000000;
 		addr -= msb;
@@ -356,6 +399,15 @@
 	unsigned long msb;
 	unsigned long w;
 
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "lca: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += LCA_DENSE_MEM;
+	}
+#endif
+
+	addr -= LCA_DENSE_MEM;
 	if (addr >= (1UL << 24)) {
 		msb = addr & 0xf8000000;
 		addr -= msb;
@@ -367,19 +419,38 @@
 
 __EXTERN_INLINE void lca_writel(unsigned int b, unsigned long addr)
 {
-	*(vuip) (addr + LCA_DENSE_MEM) = b;
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "lca: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += LCA_DENSE_MEM;
+	}
+#endif
+
+	*(vuip)addr = b;
 }
 
 __EXTERN_INLINE void lca_writeq(unsigned long b, unsigned long addr)
 {
-	*(vulp) (addr + LCA_DENSE_MEM) = b;
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "lca: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += LCA_DENSE_MEM;
+	}
+#endif
+
+	*(vulp)addr = b;
 }
 
-/* Find the DENSE memory area for a given bus address.  */
+__EXTERN_INLINE unsigned long lca_ioremap(unsigned long addr)
+{
+	return LCA_DENSE_MEM + addr;
+}
 
-__EXTERN_INLINE unsigned long lca_dense_mem(unsigned long addr)
+__EXTERN_INLINE int lca_is_ioaddr(unsigned long addr)
 {
-	return LCA_DENSE_MEM;
+	return addr >= IDENT_ADDR + 0x100000000UL;
 }
 
 #undef vip
@@ -404,7 +475,8 @@
 #define __readq		lca_readq
 #define __writel	lca_writel
 #define __writeq	lca_writeq
-#define dense_mem	lca_dense_mem
+#define __ioremap	lca_ioremap
+#define __is_ioaddr	lca_is_ioaddr
 
 #define inb(port) \
 (__builtin_constant_p((port))?__inb(port):_inb(port))
@@ -412,10 +484,12 @@
 #define outb(x, port) \
 (__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port)))
 
-#define readl(a)	__readl((unsigned long)(a))
-#define readq(a)	__readq((unsigned long)(a))
-#define writel(v,a)	__writel((v),(unsigned long)(a))
-#define writeq(v,a)	__writeq((v),(unsigned long)(a))
+#if !__DEBUG_IOREMAP
+#define __raw_readl(a)		__readl((unsigned long)(a))
+#define __raw_readq(a)		__readq((unsigned long)(a))
+#define __raw_writel(v,a)	__writel((v),(unsigned long)(a))
+#define __raw_writeq(v,a)	__writeq((v),(unsigned long)(a))
+#endif
 
 #endif /* __WANT_IO_DEF */
 
diff -u --recursive --new-file v2.3.13/linux/include/asm-alpha/core_mcpcia.h linux/include/asm-alpha/core_mcpcia.h
--- v2.3.13/linux/include/asm-alpha/core_mcpcia.h	Sun Jan 10 09:59:59 1999
+++ linux/include/asm-alpha/core_mcpcia.h	Mon Aug 16 10:33:58 1999
@@ -37,17 +37,15 @@
 
 /* MCPCIA ADDRESS BIT DEFINITIONS
  *
- *  3 3 3 3|3 3 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 
- *  9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |1| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |0|0|0|
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
- *  |                                                                        \_/ \_/
- *  |                                                                         |   |
- *  +-- IO space, not cached.                                   Byte Enable --+   |
- *                                                              Transfer Length --+
- *
- *
+ *  3333 3333 3322 2222 2222 1111 1111 11
+ *  9876 5432 1098 7654 3210 9876 5432 1098 7654 3210
+ *  ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
+ *  1                                             000
+ *  ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
+ *  |                                             |\|
+ *  |                               Byte Enable --+ |
+ *  |                             Transfer Length --+
+ *  +-- IO space, not cached
  *
  *   Byte      Transfer
  *   Enable    Length    Transfer  Byte    Address
@@ -171,8 +169,8 @@
  * Data structure for handling MCPCIA machine checks:
  */
 struct el_MCPCIA_uncorrected_frame_mcheck {
-        struct el_common header;
-        struct el_common_EV5_uncorrectable_mcheck procdata;
+	struct el_common header;
+	struct el_common_EV5_uncorrectable_mcheck procdata;
 };
 
 
@@ -215,41 +213,6 @@
 #define vuip	volatile unsigned int *
 #define vulp	volatile unsigned long *
 
-#if 0 /* BWIO */
-__EXTERN_INLINE unsigned int mcpcia_bw_inb(unsigned long addr)
-{
-	return __kernel_ldbu(*(vucp)(addr+MCPCIA_BW_IO));
-}
-
-__EXTERN_INLINE void mcpcia_bw_outb(unsigned char b, unsigned long addr)
-{
-	__kernel_stb(b, *(vucp)(addr+MCPCIA_BW_IO));
-	mb();
-}
-
-__EXTERN_INLINE unsigned int mcpcia_bw_inw(unsigned long addr)
-{
-	return __kernel_ldwu(*(vusp)(addr+MCPCIA_BW_IO));
-}
-
-__EXTERN_INLINE void mcpcia_bw_outw(unsigned short b, unsigned long addr)
-{
-	__kernel_stw(b, *(vusp)(addr+MCPCIA_BW_IO));
-	mb();
-}
-
-__EXTERN_INLINE unsigned int mcpcia_bw_inl(unsigned long addr)
-{
-	return *(vuip)(addr+MCPCIA_BW_IO);
-}
-
-__EXTERN_INLINE void mcpcia_bw_outl(unsigned int b, unsigned long addr)
-{
-	*(vuip)(addr+MCPCIA_BW_IO) = b;
-	mb();
-}
-#endif
-
 __EXTERN_INLINE unsigned int mcpcia_inb(unsigned long in_addr)
 {
 	unsigned long addr = in_addr & 0xffffffffUL;
@@ -307,8 +270,8 @@
 /*
  * Memory functions.  64-bit and 32-bit accesses are done through
  * dense memory space, everything else through sparse space.
- * 
- * For reading and writing 8 and 16 bit quantities we need to 
+ *
+ * For reading and writing 8 and 16 bit quantities we need to
  * go through one of the three sparse address mapping regions
  * and use the HAE_MEM CSR to provide some bits of the address.
  * The following few routines use only sparse address region 1
@@ -317,10 +280,10 @@
  * See p 6-17 of the specification but it looks something like this:
  *
  * 21164 Address:
- * 
+ *
  *          3         2         1
  * 9876543210987654321098765432109876543210
- * 1ZZZZ0.PCI.QW.Address............BBLL                 
+ * 1ZZZZ0.PCI.QW.Address............BBLL
  *
  * ZZ = SBZ
  * BB = Byte offset
@@ -333,56 +296,34 @@
  * HHH....PCI.QW.Address........ 00
  *
  * HHH = 31:29 HAE_MEM CSR
- * 
+ *
  */
 
-#if 0 /* BWIO */
-__EXTERN_INLINE unsigned long mcpcia_bw_readb(unsigned long addr)
-{
-	return __kernel_ldbu(*(vucp)(addr+MCPCIA_BW_MEM));
-}
-
-__EXTERN_INLINE unsigned long mcpcia_bw_readw(unsigned long addr)
-{
-	return __kernel_ldbw(*(vusp)(addr+MCPCIA_BW_MEM));
-}
-
-__EXTERN_INLINE unsigned long mcpcia_bw_readl(unsigned long addr)
-{
-	return *(vuip)(addr + MCPCIA_BW_MEM);
-}
-
-__EXTERN_INLINE unsigned long mcpcia_bw_readq(unsigned long addr)
+__EXTERN_INLINE unsigned long mcpcia_ioremap(unsigned long in_addr)
 {
-	return *(vulp)(addr + MCPCIA_BW_MEM);
-}
-
-__EXTERN_INLINE void mcpcia_bw_writeb(unsigned char b, unsigned long addr)
-{
-	__kernel_stb(b, *(vucp)(addr+MCPCIA_BW_MEM));
-}
-
-__EXTERN_INLINE void mcpcia_bw_writew(unsigned short b, unsigned long addr)
-{
-	__kernel_stw(b, *(vusp)(addr+MCPCIA_BW_MEM));
-}
-
-__EXTERN_INLINE void mcpcia_bw_writel(unsigned int b, unsigned long addr)
-{
-	*(vuip)(addr+MCPCIA_BW_MEM) = b;
+	unsigned long addr = in_addr & 0xffffffffUL;
+	unsigned long hose = (in_addr >> 32) & 3;
+	return addr + MCPCIA_DENSE(hose);
 }
 
-__EXTERN_INLINE void mcpcia_bw_writeq(unsigned long b, unsigned long addr)
+__EXTERN_INLINE int mcpcia_is_ioaddr(unsigned long addr)
 {
-	*(vulp)(addr+MCPCIA_BW_MEM) = b;
+	return addr >= IDENT_ADDR + 0x8000000000UL;
 }
-#endif
 
 __EXTERN_INLINE unsigned long mcpcia_srm_base(unsigned long addr)
 {
 	unsigned long mask, base;
 	unsigned long hose = (addr >> 32) & 3;
 
+#if __DEBUG_IOREMAP
+	if (addr <= 0x1000000000) {
+		printk(KERN_CRIT "mcpcia: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+	}
+#endif
+
+	addr &= 0xfffffffful;
 	if (addr >= alpha_mv.sm_base_r1
 	    && addr <= alpha_mv.sm_base_r1 + MCPCIA_MEM_MASK) {
 		mask = MCPCIA_MEM_MASK;
@@ -407,7 +348,7 @@
 		return 0xff;
 	work += 0x00;	/* add transfer length */
 
-	result = *(vip) work;
+	result = *(vip)work;
 	return __kernel_extbl(result, addr & 3);
 }
 
@@ -425,28 +366,39 @@
 
 __EXTERN_INLINE void mcpcia_srm_writeb(unsigned char b, unsigned long addr)
 {
-	unsigned long work = mcpcia_srm_base(addr);
+	unsigned long w, work = mcpcia_srm_base(addr);
 	if (work) {
 		work += 0x00;	/* add transfer length */
-		*(vuip) work = b * 0x01010101;
+		w = __kernel_insbl(b, addr & 3);
+		*(vuip)work = w;
 	}
 }
 
 __EXTERN_INLINE void mcpcia_srm_writew(unsigned short b, unsigned long addr)
 {
-	unsigned long work = mcpcia_srm_base(addr);
+	unsigned long w, work = mcpcia_srm_base(addr);
 	if (work) {
 		work += 0x08;	/* add transfer length */
-		*(vuip) work = b * 0x00010001;
+		w = __kernel_inswl(b, addr & 3);
+		*(vuip)work = w;
 	}
 }
 
 __EXTERN_INLINE unsigned long mcpcia_readb(unsigned long in_addr)
 {
+	/* Note that MCPCIA_DENSE(hose) has no bits not masked here, and
+	   that the hose calculation is still correct.  */
 	unsigned long addr = in_addr & 0xffffffffUL;
 	unsigned long hose = (in_addr >> 32) & 3;
 	unsigned long result, msb, work, temp;
 
+#if __DEBUG_IOREMAP
+	if (in_addr <= 0x1000000000) {
+		printk(KERN_CRIT "mcpcia: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+	}
+#endif
+
 	msb = addr & ~MCPCIA_MEM_MASK;
 	temp = addr & MCPCIA_MEM_MASK;
 	set_hae(msb);
@@ -458,12 +410,21 @@
 
 __EXTERN_INLINE unsigned long mcpcia_readw(unsigned long in_addr)
 {
+	/* Note that MCPCIA_DENSE(hose) has no bits not masked here, and
+	   that the hose calculation is still correct.  */
 	unsigned long addr = in_addr & 0xffffffffUL;
 	unsigned long hose = (in_addr >> 32) & 3;
 	unsigned long result, msb, work, temp;
 
+#if __DEBUG_IOREMAP
+	if (in_addr <= 0x1000000000) {
+		printk(KERN_CRIT "mcpcia: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+	}
+#endif
+
 	msb = addr & ~MCPCIA_MEM_MASK;
-	temp = addr & MCPCIA_MEM_MASK ;
+	temp = addr & MCPCIA_MEM_MASK;
 	set_hae(msb);
 
 	work = ((temp << 5) + MCPCIA_SPARSE(hose) + 0x08);
@@ -473,63 +434,100 @@
 
 __EXTERN_INLINE void mcpcia_writeb(unsigned char b, unsigned long in_addr)
 {
+	/* Note that MCPCIA_DENSE(hose) has no bits not masked here, and
+	   that the hose calculation is still correct.  */
 	unsigned long addr = in_addr & 0xffffffffUL;
 	unsigned long hose = (in_addr >> 32) & 3;
-        unsigned long msb; 
+	unsigned long msb, w;
+
+#if __DEBUG_IOREMAP
+	if (in_addr <= 0x1000000000) {
+		printk(KERN_CRIT "mcpcia: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+	}
+#endif
 
 	msb = addr & ~MCPCIA_MEM_MASK;
 	addr &= MCPCIA_MEM_MASK;
 	set_hae(msb);
 
-	*(vuip) ((addr << 5) + MCPCIA_SPARSE(hose) + 0x00) = b * 0x01010101;
+	w = __kernel_insbl(b, in_addr & 3);
+	*(vuip) ((addr << 5) + MCPCIA_SPARSE(hose) + 0x00) = w;
 }
 
 __EXTERN_INLINE void mcpcia_writew(unsigned short b, unsigned long in_addr)
 {
+	/* Note that MCPCIA_DENSE(hose) has no bits not masked here, and
+	   that the hose calculation is still correct.  */
 	unsigned long addr = in_addr & 0xffffffffUL;
 	unsigned long hose = (in_addr >> 32) & 3;
-        unsigned long msb ; 
+	unsigned long msb, w;
+
+#if __DEBUG_IOREMAP
+	if (in_addr <= 0x1000000000) {
+		printk(KERN_CRIT "mcpcia: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+	}
+#endif
 
-	msb = addr & ~MCPCIA_MEM_MASK ;
-	addr &= MCPCIA_MEM_MASK ;
+	msb = addr & ~MCPCIA_MEM_MASK;
+	addr &= MCPCIA_MEM_MASK;
 	set_hae(msb);
 
-	*(vuip) ((addr << 5) + MCPCIA_SPARSE(hose) + 0x08) = b * 0x00010001;
+	w = __kernel_inswl(b, in_addr & 3);
+	*(vuip) ((addr << 5) + MCPCIA_SPARSE(hose) + 0x08) = w;
 }
 
-__EXTERN_INLINE unsigned long mcpcia_readl(unsigned long in_addr)
+__EXTERN_INLINE unsigned long mcpcia_readl(unsigned long addr)
 {
-	unsigned long addr = in_addr & 0xffffffffUL;
-	unsigned long hose = (in_addr >> 32) & 3;
-	return *(vuip) (addr + MCPCIA_DENSE(hose));
-}
+#if __DEBUG_IOREMAP
+	if (addr <= 0x1000000000) {
+		printk(KERN_CRIT "mcpcia: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr = mcpcia_ioremap(addr);
+	}
+#endif
 
-__EXTERN_INLINE unsigned long mcpcia_readq(unsigned long in_addr)
-{
-	unsigned long addr = in_addr & 0xffffffffUL;
-	unsigned long hose = (in_addr >> 32) & 3;
-	return *(vulp) (addr + MCPCIA_DENSE(hose));
+	return *(vuip)addr;
 }
 
-__EXTERN_INLINE void mcpcia_writel(unsigned int b, unsigned long in_addr)
+__EXTERN_INLINE unsigned long mcpcia_readq(unsigned long addr)
 {
-	unsigned long addr = in_addr & 0xffffffffUL;
-	unsigned long hose = (in_addr >> 32) & 3;
-	*(vuip) (addr + MCPCIA_DENSE(hose)) = b;
+#if __DEBUG_IOREMAP
+	if (addr <= 0x1000000000) {
+		printk(KERN_CRIT "mcpcia: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr = mcpcia_ioremap(addr);
+	}
+#endif
+
+	return *(vulp)addr;
 }
 
-__EXTERN_INLINE void mcpcia_writeq(unsigned long b, unsigned long in_addr)
+__EXTERN_INLINE void mcpcia_writel(unsigned int b, unsigned long addr)
 {
-	unsigned long addr = in_addr & 0xffffffffUL;
-	unsigned long hose = (in_addr >> 32) & 3;
-	*(vulp) (addr + MCPCIA_DENSE(hose)) = b;
-}
+#if __DEBUG_IOREMAP
+	if (addr <= 0x1000000000) {
+		printk(KERN_CRIT "mcpcia: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr = mcpcia_ioremap(addr);
+	}
+#endif
 
-/* Find the DENSE memory area for a given bus address.  */
+	*(vuip)addr = b;
+}
 
-__EXTERN_INLINE unsigned long mcpcia_dense_mem(unsigned long addr)
+__EXTERN_INLINE void mcpcia_writeq(unsigned long b, unsigned long addr)
 {
-	return MCPCIA_DENSE((addr >> 32) & 3);
+#if __DEBUG_IOREMAP
+	if (addr <= 0x1000000000) {
+		printk(KERN_CRIT "mcpcia: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr = mcpcia_ioremap(addr);
+	}
+#endif
+
+	*(vulp)addr = b;
 }
 
 #undef vucp
@@ -543,69 +541,42 @@
 #define virt_to_bus	mcpcia_virt_to_bus
 #define bus_to_virt	mcpcia_bus_to_virt
 
-#if 0 /* BWIO */
-# define __inb		mcpcia_bw_inb
-# define __inw		mcpcia_bw_inw
-# define __inl		mcpcia_bw_inl
-# define __outb		mcpcia_bw_outb
-# define __outw		mcpcia_bw_outw
-# define __outl		mcpcia_bw_outl
-# define __readb	mcpcia_bw_readb
-# define __readw	mcpcia_bw_readw
-# define __writeb	mcpcia_bw_writeb
-# define __writew	mcpcia_bw_writew
-# define __readl	mcpcia_bw_readl
-# define __readq	mcpcia_bw_readq
-# define __writel	mcpcia_bw_writel
-# define __writeq	mcpcia_bw_writeq
-#else
-# define __inb		mcpcia_inb
-# define __inw		mcpcia_inw
-# define __inl		mcpcia_inl
-# define __outb		mcpcia_outb
-# define __outw		mcpcia_outw
-# define __outl		mcpcia_outl
-# ifdef CONFIG_ALPHA_SRM_SETUP
-#  define __readb	mcpcia_srm_readb
-#  define __readw	mcpcia_srm_readw
-#  define __writeb	mcpcia_srm_writeb
-#  define __writew	mcpcia_srm_writew
-# else
-#  define __readb	mcpcia_readb
-#  define __readw	mcpcia_readw
-#  define __writeb	mcpcia_writeb
-#  define __writew	mcpcia_writew
-# endif
-# define __readl	mcpcia_readl
-# define __readq	mcpcia_readq
-# define __writel	mcpcia_writel
-# define __writeq	mcpcia_writeq
-#endif /* BWIO */
-
-#define dense_mem	mcpcia_dense_mem
-
-#if 0 /* BWIO */
-# define inb(port) __inb((port))
-# define inw(port) __inw((port))
-# define inl(port) __inl((port))
-# define outb(x, port) __outb((x),(port))
-# define outw(x, port) __outw((x),(port))
-# define outl(x, port) __outl((x),(port))
-# define readb(addr) __readb((addr))
-# define readw(addr) __readw((addr))
-# define writeb(b, addr) __writeb((b),(addr))
-# define writew(b, addr) __writew((b),(addr))
+#define __inb		mcpcia_inb
+#define __inw		mcpcia_inw
+#define __inl		mcpcia_inl
+#define __outb		mcpcia_outb
+#define __outw		mcpcia_outw
+#define __outl		mcpcia_outl
+#ifdef CONFIG_ALPHA_SRM_SETUP
+# define __readb	mcpcia_srm_readb
+# define __readw	mcpcia_srm_readw
+# define __writeb	mcpcia_srm_writeb
+# define __writew	mcpcia_srm_writew
 #else
+# define __readb	mcpcia_readb
+# define __readw	mcpcia_readw
+# define __writeb	mcpcia_writeb
+# define __writew	mcpcia_writew
+#endif
+#define __readl		mcpcia_readl
+#define __readq		mcpcia_readq
+#define __writel	mcpcia_writel
+#define __writeq	mcpcia_writeq
+
+#define __ioremap	mcpcia_ioremap
+#define __is_ioaddr	mcpcia_is_ioaddr
+
 # define inb(port) \
   (__builtin_constant_p((port))?__inb(port):_inb(port))
 # define outb(x, port) \
   (__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port)))
-#endif /* BWIO */
 
-#define readl(a)	__readl((unsigned long)(a))
-#define readq(a)	__readq((unsigned long)(a))
-#define writel(v,a)	__writel((v),(unsigned long)(a))
-#define writeq(v,a)	__writeq((v),(unsigned long)(a))
+#if !__DEBUG_IOREMAP
+#define __raw_readl(a)		__readl((unsigned long)(a))
+#define __raw_readq(a)		__readq((unsigned long)(a))
+#define __raw_writel(v,a)	__writel((v),(unsigned long)(a))
+#define __raw_writeq(v,a)	__writeq((v),(unsigned long)(a))
+#endif
 
 #endif /* __WANT_IO_DEF */
 
diff -u --recursive --new-file v2.3.13/linux/include/asm-alpha/core_polaris.h linux/include/asm-alpha/core_polaris.h
--- v2.3.13/linux/include/asm-alpha/core_polaris.h	Sun Jan 24 21:29:53 1999
+++ linux/include/asm-alpha/core_polaris.h	Mon Aug 16 10:33:58 1999
@@ -19,23 +19,23 @@
  */
 
 /* Polaris memory regions */
-#define		POLARIS_SPARSE_MEM_BASE		(IDENT_ADDR + 0xf800000000)
-#define		POLARIS_DENSE_MEM_BASE		(IDENT_ADDR + 0xf900000000)
-#define 	POLARIS_SPARSE_IO_BASE		(IDENT_ADDR + 0xf980000000)
-#define		POLARIS_SPARSE_CONFIG_BASE	(IDENT_ADDR + 0xf9c0000000)
-#define		POLARIS_IACK_BASE		(IDENT_ADDR + 0xf9f8000000)
-#define		POLARIS_DENSE_IO_BASE		(IDENT_ADDR + 0xf9fc000000)
-#define		POLARIS_DENSE_CONFIG_BASE	(IDENT_ADDR + 0xf9fe000000)
+#define POLARIS_SPARSE_MEM_BASE		(IDENT_ADDR + 0xf800000000)
+#define POLARIS_DENSE_MEM_BASE		(IDENT_ADDR + 0xf900000000)
+#define POLARIS_SPARSE_IO_BASE		(IDENT_ADDR + 0xf980000000)
+#define POLARIS_SPARSE_CONFIG_BASE	(IDENT_ADDR + 0xf9c0000000)
+#define POLARIS_IACK_BASE		(IDENT_ADDR + 0xf9f8000000)
+#define POLARIS_DENSE_IO_BASE		(IDENT_ADDR + 0xf9fc000000)
+#define POLARIS_DENSE_CONFIG_BASE	(IDENT_ADDR + 0xf9fe000000)
 
-#define		POLARIS_IACK_SC			POLARIS_IACK_BASE
+#define POLARIS_IACK_SC			POLARIS_IACK_BASE
 
 /* The Polaris command/status registers live in PCI Config space for
  * bus 0/device 0.  As such, they may be bytes, words, or doublewords.
  */
-#define		POLARIS_W_VENID		(POLARIS_DENSE_CONFIG_BASE)
-#define		POLARIS_W_DEVID		(POLARIS_DENSE_CONFIG_BASE+2)
-#define		POLARIS_W_CMD		(POLARIS_DENSE_CONFIG_BASE+4)
-#define		POLARIS_W_STATUS	(POLARIS_DENSE_CONFIG_BASE+6)
+#define POLARIS_W_VENID		(POLARIS_DENSE_CONFIG_BASE)
+#define POLARIS_W_DEVID		(POLARIS_DENSE_CONFIG_BASE+2)
+#define POLARIS_W_CMD		(POLARIS_DENSE_CONFIG_BASE+4)
+#define POLARIS_W_STATUS	(POLARIS_DENSE_CONFIG_BASE+6)
 
 /* No HAE address.  Polaris has no concept of an HAE, since it
  * supports transfers of all sizes in dense space.
@@ -62,7 +62,7 @@
     u_long	psc_pcictl2;
 };
 
- #ifdef __KERNEL__
+#ifdef __KERNEL__
 
 #ifndef __EXTERN_INLINE
 #define __EXTERN_INLINE extern inline
@@ -96,7 +96,7 @@
 
 __EXTERN_INLINE unsigned int polaris_inb(unsigned long addr)
 {
-        return __kernel_ldbu(*(vucp)(addr + POLARIS_DENSE_IO_BASE));
+	return __kernel_ldbu(*(vucp)(addr + POLARIS_DENSE_IO_BASE));
 }
 
 __EXTERN_INLINE void polaris_outb(unsigned char b, unsigned long addr)
@@ -107,7 +107,7 @@
 
 __EXTERN_INLINE unsigned int polaris_inw(unsigned long addr)
 {
-        return __kernel_ldwu(*(vusp)(addr + POLARIS_DENSE_IO_BASE));
+	return __kernel_ldwu(*(vusp)(addr + POLARIS_DENSE_IO_BASE));
 }
 
 __EXTERN_INLINE void polaris_outw(unsigned short b, unsigned long addr)
@@ -118,13 +118,13 @@
 
 __EXTERN_INLINE unsigned int polaris_inl(unsigned long addr)
 {
-        return *(vuip)(addr + POLARIS_DENSE_IO_BASE);
+	return *(vuip)(addr + POLARIS_DENSE_IO_BASE);
 }
 
 __EXTERN_INLINE void polaris_outl(unsigned int b, unsigned long addr)
 {
-        *(vuip)(addr + POLARIS_DENSE_IO_BASE) = b;
-        mb();
+	*(vuip)(addr + POLARIS_DENSE_IO_BASE) = b;
+	mb();
 }
 
 /*
@@ -136,53 +136,116 @@
 
 __EXTERN_INLINE unsigned long polaris_readb(unsigned long addr)
 {
-        return __kernel_ldbu(*(vucp)(addr + POLARIS_DENSE_MEM_BASE));
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "polaris: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += POLARIS_DENSE_MEM_BASE;
+	}
+#endif
+
+	return __kernel_ldbu(*(vucp)addr);
 }
 
 __EXTERN_INLINE unsigned long polaris_readw(unsigned long addr)
 {
-        return __kernel_ldwu(*(vusp)(addr + POLARIS_DENSE_MEM_BASE));
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "polaris: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += POLARIS_DENSE_MEM_BASE;
+	}
+#endif
+
+	return __kernel_ldwu(*(vusp)addr);
 }
 
 __EXTERN_INLINE unsigned long polaris_readl(unsigned long addr)
 {
-        return *(vuip)(addr + POLARIS_DENSE_MEM_BASE);
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "polaris: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += POLARIS_DENSE_MEM_BASE;
+	}
+#endif
+
+	return *(vuip)addr;
 }
 
 __EXTERN_INLINE unsigned long polaris_readq(unsigned long addr)
 {
-        return *(vulp)(addr + POLARIS_DENSE_MEM_BASE);
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "polaris: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += POLARIS_DENSE_MEM_BASE;
+	}
+#endif
+
+	return *(vulp)addr;
 }
 
 __EXTERN_INLINE void polaris_writeb(unsigned char b, unsigned long addr)
 {
-        __kernel_stb(b, *(vucp)(addr + POLARIS_DENSE_MEM_BASE));
-        mb();
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "polaris: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += POLARIS_DENSE_MEM_BASE;
+	}
+#endif
+
+	__kernel_stb(b, *(vucp)addr);
 }
 
 __EXTERN_INLINE void polaris_writew(unsigned short b, unsigned long addr)
 {
-        __kernel_stw(b, *(vusp)(addr + POLARIS_DENSE_MEM_BASE));
-        mb();
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "polaris: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += POLARIS_DENSE_MEM_BASE;
+	}
+#endif
+
+	__kernel_stw(b, *(vusp)addr);
 }
 
 __EXTERN_INLINE void polaris_writel(unsigned int b, unsigned long addr)
 {
-        *(vuip)(addr + POLARIS_DENSE_MEM_BASE) = b;
-        mb();
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "polaris: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += POLARIS_DENSE_MEM_BASE;
+	}
+#endif
+
+	*(vuip)addr = b;
 }
 
 __EXTERN_INLINE void polaris_writeq(unsigned long b, unsigned long addr)
 {
-        *(vulp)(addr + POLARIS_DENSE_MEM_BASE) = b;
-        mb();
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "polaris: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += POLARIS_DENSE_MEM_BASE;
+	}
+#endif
+
+	*(vulp)addr = b;
 }
 
-/* Find the DENSE memory area for a given bus address.  */
+__EXTERN_INLINE unsigned long polaris_ioremap(unsigned long addr)
+{
+	return POLARIS_DENSE_MEM_BASE + addr;
+}
 
-__EXTERN_INLINE unsigned long polaris_dense_mem(unsigned long addr)
+__EXTERN_INLINE int polaris_is_ioaddr(unsigned long addr)
 {
-        return POLARIS_DENSE_MEM_BASE;
+	return addr >= IDENT_ADDR + 0x8000000000UL;
 }
 
 #undef vucp
@@ -209,7 +272,8 @@
 #define __readq         polaris_readq
 #define __writel        polaris_writel
 #define __writeq        polaris_writeq
-#define dense_mem       polaris_dense_mem
+#define __ioremap       polaris_ioremap
+#define __is_ioaddr	polaris_is_ioaddr
 
 #define inb(port) __inb((port))
 #define inw(port) __inw((port))
@@ -219,15 +283,16 @@
 #define outw(v, port) __outw((v),(port))
 #define outl(v, port) __outl((v),(port))
 
-#define readb(a)        __readb((unsigned long)(a))
-#define readw(a)        __readw((unsigned long)(a))
-#define readl(a)        __readl((unsigned long)(a))
-#define readq(a)        __readq((unsigned long)(a))
-
-#define writeb(v,a)     __writeb((v),(unsigned long)(a))
-#define writew(v,a)     __writew((v),(unsigned long)(a))
-#define writel(v,a)     __writel((v),(unsigned long)(a))
-#define writeq(v,a)     __writeq((v),(unsigned long)(a))
+#if !__DEBUG_IOREMAP
+#define __raw_readb(a)		__readb((unsigned long)(a))
+#define __raw_readw(a)		__readw((unsigned long)(a))
+#define __raw_readl(a)		__readl((unsigned long)(a))
+#define __raw_readq(a)		__readq((unsigned long)(a))
+#define __raw_writeb(v,a)	__writeb((v),(unsigned long)(a))
+#define __raw_writeb(v,a)	__writew((v),(unsigned long)(a))
+#define __raw_writel(v,a)	__writel((v),(unsigned long)(a))
+#define __raw_writeq(v,a)	__writeq((v),(unsigned long)(a))
+#endif
 
 #endif /* __WANT_IO_DEF */
 
diff -u --recursive --new-file v2.3.13/linux/include/asm-alpha/core_pyxis.h linux/include/asm-alpha/core_pyxis.h
--- v2.3.13/linux/include/asm-alpha/core_pyxis.h	Wed Jul 21 15:46:48 1999
+++ linux/include/asm-alpha/core_pyxis.h	Mon Aug 16 10:33:58 1999
@@ -34,19 +34,17 @@
 **------------------------------------------------------------------------*/
 
 
-/* CIA ADDRESS BIT DEFINITIONS
- *
- *  3 3 3 3|3 3 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 
- *  9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |1| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |0|0|0|
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
- *  |                                                                        \_/ \_/
- *  |                                                                         |   |
- *  +-- IO space, not cached.                                   Byte Enable --+   |
- *                                                              Transfer Length --+
- *
+/* PYXIS ADDRESS BIT DEFINITIONS
  *
+ *  3333 3333 3322 2222 2222 1111 1111 11
+ *  9876 5432 1098 7654 3210 9876 5432 1098 7654 3210
+ *  ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
+ *  1                                             000
+ *  ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
+ *  |						  |\|
+ *  |                               Byte Enable --+ |
+ *  |                             Transfer Length --+
+ *  +-- IO space, not cached
  *
  *   Byte      Transfer
  *   Enable    Length    Transfer  Byte    Address
@@ -74,8 +72,18 @@
 #define PYXIS_MEM_R2_MASK 0x07ffffff  /* SPARSE Mem region 2 mask is 27 bits */
 #define PYXIS_MEM_R3_MASK 0x03ffffff  /* SPARSE Mem region 3 mask is 26 bits */
 
-#define PYXIS_DMA_WIN_BASE_DEFAULT	(2UL*1024*1024*1024)
-#define PYXIS_DMA_WIN_SIZE_DEFAULT	(1UL*1024*1024*1024)
+#define PYXIS_DMA_WIN_BASE_DEFAULT	(1UL*1024*1024*1024)
+#define PYXIS_DMA_WIN_SIZE_DEFAULT	(2UL*1024*1024*1024)
+
+/* Window 0 at 1GB size 1GB mapping 0 */
+#define PYXIS_DMA_WIN0_BASE_DEFAULT	(1UL*1024*1024*1024)
+#define PYXIS_DMA_WIN0_SIZE_DEFAULT	(1UL*1024*1024*1024)
+#define PYXIS_DMA_WIN0_TRAN_DEFAULT	(0UL)
+
+/* Window 0 at 2GB size 1GB mapping 1GB */
+#define PYXIS_DMA_WIN1_BASE_DEFAULT	(2UL*1024*1024*1024)
+#define PYXIS_DMA_WIN1_SIZE_DEFAULT	(1UL*1024*1024*1024)
+#define PYXIS_DMA_WIN1_TRAN_DEFAULT	(1UL*1024*1024*1024)
 
 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
 #define PYXIS_DMA_WIN_BASE		alpha_mv.dma_win_base
@@ -203,47 +211,47 @@
  * Data structure for handling PYXIS machine checks:
  */
 struct el_PYXIS_sysdata_mcheck {
-    u_long      coma_gcr;                       
-    u_long      coma_edsr;                      
-    u_long      coma_ter;                       
-    u_long      coma_elar;                      
-    u_long      coma_ehar;                      
-    u_long      coma_ldlr;                      
-    u_long      coma_ldhr;                      
-    u_long      coma_base0;                     
-    u_long      coma_base1;                     
-    u_long      coma_base2;                     
-    u_long      coma_cnfg0;                     
-    u_long      coma_cnfg1;                     
-    u_long      coma_cnfg2;                     
-    u_long      epic_dcsr;                      
-    u_long      epic_pear;                      
-    u_long      epic_sear;                      
-    u_long      epic_tbr1;                      
-    u_long      epic_tbr2;                      
-    u_long      epic_pbr1;                      
-    u_long      epic_pbr2;                      
-    u_long      epic_pmr1;                      
-    u_long      epic_pmr2;                      
-    u_long      epic_harx1;                     
-    u_long      epic_harx2;                     
-    u_long      epic_pmlt;                      
-    u_long      epic_tag0;                      
-    u_long      epic_tag1;                      
-    u_long      epic_tag2;                      
-    u_long      epic_tag3;                      
-    u_long      epic_tag4;                      
-    u_long      epic_tag5;                      
-    u_long      epic_tag6;                      
-    u_long      epic_tag7;                      
-    u_long      epic_data0;                     
-    u_long      epic_data1;                     
-    u_long      epic_data2;                     
-    u_long      epic_data3;                     
-    u_long      epic_data4;                     
-    u_long      epic_data5;                     
-    u_long      epic_data6;                     
-    u_long      epic_data7;                     
+    u_long      coma_gcr;
+    u_long      coma_edsr;
+    u_long      coma_ter;
+    u_long      coma_elar;
+    u_long      coma_ehar;
+    u_long      coma_ldlr;
+    u_long      coma_ldhr;
+    u_long      coma_base0;
+    u_long      coma_base1;
+    u_long      coma_base2;
+    u_long      coma_cnfg0;
+    u_long      coma_cnfg1;
+    u_long      coma_cnfg2;
+    u_long      epic_dcsr;
+    u_long      epic_pear;
+    u_long      epic_sear;
+    u_long      epic_tbr1;
+    u_long      epic_tbr2;
+    u_long      epic_pbr1;
+    u_long      epic_pbr2;
+    u_long      epic_pmr1;
+    u_long      epic_pmr2;
+    u_long      epic_harx1;
+    u_long      epic_harx2;
+    u_long      epic_pmlt;
+    u_long      epic_tag0;
+    u_long      epic_tag1;
+    u_long      epic_tag2;
+    u_long      epic_tag3;
+    u_long      epic_tag4;
+    u_long      epic_tag5;
+    u_long      epic_tag6;
+    u_long      epic_tag7;
+    u_long      epic_data0;
+    u_long      epic_data1;
+    u_long      epic_data2;
+    u_long      epic_data3;
+    u_long      epic_data4;
+    u_long      epic_data5;
+    u_long      epic_data6;
+    u_long      epic_data7;
 };
 
 
@@ -363,8 +371,8 @@
 /*
  * Memory functions.  64-bit and 32-bit accesses are done through
  * dense memory space, everything else through sparse space.
- * 
- * For reading and writing 8 and 16 bit quantities we need to 
+ *
+ * For reading and writing 8 and 16 bit quantities we need to
  * go through one of the three sparse address mapping regions
  * and use the HAE_MEM CSR to provide some bits of the address.
  * The following few routines use only sparse address region 1
@@ -373,10 +381,10 @@
  * See p 6-17 of the specification but it looks something like this:
  *
  * 21164 Address:
- * 
- *          3         2         1                                                               
+ *
+ *          3         2         1
  * 9876543210987654321098765432109876543210
- * 1ZZZZ0.PCI.QW.Address............BBLL                 
+ * 1ZZZZ0.PCI.QW.Address............BBLL
  *
  * ZZ = SBZ
  * BB = Byte offset
@@ -384,60 +392,136 @@
  *
  * PCI Address:
  *
- * 3         2         1                                                               
+ * 3         2         1
  * 10987654321098765432109876543210
  * HHH....PCI.QW.Address........ 00
  *
  * HHH = 31:29 HAE_MEM CSR
- * 
+ *
  */
 
 __EXTERN_INLINE unsigned long pyxis_bw_readb(unsigned long addr)
 {
-	return __kernel_ldbu(*(vucp)(addr+PYXIS_BW_MEM));
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += PYXIS_BW_MEM;
+	}
+#endif
+
+	return __kernel_ldbu(*(vucp)addr);
 }
 
 __EXTERN_INLINE unsigned long pyxis_bw_readw(unsigned long addr)
 {
-	return __kernel_ldwu(*(vusp)(addr+PYXIS_BW_MEM));
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += PYXIS_BW_MEM;
+	}
+#endif
+
+	return __kernel_ldwu(*(vusp)addr);
 }
 
 __EXTERN_INLINE unsigned long pyxis_bw_readl(unsigned long addr)
 {
-	return *(vuip)(addr+PYXIS_BW_MEM);
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += PYXIS_BW_MEM;
+	}
+#endif
+
+	return *(vuip)addr;
 }
 
 __EXTERN_INLINE unsigned long pyxis_bw_readq(unsigned long addr)
 {
-	return *(vulp)(addr+PYXIS_BW_MEM);
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += PYXIS_BW_MEM;
+	}
+#endif
+
+	return *(vulp)addr;
 }
 
 __EXTERN_INLINE void pyxis_bw_writeb(unsigned char b, unsigned long addr)
 {
-	__kernel_stb(b, *(vucp)(addr+PYXIS_BW_MEM));
-	mb();
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += PYXIS_BW_MEM;
+	}
+#endif
+
+	__kernel_stb(b, *(vucp)addr);
 }
 
 __EXTERN_INLINE void pyxis_bw_writew(unsigned short b, unsigned long addr)
 {
-	__kernel_stw(b, *(vusp)(addr+PYXIS_BW_MEM));
-	mb();
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += PYXIS_BW_MEM;
+	}
+#endif
+
+	__kernel_stw(b, *(vusp)addr);
 }
 
 __EXTERN_INLINE void pyxis_bw_writel(unsigned int b, unsigned long addr)
 {
-	*(vuip)(addr+PYXIS_BW_MEM) = b;
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += PYXIS_BW_MEM;
+	}
+#endif
+
+	*(vuip)addr = b;
 }
 
 __EXTERN_INLINE void pyxis_bw_writeq(unsigned long b, unsigned long addr)
 {
-	*(vulp)(addr+PYXIS_BW_MEM) = b;
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += PYXIS_BW_MEM;
+	}
+#endif
+
+	*(vulp)addr = b;
+}
+
+__EXTERN_INLINE unsigned long pyxis_bw_ioremap(unsigned long addr)
+{
+	return PYXIS_BW_MEM + addr;
 }
 
 __EXTERN_INLINE unsigned long pyxis_srm_base(unsigned long addr)
 {
 	unsigned long mask, base;
 
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += PYXIS_BW_MEM;
+	}
+#endif
+
+	addr -= PYXIS_BW_MEM;
 	if (addr >= alpha_mv.sm_base_r1
 	    && addr <= alpha_mv.sm_base_r1 + PYXIS_MEM_R1_MASK) {
 		mask = PYXIS_MEM_R1_MASK;
@@ -490,19 +574,21 @@
 
 __EXTERN_INLINE void pyxis_srm_writeb(unsigned char b, unsigned long addr)
 {
-	unsigned long work = pyxis_srm_base(addr);
+	unsigned long w, work = pyxis_srm_base(addr);
 	if (work) {
 		work += 0x00;	/* add transfer length */
-		*(vuip) work = b * 0x01010101;
+		w = __kernel_insbl(b, addr & 3);
+		*(vuip)work = w;
 	}
 }
 
 __EXTERN_INLINE void pyxis_srm_writew(unsigned short b, unsigned long addr)
 {
-	unsigned long work = pyxis_srm_base(addr);
+	unsigned long w, work = pyxis_srm_base(addr);
 	if (work) {
 		work += 0x08;	/* add transfer length */
-		*(vuip) work = b * 0x00010001;
+		w = __kernel_inswl(b, addr & 3);
+		*(vuip)work = w;
 	}
 }
 
@@ -510,8 +596,17 @@
 {
 	unsigned long result, msb, work, temp;
 
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+	}
+#endif
+
+	/* Note that PYXIS_DENSE_MEM has no bits not masked in these
+	   operations, so we don't have to subtract it back out.  */
 	msb = addr & 0xE0000000UL;
-	temp = addr & PYXIS_MEM_R1_MASK ;
+	temp = addr & PYXIS_MEM_R1_MASK;
 	set_hae(msb);
 
 	work = ((temp << 5) + PYXIS_SPARSE_MEM + 0x00);
@@ -523,8 +618,17 @@
 {
 	unsigned long result, msb, work, temp;
 
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+	}
+#endif
+
+	/* Note that PYXIS_DENSE_MEM has no bits not masked in these
+	   operations, so we don't have to subtract it back out.  */
 	msb = addr & 0xE0000000UL;
-	temp = addr & PYXIS_MEM_R1_MASK ;
+	temp = addr & PYXIS_MEM_R1_MASK;
 	set_hae(msb);
 
 	work = ((temp << 5) + PYXIS_SPARSE_MEM + 0x08);
@@ -534,51 +638,106 @@
 
 __EXTERN_INLINE void pyxis_writeb(unsigned char b, unsigned long addr)
 {
-        unsigned long msb ; 
+	unsigned long msb, w;
+
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+	}
+#endif
 
-	msb = addr & 0xE0000000 ;
-	addr &= PYXIS_MEM_R1_MASK ;
+	/* Note that PYXIS_DENSE_MEM has no bits not masked in these
+	   operations, so we don't have to subtract it back out.  */
+	msb = addr & 0xE0000000;
+	addr &= PYXIS_MEM_R1_MASK;
 	set_hae(msb);
 
-	*(vuip) ((addr << 5) + PYXIS_SPARSE_MEM + 0x00) = b * 0x01010101;
+	w = __kernel_insbl(b, addr & 3);
+	*(vuip) ((addr << 5) + PYXIS_SPARSE_MEM + 0x00) = w;
 }
 
 __EXTERN_INLINE void pyxis_writew(unsigned short b, unsigned long addr)
 {
-        unsigned long msb ; 
+	unsigned long msb, w;
+
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+	}
+#endif
 
-	msb = addr & 0xE0000000 ;
-	addr &= PYXIS_MEM_R1_MASK ;
+	/* Note that PYXIS_DENSE_MEM has no bits not masked in these
+	   operations, so we don't have to subtract it back out.  */
+	msb = addr & 0xE0000000;
+	addr &= PYXIS_MEM_R1_MASK;
 	set_hae(msb);
 
-	*(vuip) ((addr << 5) + PYXIS_SPARSE_MEM + 0x08) = b * 0x00010001;
+	w = __kernel_inswl(b, addr & 3);
+	*(vuip) ((addr << 5) + PYXIS_SPARSE_MEM + 0x08) = w;
 }
 
 __EXTERN_INLINE unsigned long pyxis_readl(unsigned long addr)
 {
-	return *(vuip) (addr + PYXIS_DENSE_MEM);
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += PYXIS_DENSE_MEM;
+	}
+#endif
+
+	return *(vuip)addr;
 }
 
 __EXTERN_INLINE unsigned long pyxis_readq(unsigned long addr)
 {
-	return *(vulp) (addr + PYXIS_DENSE_MEM);
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += PYXIS_DENSE_MEM;
+	}
+#endif
+
+	return *(vulp)addr;
 }
 
 __EXTERN_INLINE void pyxis_writel(unsigned int b, unsigned long addr)
 {
-	*(vuip) (addr + PYXIS_DENSE_MEM) = b;
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += PYXIS_DENSE_MEM;
+	}
+#endif
+
+	*(vuip)addr = b;
 }
 
 __EXTERN_INLINE void pyxis_writeq(unsigned long b, unsigned long addr)
 {
-	*(vulp) (addr + PYXIS_DENSE_MEM) = b;
+#if __DEBUG_IOREMAP
+	if (addr <= 0x100000000) {
+		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr += PYXIS_DENSE_MEM;
+	}
+#endif
+
+	*(vulp)addr = b;
 }
 
-/* Find the DENSE memory area for a given bus address.  */
+__EXTERN_INLINE unsigned long pyxis_ioremap(unsigned long addr)
+{
+	return PYXIS_DENSE_MEM + addr;
+}
 
-__EXTERN_INLINE unsigned long pyxis_dense_mem(unsigned long addr)
+__EXTERN_INLINE int pyxis_is_ioaddr(unsigned long addr)
 {
-	return PYXIS_DENSE_MEM;
+	return addr >= IDENT_ADDR + 0x8000000000UL;
 }
 
 #undef vucp
@@ -607,6 +766,7 @@
 # define __readq	pyxis_bw_readq
 # define __writel	pyxis_bw_writel
 # define __writeq	pyxis_bw_writeq
+# define __ioremap	pyxis_bw_ioremap
 #else
 # define __inb		pyxis_inb
 # define __inw		pyxis_inw
@@ -629,21 +789,24 @@
 # define __readq	pyxis_readq
 # define __writel	pyxis_writel
 # define __writeq	pyxis_writeq
+# define __ioremap	pyxis_ioremap
 #endif /* BWIO */
 
-#define dense_mem	pyxis_dense_mem
+#define __is_ioaddr	pyxis_is_ioaddr
 
 #if defined(BWIO_ENABLED) && !defined(CONFIG_ALPHA_RUFFIAN)
-# define inb(port) __inb((port))
-# define inw(port) __inw((port))
-# define inl(port) __inl((port))
-# define outb(x, port) __outb((x),(port))
-# define outw(x, port) __outw((x),(port))
-# define outl(x, port) __outl((x),(port))
-# define readb(addr) __readb((addr))
-# define readw(addr) __readw((addr))
-# define writeb(b, addr) __writeb((b),(addr))
-# define writew(b, addr) __writew((b),(addr))
+# define inb(port)		__inb((port))
+# define inw(port)		__inw((port))
+# define inl(port)		__inl((port))
+# define outb(x, port)		__outb((x),(port))
+# define outw(x, port)		__outw((x),(port))
+# define outl(x, port)		__outl((x),(port))
+# if !__DEBUG_IOREMAP
+#  define __raw_readb(addr)	__readb((addr))
+#  define __raw_readw(addr)	__readw((addr))
+#  define __raw_writeb(b, addr)	__writeb((b),(addr))
+#  define __raw_writeb(b, addr)	__writew((b),(addr))
+# endif
 #else
 # define inb(port) \
   (__builtin_constant_p((port))?__inb(port):_inb(port))
@@ -651,10 +814,12 @@
   (__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port)))
 #endif /* BWIO */
 
-#define readl(a)	__readl((unsigned long)(a))
-#define readq(a)	__readq((unsigned long)(a))
-#define writel(v,a)	__writel((v),(unsigned long)(a))
-#define writeq(v,a)	__writeq((v),(unsigned long)(a))
+#if !__DEBUG_IOREMAP
+#define __raw_readl(a)		__readl((unsigned long)(a))
+#define __raw_readq(a)		__readq((unsigned long)(a))
+#define __raw_writel(v,a)	__writel((v),(unsigned long)(a))
+#define __raw_writeq(v,a)	__writeq((v),(unsigned long)(a))
+#endif
 
 #endif /* __WANT_IO_DEF */
 
diff -u --recursive --new-file v2.3.13/linux/include/asm-alpha/core_t2.h linux/include/asm-alpha/core_t2.h
--- v2.3.13/linux/include/asm-alpha/core_t2.h	Sun Dec 27 15:21:50 1998
+++ linux/include/asm-alpha/core_t2.h	Mon Aug 16 10:33:58 1999
@@ -78,33 +78,33 @@
  3.8fff.ffff
  *
  *  +--------------+ 3 8000 0000
- *  | CPU 0 CSRs   |            
+ *  | CPU 0 CSRs   |
  *  +--------------+ 3 8100 0000
- *  | CPU 1 CSRs   |            
+ *  | CPU 1 CSRs   |
  *  +--------------+ 3 8200 0000
- *  | CPU 2 CSRs   |            
+ *  | CPU 2 CSRs   |
  *  +--------------+ 3 8300 0000
- *  | CPU 3 CSRs   |            
+ *  | CPU 3 CSRs   |
  *  +--------------+ 3 8400 0000
- *  | CPU Reserved |            
+ *  | CPU Reserved |
  *  +--------------+ 3 8700 0000
- *  | Mem Reserved |            
+ *  | Mem Reserved |
  *  +--------------+ 3 8800 0000
- *  | Mem 0 CSRs   |            
+ *  | Mem 0 CSRs   |
  *  +--------------+ 3 8900 0000
- *  | Mem 1 CSRs   |            
+ *  | Mem 1 CSRs   |
  *  +--------------+ 3 8a00 0000
- *  | Mem 2 CSRs   |            
+ *  | Mem 2 CSRs   |
  *  +--------------+ 3 8b00 0000
- *  | Mem 3 CSRs   |            
- *  +--------------+ 3 8c00 0000           
- *  | Mem Reserved |            
- *  +--------------+ 3 8e00 0000           
- *  | PCI Bridge   |            
- *  +--------------+ 3 8f00 0000           
- *  | Expansion IO |            
- *  +--------------+ 3 9000 0000           
- *                                              
+ *  | Mem 3 CSRs   |
+ *  +--------------+ 3 8c00 0000
+ *  | Mem Reserved |
+ *  +--------------+ 3 8e00 0000
+ *  | PCI Bridge   |
+ *  +--------------+ 3 8f00 0000
+ *  | Expansion IO |
+ *  +--------------+ 3 9000 0000
+ *
  *
  */
 #define T2_CPU0_BASE            (IDENT_ADDR + GAMMA_BIAS + 0x380000000L)
@@ -176,7 +176,7 @@
 	unsigned long	elfmc_bc_tag;	/* Backup Cache Tag Probe Results. */
 };
 
-/* 
+/*
  * Sable processor specific Machine Check Data segment.
  */
 
@@ -184,7 +184,7 @@
 	unsigned int	elfl_size;	/* size in bytes of logout area. */
 	int		elfl_sbz1:31;	/* Should be zero. */
 	char		elfl_retry:1;	/* Retry flag. */
-        unsigned int	elfl_procoffset; /* Processor-specific offset. */
+	unsigned int	elfl_procoffset; /* Processor-specific offset. */
 	unsigned int	elfl_sysoffset;	 /* Offset of system-specific. */
 	unsigned int	elfl_error_type;	/* PAL error type code. */
 	unsigned int	elfl_frame_rev;		/* PAL Frame revision. */
@@ -233,7 +233,7 @@
  */
 struct el_t2_data_other_cpu {
 	short	      elco_cpuid;	/* CPU ID */
-	short	      elco_res02[3];	
+	short	      elco_res02[3];
 	unsigned long elco_bcc;	/* CSR 0 */
 	unsigned long elco_bcce;	/* CSR 1 */
 	unsigned long elco_bccea;	/* CSR 2 */
@@ -256,7 +256,7 @@
  * Sable other CPU error frame - sable pfms section 3.44
  */
 struct el_t2_data_t2{
-        struct el_t2_frame_header elct_hdr;	/* ID$T2-FRAME */
+	struct el_t2_frame_header elct_hdr;	/* ID$T2-FRAME */
 	unsigned long elct_iocsr;	/* IO Control and Status Register */
 	unsigned long elct_cerr1;	/* Cbus Error Register 1 */
 	unsigned long elct_cerr2;	/* Cbus Error Register 2 */
@@ -294,31 +294,31 @@
 	unsigned long elcpb_bc_tag;
 };
 
-/* 
+/*
  * Sable error log data structure
  * Note there are 4 memory slots on sable (see t2.h)
  */
 struct el_t2_frame_mcheck {
-        struct el_t2_frame_header elfmc_header;	/* ID$P-FRAME_MCHECK */
+	struct el_t2_frame_header elfmc_header;	/* ID$P-FRAME_MCHECK */
 	struct el_t2_logout_header elfmc_hdr;
 	struct el_t2_procdata_mcheck elfmc_procdata;
 	struct el_t2_sysdata_mcheck elfmc_sysdata;
 	struct el_t2_data_t2 elfmc_t2data;
-	struct el_t2_data_memory elfmc_memdata[4]; 
-        struct el_t2_frame_header elfmc_footer;	/* empty */
+	struct el_t2_data_memory elfmc_memdata[4];
+	struct el_t2_frame_header elfmc_footer;	/* empty */
 };
 
 
-/* 
+/*
  * Sable error log data structures on memory errors
  */
 struct el_t2_frame_corrected {
-        struct el_t2_frame_header elfcc_header;	/* ID$P-BC-COR */
+	struct el_t2_frame_header elfcc_header;	/* ID$P-BC-COR */
 	struct el_t2_logout_header elfcc_hdr;
-	struct el_t2_data_corrected elfcc_procdata; 
+	struct el_t2_data_corrected elfcc_procdata;
 /*	struct el_t2_data_t2 elfcc_t2data;		*/
 /*	struct el_t2_data_memory elfcc_memdata[4];	*/
-        struct el_t2_frame_header elfcc_footer;	/* empty */
+	struct el_t2_frame_header elfcc_footer;	/* empty */
 };
 
 
@@ -398,10 +398,9 @@
 
 
 /*
- * Memory functions.  64-bit and 32-bit accesses are done through
- * dense memory space, everything else through sparse space.
- * 
- * For reading and writing 8 and 16 bit quantities we need to 
+ * Memory functions.
+ *
+ * For reading and writing 8 and 16 bit quantities we need to
  * go through one of the three sparse address mapping regions
  * and use the HAE_MEM CSR to provide some bits of the address.
  * The following few routines use only sparse address region 1
@@ -410,10 +409,10 @@
  * See p 6-17 of the specification but it looks something like this:
  *
  * 21164 Address:
- * 
- *          3         2         1                                                               
+ *
+ *          3         2         1
  * 9876543210987654321098765432109876543210
- * 1ZZZZ0.PCI.QW.Address............BBLL                 
+ * 1ZZZZ0.PCI.QW.Address............BBLL
  *
  * ZZ = SBZ
  * BB = Byte offset
@@ -421,12 +420,12 @@
  *
  * PCI Address:
  *
- * 3         2         1                                                               
+ * 3         2         1
  * 10987654321098765432109876543210
  * HHH....PCI.QW.Address........ 00
  *
  * HHH = 31:29 HAE_MEM CSR
- * 
+ *
  */
 
 __EXTERN_INLINE unsigned long t2_srm_base(unsigned long addr)
@@ -495,19 +494,21 @@
 
 __EXTERN_INLINE void t2_srm_writeb(unsigned char b, unsigned long addr)
 {
-	unsigned long work = t2_srm_base(addr);
+	unsigned long w, work = t2_srm_base(addr);
 	if (work) {
 		work += 0x00;	/* add transfer length */
-		*(vuip) work = b * 0x01010101;
+		w = __kernel_insbl(b, addr & 3);
+		*(vuip) work = w;
 	}
 }
 
 __EXTERN_INLINE void t2_srm_writew(unsigned short b, unsigned long addr)
 {
-	unsigned long work = t2_srm_base(addr);
+	unsigned long w, work = t2_srm_base(addr);
 	if (work) {
 		work += 0x08;	/* add transfer length */
-		*(vuip) work = b * 0x00010001;
+		w = __kernel_inswl(b, addr & 3);
+		*(vuip) work = w;
 	}
 }
 
@@ -537,11 +538,11 @@
 {
 	unsigned long result, msb;
 
-	msb = addr & 0xE0000000 ;
-	addr &= T2_MEM_R1_MASK ;
+	msb = addr & 0xE0000000;
+	addr &= T2_MEM_R1_MASK;
 	set_hae(msb);
 
-	result = *(vip) ((addr << 5) + T2_SPARSE_MEM + 0x00) ;
+	result = *(vip) ((addr << 5) + T2_SPARSE_MEM + 0x00);
 	return __kernel_extbl(result, addr & 3);
 }
 
@@ -549,8 +550,8 @@
 {
 	unsigned long result, msb;
 
-	msb = addr & 0xE0000000 ;
-	addr &= T2_MEM_R1_MASK ;
+	msb = addr & 0xE0000000;
+	addr &= T2_MEM_R1_MASK;
 	set_hae(msb);
 
 	result = *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x08);
@@ -562,8 +563,8 @@
 {
 	unsigned long msb;
 
-	msb = addr & 0xE0000000 ;
-	addr &= T2_MEM_R1_MASK ;
+	msb = addr & 0xE0000000;
+	addr &= T2_MEM_R1_MASK;
 	set_hae(msb);
 
 	return *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x18);
@@ -573,8 +574,8 @@
 {
 	unsigned long r0, r1, work, msb;
 
-	msb = addr & 0xE0000000 ;
-	addr &= T2_MEM_R1_MASK ;
+	msb = addr & 0xE0000000;
+	addr &= T2_MEM_R1_MASK;
 	set_hae(msb);
 
 	work = (addr << 5) + T2_SPARSE_MEM + 0x18;
@@ -585,33 +586,35 @@
 
 __EXTERN_INLINE void t2_writeb(unsigned char b, unsigned long addr)
 {
-        unsigned long msb ; 
+	unsigned long msb, w;
 
-	msb = addr & 0xE0000000 ;
-	addr &= T2_MEM_R1_MASK ;
+	msb = addr & 0xE0000000;
+	addr &= T2_MEM_R1_MASK;
 	set_hae(msb);
 
-	*(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x00) = b * 0x01010101;
+	w = __kernel_insbl(b, addr & 3);
+	*(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x00) = w;
 }
 
 __EXTERN_INLINE void t2_writew(unsigned short b, unsigned long addr)
 {
-        unsigned long msb ; 
+	unsigned long msb, w;
 
-	msb = addr & 0xE0000000 ;
-	addr &= T2_MEM_R1_MASK ;
+	msb = addr & 0xE0000000;
+	addr &= T2_MEM_R1_MASK;
 	set_hae(msb);
 
-	*(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x08) = b * 0x00010001;
+	w = __kernel_inswl(b, addr & 3);
+	*(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x08) = w;
 }
 
 /* On SABLE with T2, we must use SPARSE memory even for 32-bit access. */
 __EXTERN_INLINE void t2_writel(unsigned int b, unsigned long addr)
 {
-        unsigned long msb ; 
+	unsigned long msb;
 
-	msb = addr & 0xE0000000 ;
-	addr &= T2_MEM_R1_MASK ;
+	msb = addr & 0xE0000000;
+	addr &= T2_MEM_R1_MASK;
 	set_hae(msb);
 
 	*(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x18) = b;
@@ -619,10 +622,10 @@
 
 __EXTERN_INLINE void t2_writeq(unsigned long b, unsigned long addr)
 {
-        unsigned long msb, work;
+	unsigned long msb, work;
 
-	msb = addr & 0xE0000000 ;
-	addr &= T2_MEM_R1_MASK ;
+	msb = addr & 0xE0000000;
+	addr &= T2_MEM_R1_MASK;
 	set_hae(msb);
 
 	work = (addr << 5) + T2_SPARSE_MEM + 0x18;
@@ -630,11 +633,14 @@
 	*(vuip)(work + (4 << 5)) = b >> 32;
 }
 
-/* Find the DENSE memory area for a given bus address.  */
+__EXTERN_INLINE unsigned long t2_ioremap(unsigned long addr)
+{
+	return addr;
+}
 
-__EXTERN_INLINE unsigned long t2_dense_mem(unsigned long addr)
+__EXTERN_INLINE int t2_is_ioaddr(unsigned long addr)
 {
-	return T2_DENSE_MEM;
+	return (long)addr >= 0;
 }
 
 #undef vip
@@ -671,7 +677,8 @@
 #define __writeq	t2_writeq
 #endif
 
-#define dense_mem	t2_dense_mem
+#define __ioremap	t2_ioremap
+#define __is_ioaddr	t2_is_ioaddr
 
 #define inb(port) \
 (__builtin_constant_p((port))?__inb(port):_inb(port))
diff -u --recursive --new-file v2.3.13/linux/include/asm-alpha/core_tsunami.h linux/include/asm-alpha/core_tsunami.h
--- v2.3.13/linux/include/asm-alpha/core_tsunami.h	Sun Jan 10 09:59:59 1999
+++ linux/include/asm-alpha/core_tsunami.h	Mon Aug 16 10:33:58 1999
@@ -16,8 +16,24 @@
  *
  */
 
-#define TSUNAMI_DMA_WIN_BASE_DEFAULT    (1024*1024*1024U)
-#define TSUNAMI_DMA_WIN_SIZE_DEFAULT    (1024*1024*1024U)
+/*
+ * We must actually use 2 windows to direct-map the 2GB space, because
+ * of an "idiot-syncracy" of the CYPRESS chip used on DS20 and others.
+ * It may respond to a PCI bus address in the last 1MB of the 4GB
+ * address range, and that is where real memory may appear.
+ *
+ * Sigh...
+ */
+#define TSUNAMI_DMA_WIN_BASE_DEFAULT	(1UL*1024*1024*1024)
+#define TSUNAMI_DMA_WIN_SIZE_DEFAULT	(2UL*1024*1024*1024)
+
+#define TSUNAMI_DMA_WIN0_BASE_DEFAULT	(1UL*1024*1024*1024)
+#define TSUNAMI_DMA_WIN0_SIZE_DEFAULT	(1UL*1024*1024*1024)
+#define TSUNAMI_DMA_WIN0_TRAN_DEFAULT	(0UL)
+
+#define TSUNAMI_DMA_WIN1_BASE_DEFAULT	(2UL*1024*1024*1024)
+#define TSUNAMI_DMA_WIN1_SIZE_DEFAULT	(1UL*1024*1024*1024)
+#define TSUNAMI_DMA_WIN1_TRAN_DEFAULT	(1UL*1024*1024*1024)
 
 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
 #define TSUNAMI_DMA_WIN_BASE		alpha_mv.dma_win_base
@@ -142,7 +158,7 @@
 		unsigned perror_v_rsvd2 : 1;
 		unsigned perror_v_cmd : 4;
 		unsigned perror_v_syn : 8;
-        } perror_r_bits;
+	} perror_r_bits;
 	int perror_q_whole [2];
 };                       
 
@@ -162,7 +178,7 @@
 		unsigned wsba_v_rsvd1 : 17;
 		unsigned wsba_v_addr : 12;
 		unsigned wsba_v_rsvd2 : 32;
-        } wsba_r_bits;
+	} wsba_r_bits;
 	int wsba_q_whole [2];
 };
 
@@ -256,7 +272,7 @@
 		unsigned perrmask_v_cre : 1;                 
 		unsigned perrmask_v_rsvd1 : 20;
 		unsigned perrmask_v_rsvd2 : 32;
-        } perrmask_r_bits;
+	} perrmask_r_bits;
 	int perrmask_q_whole [2];
 };                       
 
@@ -353,55 +369,118 @@
  * Memory functions.  all accesses are done through linear space.
  */
 
+__EXTERN_INLINE unsigned long tsunami_ioremap(unsigned long addr)
+{
+	return XADDR + TSUNAMI_MEM(XHOSE);
+}
+
+__EXTERN_INLINE int tsunami_is_ioaddr(unsigned long addr)
+{
+	return addr >= IDENT_ADDR+TS_BIAS;
+}
+
 __EXTERN_INLINE unsigned long tsunami_readb(unsigned long addr)
 {
-	return __kernel_ldbu(*(vucp)(XADDR + TSUNAMI_MEM(XHOSE)));
+#if __DEBUG_IOREMAP
+	if (addr <= 0x1000000000) {
+		printk(KERN_CRIT "tsunami: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr = tsunami_ioremap(addr);
+	}
+#endif
+
+	return __kernel_ldbu(*(vucp)addr);
 }
 
 __EXTERN_INLINE unsigned long tsunami_readw(unsigned long addr)
 {
-	return __kernel_ldwu(*(vusp)(XADDR + TSUNAMI_MEM(XHOSE)));
+#if __DEBUG_IOREMAP
+	if (addr <= 0x1000000000) {
+		printk(KERN_CRIT "tsunami: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr = tsunami_ioremap(addr);
+	}
+#endif
+
+	return __kernel_ldwu(*(vusp)addr);
 }
 
 __EXTERN_INLINE unsigned long tsunami_readl(unsigned long addr)
 {
-	return *(vuip)(XADDR + TSUNAMI_MEM(XHOSE));
+#if __DEBUG_IOREMAP
+	if (addr <= 0x1000000000) {
+		printk(KERN_CRIT "tsunami: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr = tsunami_ioremap(addr);
+	}
+#endif
+
+	return *(vuip)addr;
 }
 
 __EXTERN_INLINE unsigned long tsunami_readq(unsigned long addr)
 {
-	return *(vulp)(XADDR + TSUNAMI_MEM(XHOSE));
+#if __DEBUG_IOREMAP
+	if (addr <= 0x1000000000) {
+		printk(KERN_CRIT "tsunami: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr = tsunami_ioremap(addr);
+	}
+#endif
+
+	return *(vulp)addr;
 }
 
 __EXTERN_INLINE void tsunami_writeb(unsigned char b, unsigned long addr)
 {
-	__kernel_stb(b, *(vucp)(XADDR + TSUNAMI_MEM(XHOSE)));
-	mb();
+#if __DEBUG_IOREMAP
+	if (addr <= 0x1000000000) {
+		printk(KERN_CRIT "tsunami: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr = tsunami_ioremap(addr);
+	}
+#endif
+
+	__kernel_stb(b, *(vucp)addr);
 }
 
 __EXTERN_INLINE void tsunami_writew(unsigned short b, unsigned long addr)
 {
-	__kernel_stw(b, *(vusp)(XADDR + TSUNAMI_MEM(XHOSE)));
-	mb();
+#if __DEBUG_IOREMAP
+	if (addr <= 0x1000000000) {
+		printk(KERN_CRIT "tsunami: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr = tsunami_ioremap(addr);
+	}
+#endif
+
+	__kernel_stw(b, *(vusp)addr);
 }
 
 __EXTERN_INLINE void tsunami_writel(unsigned int b, unsigned long addr)
 {
-	*(vuip)(XADDR + TSUNAMI_MEM(XHOSE)) = b;
-	mb();
+#if __DEBUG_IOREMAP
+	if (addr <= 0x1000000000) {
+		printk(KERN_CRIT "tsunami: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr = tsunami_ioremap(addr);
+	}
+#endif
+
+	*(vuip)addr = b;
 }
 
 __EXTERN_INLINE void tsunami_writeq(unsigned long b, unsigned long addr)
 {
-	*(vulp)(XADDR + TSUNAMI_MEM(XHOSE)) = b;
-	mb();
-}
-
-/* Find the DENSE memory area for a given bus address.  */
+#if __DEBUG_IOREMAP
+	if (addr <= 0x1000000000) {
+		printk(KERN_CRIT "tsunami: 0x%lx not ioremapped (%p)\n",
+		       addr, __builtin_return_address(0));
+		addr = tsunami_ioremap(addr);
+	}
+#endif
 
-__EXTERN_INLINE unsigned long tsunami_dense_mem(unsigned long addr)
-{
-	return TSUNAMI_MEM(XHOSE);
+	*(vulp)addr = b;
 }
 
 #undef vucp
@@ -431,7 +510,8 @@
 #define __readq		tsunami_readq
 #define __writel	tsunami_writel
 #define __writeq	tsunami_writeq
-#define dense_mem	tsunami_dense_mem
+#define __ioremap	tsunami_ioremap
+#define __is_ioaddr	tsunami_is_ioaddr
 
 #define inb(port) __inb((port))
 #define inw(port) __inw((port))
@@ -441,15 +521,16 @@
 #define outw(v, port) __outw((v),(port))
 #define outl(v, port) __outl((v),(port))
 
-#define readb(a)	__readb((unsigned long)(a))
-#define readw(a)	__readw((unsigned long)(a))
-#define readl(a)	__readl((unsigned long)(a))
-#define readq(a)	__readq((unsigned long)(a))
-
-#define writeb(v,a)	__writeb((v),(unsigned long)(a))
-#define writew(v,a)	__writew((v),(unsigned long)(a))
-#define writel(v,a)	__writel((v),(unsigned long)(a))
-#define writeq(v,a)	__writeq((v),(unsigned long)(a))
+#if !__DEBUG_IOREMAP
+#define __raw_readb(a)		__readb((unsigned long)(a))
+#define __raw_readw(a)		__readw((unsigned long)(a))
+#define __raw_readl(a)		__readl((unsigned long)(a))
+#define __raw_readq(a)		__readq((unsigned long)(a))
+#define __raw_writeb(v,a)	__writeb((v),(unsigned long)(a))
+#define __raw_writeb(v,a)	__writew((v),(unsigned long)(a))
+#define __raw_writel(v,a)	__writel((v),(unsigned long)(a))
+#define __raw_writeq(v,a)	__writeq((v),(unsigned long)(a))
+#endif
 
 #endif /* __WANT_IO_DEF */
 
diff -u --recursive --new-file v2.3.13/linux/include/asm-alpha/io.h linux/include/asm-alpha/io.h
--- v2.3.13/linux/include/asm-alpha/io.h	Mon Aug  9 14:59:23 1999
+++ linux/include/asm-alpha/io.h	Mon Aug 16 10:33:58 1999
@@ -1,7 +1,10 @@
 #ifndef __ALPHA_IO_H
 #define __ALPHA_IO_H
 
+#define __DEBUG_IOREMAP 1
+
 #include <linux/config.h>
+#include <linux/kernel.h>
 #include <asm/system.h>
 
 /* We don't use IO slowdowns on the Alpha, but.. */
@@ -103,6 +106,9 @@
 # define __writel(v,a)	alpha_mv.mv_writel((v),(unsigned long)(a))
 # define __writeq(v,a)	alpha_mv.mv_writeq((v),(unsigned long)(a))
 
+# define __ioremap(a)	alpha_mv.mv_ioremap(a)
+# define __is_ioaddr(a)	alpha_mv.mv_is_ioaddr(a)
+
 # define inb		__inb
 # define inw		__inw
 # define inl		__inl
@@ -110,16 +116,14 @@
 # define outw		__outw
 # define outl		__outl
 
-# define readb		__readb
-# define readw		__readw
-# define readl		__readl
-# define readq		__readq
-# define writeb		__writeb
-# define writew		__writew
-# define writel		__writel
-# define writeq		__writeq
-
-# define dense_mem(a)	alpha_mv.mv_dense_mem(a)
+# define __raw_readb	__readb
+# define __raw_readw	__readw
+# define __raw_readl	__readl
+# define __raw_readq	__readq
+# define __raw_writeb	__writeb
+# define __raw_writeb	__writew
+# define __raw_writel	__writel
+# define __raw_writeq	__writeq
 
 #else
 
@@ -244,21 +248,85 @@
 #ifdef __KERNEL__
 
 /*
- * The "address" in IO memory space is not clearly either an integer or a
- * pointer. We will accept both, thus the casts.
+ * On Alpha, we have the whole of I/O space mapped at all times, but
+ * at odd and sometimes discontinuous addresses.  Note that the 
+ * discontinuities are all across busses, so we need not care for that
+ * for any one device.
  *
- * On the alpha, we have the whole physical address space mapped at all
- * times, so "ioremap()" and "iounmap()" do not need to do anything.
+ * Map the I/O space address into the kernel's virtual address space.
  */
 static inline void * ioremap(unsigned long offset, unsigned long size)
 {
-	return (void *) offset;
+	return (void *) __ioremap(offset);
 } 
 
 static inline void iounmap(void *addr)
 {
 }
 
+/* Indirect back to the macros provided.  */
+
+extern unsigned long	___raw_readb(unsigned long addr);
+extern unsigned long	___raw_readw(unsigned long addr);
+extern unsigned long	___raw_readl(unsigned long addr);
+extern unsigned long	___raw_readq(unsigned long addr);
+extern void		___raw_writeb(unsigned char b, unsigned long addr);
+extern void		___raw_writeb(unsigned short b, unsigned long addr);
+extern void		___raw_writel(unsigned int b, unsigned long addr);
+extern void		___raw_writeq(unsigned long b, unsigned long addr);
+
+#ifdef __raw_readb
+# define readb(a)	({ unsigned long r_ = __raw_readb(a); mb(); r_; })
+#endif
+#ifdef __raw_readw
+# define readw(a)	({ unsigned long r_ = __raw_readw(a); mb(); r_; })
+#endif
+#ifdef __raw_readl
+# define readl(a)	({ unsigned long r_ = __raw_readl(a); mb(); r_; })
+#endif
+#ifdef __raw_readq
+# define readq(a)	({ unsigned long r_ = __raw_readq(a); mb(); r_; })
+#endif
+
+#ifdef __raw_writeb
+# define writeb(v,a)	({ __raw_writeb((v),(a)); mb(); })
+#endif
+#ifdef __raw_writeb
+# define writew(v,a)	({ __raw_writeb((v),(a)); mb(); })
+#endif
+#ifdef __raw_writel
+# define writel(v,a)	({ __raw_writel((v),(a)); mb(); })
+#endif
+#ifdef __raw_writeq
+# define writeq(v,a)	({ __raw_writeq((v),(a)); mb(); })
+#endif
+
+#ifndef __raw_readb
+# define __raw_readb(a)	___raw_readb((unsigned long)(a))
+#endif
+#ifndef __raw_readw
+# define __raw_readw(a)	___raw_readw((unsigned long)(a))
+#endif
+#ifndef __raw_readl
+# define __raw_readl(a)	___raw_readl((unsigned long)(a))
+#endif
+#ifndef __raw_readq
+# define __raw_readq(a)	___raw_readq((unsigned long)(a))
+#endif
+
+#ifndef __raw_writeb
+# define __raw_writeb(v,a)  ___raw_writeb((v),(unsigned long)(a))
+#endif
+#ifndef __raw_writeb
+# define __raw_writeb(v,a)  ___raw_writeb((v),(unsigned long)(a))
+#endif
+#ifndef __raw_writel
+# define __raw_writel(v,a)  ___raw_writel((v),(unsigned long)(a))
+#endif
+#ifndef __raw_writeq
+# define __raw_writeq(v,a)  ___raw_writeq((v),(unsigned long)(a))
+#endif
+
 #ifndef readb
 # define readb(a)	_readb((unsigned long)(a))
 #endif
@@ -271,6 +339,7 @@
 #ifndef readq
 # define readq(a)	_readq((unsigned long)(a))
 #endif
+
 #ifndef writeb
 # define writeb(v,a)	_writeb((v),(unsigned long)(a))
 #endif
diff -u --recursive --new-file v2.3.13/linux/include/asm-alpha/jensen.h linux/include/asm-alpha/jensen.h
--- v2.3.13/linux/include/asm-alpha/jensen.h	Thu Jan 21 13:59:39 1999
+++ linux/include/asm-alpha/jensen.h	Mon Aug 16 10:33:58 1999
@@ -292,12 +292,14 @@
 	*(vuip) (addr + (4 << 7)) = b >> 32;
 }
 
-/* Find the DENSE memory area for a given bus address.
-   Whee, there is none.  */
+__EXTERN_INLINE unsigned long jensen_ioremap(unsigned long addr)
+{
+	return addr;
+}
 
-__EXTERN_INLINE unsigned long jensen_dense_mem(unsigned long addr)
+__EXTERN_INLINE int jensen_is_ioaddr(unsigned long addr)
 {
-	return 0;
+	return (long)addr >= 0;
 }
 
 #undef vuip
@@ -320,7 +322,8 @@
 #define __readq		jensen_readq
 #define __writel	jensen_writel
 #define __writeq	jensen_writeq
-#define dense_mem	jensen_dense_mem
+#define __ioremap	jensen_ioremap
+#define __is_ioaddr	jensen_is_ioaddr
 
 /*
  * The above have so much overhead that it probably doesn't make
diff -u --recursive --new-file v2.3.13/linux/include/asm-alpha/machvec.h linux/include/asm-alpha/machvec.h
--- v2.3.13/linux/include/asm-alpha/machvec.h	Mon Aug  9 14:59:23 1999
+++ linux/include/asm-alpha/machvec.h	Mon Aug 16 10:33:58 1999
@@ -56,7 +56,8 @@
 	void (*mv_writel)(unsigned int, unsigned long);
 	void (*mv_writeq)(unsigned long, unsigned long);
 
-	unsigned long (*mv_dense_mem)(unsigned long);
+	unsigned long (*mv_ioremap)(unsigned long);
+	int (*mv_is_ioaddr)(unsigned long);
 
 	int (*hose_read_config_byte)(u8, u8, u8, u8 *value,
 				     struct linux_hose_info *);
diff -u --recursive --new-file v2.3.13/linux/include/asm-alpha/smp.h linux/include/asm-alpha/smp.h
--- v2.3.13/linux/include/asm-alpha/smp.h	Wed Jul 21 15:46:48 1999
+++ linux/include/asm-alpha/smp.h	Mon Aug 16 10:33:58 1999
@@ -1,10 +1,25 @@
 #ifndef __ASM_SMP_H
 #define __ASM_SMP_H
 
+#include <asm/pal.h>
+
+/* HACK: Cabrio WHAMI return value is bogus if more than 8 bits used.. :-( */
+
+static __inline__ unsigned char
+__hard_smp_processor_id(void)
+{
+	register unsigned char __r0 __asm__("$0");
+	__asm__ __volatile__(
+		"call_pal %1 #whami"
+		: "=r"(__r0)
+		:"i" (PAL_whami)
+		: "$1", "$22", "$23", "$24", "$25");
+	return __r0;
+}
+
 #ifdef __SMP__
 
 #include <linux/tasks.h>
-#include <asm/pal.h>
 
 struct cpuinfo_alpha {
 	unsigned long loops_per_sec;
@@ -16,6 +31,9 @@
 	unsigned long prof_multiplier;
 	unsigned long prof_counter;
 	int irq_count, bh_count;
+	unsigned char mcheck_expected;
+	unsigned char mcheck_taken;
+	unsigned char mcheck_hose;
 } __attribute__((aligned(64)));
 
 extern struct cpuinfo_alpha cpu_data[NR_CPUS];
@@ -30,19 +48,7 @@
 extern int __cpu_logical_map[NR_CPUS];
 #define cpu_logical_map(cpu)  __cpu_logical_map[cpu]
 
-/* HACK: Cabrio WHAMI return value is bogus if more than 8 bits used.. :-( */
-
-static __inline__ unsigned char hard_smp_processor_id(void)
-{
-	register unsigned char __r0 __asm__("$0");
-	__asm__ __volatile__(
-		"call_pal %1 #whami"
-		: "=r"(__r0)
-		:"i" (PAL_whami)
-		: "$1", "$22", "$23", "$24", "$25");
-	return __r0;
-}
-
+#define hard_smp_processor_id()	__hard_smp_processor_id()
 #define smp_processor_id()	(current->processor)
 
 #endif /* __SMP__ */
diff -u --recursive --new-file v2.3.13/linux/include/asm-alpha/vga.h linux/include/asm-alpha/vga.h
--- v2.3.13/linux/include/asm-alpha/vga.h	Thu Feb 25 10:02:12 1999
+++ linux/include/asm-alpha/vga.h	Mon Aug 16 10:33:58 1999
@@ -15,26 +15,26 @@
 
 extern inline void scr_writew(u16 val, u16 *addr)
 {
-	if ((long) addr < 0)
-		*addr = val;
-	else
+	if (__is_ioaddr((unsigned long) addr))
 		writew(val, (unsigned long) addr);
+	else
+		*addr = val;
 }
 
 extern inline u16 scr_readw(const u16 *addr)
 {
-	if ((long) addr < 0)
-		return *addr;
-	else
+	if (__is_ioaddr((unsigned long) addr))
 		return readw((unsigned long) addr);
+	else
+		return *addr;
 }
 
 extern inline void scr_memsetw(u16 *s, u16 c, unsigned int count)
 {
-	if ((long)s < 0)
-		memsetw(s, c, count);
-	else
+	if (__is_ioaddr((unsigned long) s))
 		memsetw_io(s, c, count);
+	else
+		memsetw(s, c, count);
 }
 
 extern inline void scr_memcpyw_from(u16 *d, const u16 *s, unsigned int count)
@@ -51,6 +51,6 @@
 #define vga_readb readb
 #define vga_writeb writeb
 
-#define VGA_MAP_MEM(x) (x)
+#define VGA_MAP_MEM(x)	((unsigned long) ioremap((x), 0))
 
 #endif
diff -u --recursive --new-file v2.3.13/linux/include/asm-i386/hw_irq.h linux/include/asm-i386/hw_irq.h
--- v2.3.13/linux/include/asm-i386/hw_irq.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-i386/hw_irq.h	Wed Aug 18 16:45:10 1999
@@ -0,0 +1,223 @@
+#ifndef _ASM_HW_IRQ_H
+#define _ASM_HW_IRQ_H
+
+/*
+ *	linux/include/asm/hw_irq.h
+ *
+ *	(C) 1992, 1993 Linus Torvalds, (C) 1997 Ingo Molnar
+ *
+ *	moved some of the old arch/i386/kernel/irq.h to here. VY
+ *
+ *	IRQ/IPI changes taken from work by Thomas Radke
+ *	<tomsoft@informatik.tu-chemnitz.de>
+ */
+
+#include <asm/irq.h>
+
+/*
+ * IDT vectors usable for external interrupt sources start
+ * at 0x20:
+ */
+#define FIRST_EXTERNAL_VECTOR	0x20
+
+#define SYSCALL_VECTOR		0x80
+
+/*
+ * Vectors 0x20-0x2f are used for ISA interrupts.
+ */
+
+/*
+ * Special IRQ vectors used by the SMP architecture:
+ *
+ * (some of the following vectors are 'rare', they are merged
+ *  into a single vector (FUNCTION_VECTOR) to save vector space.
+ *  TLB, reschedule and local APIC vectors are performance-critical.)
+ */
+#define RESCHEDULE_VECTOR	0x30
+#define INVALIDATE_TLB_VECTOR	0x31
+#define STOP_CPU_VECTOR		0x40
+#define LOCAL_TIMER_VECTOR	0x41
+#define CALL_FUNCTION_VECTOR	0x50
+
+/*
+ * First APIC vector available to drivers: (vectors 0x51-0xfe)
+ */
+#define IRQ0_TRAP_VECTOR	0x51
+
+/*
+ * This IRQ should never happen, but we print a message nevertheless.
+ */
+#define SPURIOUS_APIC_VECTOR	0xff
+
+extern int irq_vector[NR_IRQS];
+#define IO_APIC_VECTOR(irq)	irq_vector[irq]
+
+extern void init_IRQ_SMP(void);
+
+/*
+ * Various low-level irq details needed by irq.c, process.c,
+ * time.c, io_apic.c and smp.c
+ *
+ * Interrupt entry/exit code at both C and assembly level
+ */
+
+extern void no_action(int cpl, void *dev_id, struct pt_regs *regs);
+extern void mask_irq(unsigned int irq);
+extern void unmask_irq(unsigned int irq);
+extern void disable_8259A_irq(unsigned int irq);
+extern int i8259A_irq_pending(unsigned int irq);
+extern void ack_APIC_irq(void);
+extern void FASTCALL(send_IPI_self(int vector));
+extern void init_VISWS_APIC_irqs(void);
+extern void setup_IO_APIC(void);
+extern int IO_APIC_get_PCI_irq_vector(int bus, int slot, int fn);
+extern void make_8259A_irq(unsigned int irq);
+extern void send_IPI(int dest, int vector);
+extern void init_pic_mode(void);
+extern void print_IO_APIC(void);
+
+extern unsigned long io_apic_irqs;
+
+extern char _stext, _etext;
+
+#define MAX_IRQ_SOURCES 128
+#define MAX_MP_BUSSES 32
+enum mp_bustype {
+	MP_BUS_ISA,
+	MP_BUS_EISA,
+	MP_BUS_PCI
+};
+extern int mp_bus_id_to_type [MAX_MP_BUSSES];
+extern int mp_bus_id_to_pci_bus [MAX_MP_BUSSES];
+
+
+#ifdef __SMP__
+#define IO_APIC_IRQ(x) (((x) >= 16) || ((1<<(x)) & io_apic_irqs))
+
+#else
+
+#define IO_APIC_IRQ(x)	(0)
+
+#endif
+
+#define __STR(x) #x
+#define STR(x) __STR(x)
+
+#define SAVE_ALL \
+	"cld\n\t" \
+	"pushl %es\n\t" \
+	"pushl %ds\n\t" \
+	"pushl %eax\n\t" \
+	"pushl %ebp\n\t" \
+	"pushl %edi\n\t" \
+	"pushl %esi\n\t" \
+	"pushl %edx\n\t" \
+	"pushl %ecx\n\t" \
+	"pushl %ebx\n\t" \
+	"movl $" STR(__KERNEL_DS) ",%edx\n\t" \
+	"movl %dx,%ds\n\t" \
+	"movl %dx,%es\n\t"
+
+#define IRQ_NAME2(nr) nr##_interrupt(void)
+#define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
+
+#define GET_CURRENT \
+	"movl %esp, %ebx\n\t" \
+	"andl $-8192, %ebx\n\t"
+
+#ifdef __SMP__
+
+/*
+ *	SMP has a few special interrupts for IPI messages
+ */
+
+	/* there is a second layer of macro just to get the symbolic
+	   name for the vector evaluated. This change is for RTLinux */
+#define BUILD_SMP_INTERRUPT(x,v) XBUILD_SMP_INTERRUPT(x,v)
+#define XBUILD_SMP_INTERRUPT(x,v)\
+asmlinkage void x(void); \
+asmlinkage void call_##x(void); \
+__asm__( \
+"\n"__ALIGN_STR"\n" \
+SYMBOL_NAME_STR(x) ":\n\t" \
+	"pushl $"#v"\n\t" \
+	SAVE_ALL \
+	SYMBOL_NAME_STR(call_##x)":\n\t" \
+	"call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
+	"jmp ret_from_intr\n");
+
+#define BUILD_SMP_TIMER_INTERRUPT(x,v) XBUILD_SMP_TIMER_INTERRUPT(x,v)
+#define XBUILD_SMP_TIMER_INTERRUPT(x,v) \
+asmlinkage void x(struct pt_regs * regs); \
+asmlinkage void call_##x(void); \
+__asm__( \
+"\n"__ALIGN_STR"\n" \
+SYMBOL_NAME_STR(x) ":\n\t" \
+	"pushl $"#v"\n\t" \
+	SAVE_ALL \
+	"movl %esp,%eax\n\t" \
+	"pushl %eax\n\t" \
+	SYMBOL_NAME_STR(call_##x)":\n\t" \
+	"call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
+	"addl $4,%esp\n\t" \
+	"jmp ret_from_intr\n");
+
+#endif /* __SMP__ */
+
+#define BUILD_COMMON_IRQ() \
+asmlinkage void call_do_IRQ(void); \
+__asm__( \
+	"\n" __ALIGN_STR"\n" \
+	"common_interrupt:\n\t" \
+	SAVE_ALL \
+	"pushl $ret_from_intr\n\t" \
+	SYMBOL_NAME_STR(call_do_IRQ)":\n\t" \
+	"jmp "SYMBOL_NAME_STR(do_IRQ));
+
+/* 
+ * subtle. orig_eax is used by the signal code to distinct between
+ * system calls and interrupted 'random user-space'. Thus we have
+ * to put a negative value into orig_eax here. (the problem is that
+ * both system calls and IRQs want to have small integer numbers in
+ * orig_eax, and the syscall code has won the optimization conflict ;)
+ *
+ * Subtle as a pigs ear.  VY
+ */
+
+#define BUILD_IRQ(nr) \
+asmlinkage void IRQ_NAME(nr); \
+__asm__( \
+"\n"__ALIGN_STR"\n" \
+SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
+	"pushl $"#nr"-256\n\t" \
+	"jmp common_interrupt");
+
+/*
+ * x86 profiling function, SMP safe. We might want to do this in
+ * assembly totally?
+ */
+static inline void x86_do_profile (unsigned long eip)
+{
+	if (prof_buffer && current->pid) {
+		eip -= (unsigned long) &_stext;
+		eip >>= prof_shift;
+		/*
+		 * Don't ignore out-of-bounds EIP values silently,
+		 * put them into the last histogram slot, so if
+		 * present, they will show up as a sharp peak.
+		 */
+		if (eip > prof_len-1)
+			eip = prof_len-1;
+		atomic_inc((atomic_t *)&prof_buffer[eip]);
+	}
+}
+
+#ifdef __SMP__ /*more of this file should probably be ifdefed SMP */
+static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) {
+		send_IPI_self(IO_APIC_VECTOR(i));
+}
+#else
+static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) {}
+#endif
+
+#endif /* _ASM_HW_IRQ_H */
diff -u --recursive --new-file v2.3.13/linux/include/asm-i386/system.h linux/include/asm-i386/system.h
--- v2.3.13/linux/include/asm-i386/system.h	Mon Aug  9 14:59:23 1999
+++ linux/include/asm-i386/system.h	Wed Aug 18 16:43:29 1999
@@ -175,12 +175,10 @@
 #define wmb()	__asm__ __volatile__ ("": : :"memory")
 
 /* interrupt control.. */
-#define __sti() __asm__ __volatile__ ("sti": : :"memory")
-#define __cli() __asm__ __volatile__ ("cli": : :"memory")
-#define __save_flags(x) \
-__asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */ :"memory")
-#define __restore_flags(x) \
-__asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory")
+#define __save_flags(x)		__asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */ :"memory")
+#define __restore_flags(x) 	__asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory")
+#define __cli() 		__asm__ __volatile__("cli": : :"memory")
+#define __sti()			__asm__ __volatile__("sti": : :"memory")
 
 /* For spinlocks etc */
 #define local_irq_save(x)	__asm__ __volatile__("pushfl ; popl %0 ; cli":"=g" (x): /* no input */ :"memory")
diff -u --recursive --new-file v2.3.13/linux/include/asm-m68k/fpu.h linux/include/asm-m68k/fpu.h
--- v2.3.13/linux/include/asm-m68k/fpu.h	Tue May 13 22:41:17 1997
+++ linux/include/asm-m68k/fpu.h	Sun Aug 15 11:47:29 1999
@@ -11,6 +11,8 @@
 #define FPSTATESIZE (216/sizeof(unsigned char))
 #elif defined(CONFIG_M68040)
 #define FPSTATESIZE (96/sizeof(unsigned char))
+#elif defined(CONFIG_M68KFPU_EMU)
+#define FPSTATESIZE (28/sizeof(unsigned char))
 #elif defined(CONFIG_M68060)
 #define FPSTATESIZE (12/sizeof(unsigned char))
 #else
diff -u --recursive --new-file v2.3.13/linux/include/asm-m68k/irq.h linux/include/asm-m68k/irq.h
--- v2.3.13/linux/include/asm-m68k/irq.h	Mon Aug  9 14:59:23 1999
+++ linux/include/asm-m68k/irq.h	Sun Aug 15 11:47:29 1999
@@ -79,13 +79,17 @@
 extern void sys_free_irq(unsigned int, void *);
 
 /*
- * various flags for request_irq()
+ * various flags for request_irq() - the Amiga now uses the standard
+ * mechanism like all other architectures - SA_INTERRUPT and SA_SHIRQ
+ * are your friends.
  */
+#ifndef CONFIG_AMIGA
 #define IRQ_FLG_LOCK	(0x0001)	/* handler is not replaceable	*/
 #define IRQ_FLG_REPLACE	(0x0002)	/* replace existing handler	*/
 #define IRQ_FLG_FAST	(0x0004)
 #define IRQ_FLG_SLOW	(0x0008)
 #define IRQ_FLG_STD	(0x8000)	/* internally used		*/
+#endif
 
 /*
  * This structure is used to chain together the ISRs for a particular
diff -u --recursive --new-file v2.3.13/linux/include/asm-m68k/math-emu.h linux/include/asm-m68k/math-emu.h
--- v2.3.13/linux/include/asm-m68k/math-emu.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-m68k/math-emu.h	Sun Aug 15 11:47:29 1999
@@ -0,0 +1,300 @@
+#ifndef _ASM_M68K_SETUP_H
+#define _ASM_M68K_SETUP_H
+
+#include <asm/setup.h>
+#include <linux/linkage.h>
+
+/* Status Register bits */
+
+/* accrued exception bits */
+#define FPSR_AEXC_INEX	3
+#define FPSR_AEXC_DZ	4
+#define FPSR_AEXC_UNFL	5
+#define FPSR_AEXC_OVFL	6
+#define FPSR_AEXC_IOP	7
+
+/* exception status bits */
+#define FPSR_EXC_INEX1	8
+#define FPSR_EXC_INEX2	9
+#define FPSR_EXC_DZ	10
+#define FPSR_EXC_UNFL	11
+#define FPSR_EXC_OVFL	12
+#define FPSR_EXC_OPERR	13
+#define FPSR_EXC_SNAN	14
+#define FPSR_EXC_BSUN	15
+
+/* quotient byte, assumes big-endian, of course */
+#define FPSR_QUOTIENT(fpsr) (*((signed char *) &(fpsr) + 1))
+
+/* condition code bits */
+#define FPSR_CC_NAN	24
+#define FPSR_CC_INF	25
+#define FPSR_CC_Z	26
+#define FPSR_CC_NEG	27
+
+
+/* Control register bits */
+
+/* rounding mode */
+#define	FPCR_ROUND_RN	0		/* round to nearest/even */
+#define FPCR_ROUND_RZ	1		/* round to zero */
+#define FPCR_ROUND_RM	2		/* minus infinity */
+#define FPCR_ROUND_RP	3		/* plus infinity */
+
+/* rounding precision */
+#define FPCR_PRECISION_X	0	/* long double */
+#define FPCR_PRECISION_S	1	/* double */
+#define FPCR_PRECISION_D	2	/* float */
+
+
+/* Flags to select the debugging output */
+#define PDECODE		0
+#define PEXECUTE	1
+#define PCONV		2
+#define PNORM		3
+#define PREGISTER	4
+#define PINSTR		5
+#define PUNIMPL		6
+#define PMOVEM		7
+
+#define PMDECODE	(1<<PDECODE)
+#define PMEXECUTE	(1<<PEXECUTE)
+#define PMCONV		(1<<PCONV)
+#define PMNORM		(1<<PNORM)
+#define PMREGISTER	(1<<PREGISTER)
+#define PMINSTR		(1<<PINSTR)
+#define PMUNIMPL	(1<<PUNIMPL)
+#define PMMOVEM		(1<<PMOVEM)
+
+#ifndef __ASSEMBLY__
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+union fp_mant64 {
+	unsigned long long m64;
+	unsigned long m32[2];
+};
+
+union fp_mant128 {
+	unsigned long long m64[2];
+	unsigned long m32[4];
+};
+
+/* internal representation of extended fp numbers */
+struct fp_ext {
+	unsigned char lowmant;
+	unsigned char sign;
+	unsigned short exp;
+	union fp_mant64 mant;
+};
+
+/* C representation of FPU registers */
+/* NOTE: if you change this, you have to change the assembler offsets
+   below and the size in <asm/fpu.h>, too */
+struct fp_data {
+	struct fp_ext fpreg[8];
+	unsigned int fpcr;
+	unsigned int fpsr;
+	unsigned int fpiar;
+	unsigned short prec;
+	unsigned short rnd;
+	struct fp_ext temp[2];
+};
+
+#if FPU_EMU_DEBUG
+extern unsigned int fp_debugprint;
+
+#define dprint(bit, fmt, args...) ({			\
+	if (fp_debugprint & (1 << (bit)))		\
+		printk(fmt, ## args);			\
+})
+#else
+#define dprint(bit, fmt, args...)
+#endif
+
+#define uprint(str) ({					\
+	static int __count = 3;				\
+							\
+	if (__count > 0) {				\
+		printk("You just hit an unimplemented "	\
+		       "fpu instruction (%s)\n", str);	\
+		printk("Please report this to ....\n");	\
+		__count--;				\
+	}						\
+})
+
+#define FPDATA		((struct fp_data *)current->thread.fp)
+
+#else	/* __ASSEMBLY__ */
+
+#define FPDATA		%a2
+
+/* offsets from the base register to the floating point data in the task struct */
+#define FPD_FPREG	(TASK_THREAD+THREAD_FPREG+0)
+#define FPD_FPCR	(TASK_THREAD+THREAD_FPREG+96)
+#define FPD_FPSR	(TASK_THREAD+THREAD_FPREG+100)
+#define FPD_FPIAR	(TASK_THREAD+THREAD_FPREG+104)
+#define FPD_PREC	(TASK_THREAD+THREAD_FPREG+108)
+#define FPD_RND		(TASK_THREAD+THREAD_FPREG+110)
+#define FPD_TEMPFP1	(TASK_THREAD+THREAD_FPREG+112)
+#define FPD_TEMPFP2	(TASK_THREAD+THREAD_FPREG+124)
+#define FPD_SIZEOF	(TASK_THREAD+THREAD_FPREG+136)
+
+/* offsets on the stack to access saved registers,
+ * these are only used during instruction decoding
+ * where we always know how deep we're on the stack.
+ */
+#define FPS_DO		(PT_D0)
+#define FPS_D1		(PT_D1)
+#define FPS_D2		(PT_D2)
+#define FPS_A0		(PT_A0)
+#define FPS_A1		(PT_A1)
+#define FPS_A2		(PT_A2)
+#define FPS_SR		(PT_SR)
+#define FPS_PC		(PT_PC)
+#define FPS_EA		(PT_PC+6)
+#define FPS_PC2		(PT_PC+10)
+
+.macro	fp_get_fp_reg
+	lea	(FPD_FPREG,FPDATA,%d0.w*4),%a0
+	lea	(%a0,%d0.w*8),%a0
+.endm
+
+/* Macros used to get/put the current program counter.
+ * 020/030 use a different stack frame then 040/060, for the
+ * 040/060 the return pc points already to the next location,
+ * so this only needs to be modified for jump instructions.
+ */
+.macro	fp_get_pc dest
+	move.l	(FPS_PC+4,%sp),\dest
+.endm
+
+.macro	fp_put_pc src,jump=0
+	move.l	\src,(FPS_PC+4,%sp)
+.endm
+
+.macro	fp_get_instr_data	f,s,dest,label
+	getuser	\f,%sp@(FPS_PC+4)@(0),\dest,\label,%sp@(FPS_PC+4)
+	addq.l	#\s,%sp@(FPS_PC+4)
+.endm
+
+.macro	fp_get_instr_word	dest,label,addr
+	fp_get_instr_data	w,2,\dest,\label,\addr
+.endm
+
+.macro	fp_get_instr_long	dest,label,addr
+	fp_get_instr_data	l,4,\dest,\label,\addr
+.endm
+
+/* These macros are used to read from/write to user space
+ * on error we jump to the fixup section, load the fault
+ * address into %a0 and jump to the exit.
+ * (derived from <asm/uaccess.h>)
+ */
+.macro	getuser	size,src,dest,label,addr
+|	printf	,"[\size<%08x]",1,\addr
+.Lu1\@:	moves\size	\src,\dest
+
+	.section .fixup,"ax"
+	.even
+.Lu2\@:	move.l	\addr,%a0
+	jra	\label
+	.previous
+
+	.section __ex_table,"a"
+	.align	4
+	.long	.Lu1\@,.Lu2\@
+	.previous
+.endm
+
+.macro	putuser	size,src,dest,label,addr
+|	printf	,"[\size>%08x]",1,\addr
+.Lu1\@:	moves\size	\src,\dest
+.Lu2\@:
+
+	.section .fixup,"ax"
+	.even
+.Lu3\@:	move.l	\addr,%a0
+	jra	\label
+	.previous
+
+	.section __ex_table,"a"
+	.align	4
+	.long	.Lu1\@,.Lu3\@
+	.long	.Lu2\@,.Lu3\@
+	.previous
+.endm
+
+
+.macro	movestack	nr,arg1,arg2,arg3,arg4,arg5
+	.if	\nr
+	movestack	(\nr-1),\arg2,\arg3,\arg4,\arg5
+	move.l	\arg1,-(%sp)
+	.endif
+.endm
+
+.macro	printf	bit=-1,string,nr=0,arg1,arg2,arg3,arg4,arg5
+#ifdef FPU_EMU_DEBUG
+	.data
+.Lpdata\@:
+	.string	"\string"
+	.previous
+
+	movem.l	%d0/%d1/%a0/%a1,-(%sp)
+	.if	\bit+1
+#if 0
+	moveq	#\bit,%d0
+	andw	#7,%d0
+	btst	%d0,fp_debugprint+((31-\bit)/8)
+#else
+	btst	#\bit,fp_debugprint+((31-\bit)/8)
+#endif
+	jeq	.Lpskip\@
+	.endif
+	movestack	\nr,\arg1,\arg2,\arg3,\arg4,\arg5
+	pea	.Lpdata\@
+	jsr	printk
+	lea	((\nr+1)*4,%sp),%sp
+.Lpskip\@:
+	movem.l	(%sp)+,%d0/%d1/%a0/%a1
+#endif
+.endm
+
+.macro	printx	bit,fp
+#ifdef FPU_EMU_DEBUG
+	movem.l	%d0/%a0,-(%sp)
+	lea	\fp,%a0
+#if 0
+	moveq	#'+',%d0
+	tst.w	(%a0)
+	jeq	.Lx1\@
+	moveq	#'-',%d0
+.Lx1\@:	printf	\bit," %c",1,%d0
+	move.l	(4,%a0),%d0
+	bclr	#31,%d0
+	jne	.Lx2\@
+	printf	\bit,"0."
+	jra	.Lx3\@
+.Lx2\@:	printf	\bit,"1."
+.Lx3\@:	printf	\bit,"%08x%08x",2,%d0,%a0@(8)
+	move.w	(2,%a0),%d0
+	ext.l	%d0
+	printf	\bit,"E%04x",1,%d0
+#else
+	printf	\bit," %08x%08x%08x",3,%a0@,%a0@(4),%a0@(8)
+#endif
+	movem.l	(%sp)+,%d0/%a0
+#endif
+.endm
+
+.macro	debug	instr,args
+#ifdef FPU_EMU_DEBUG
+	\instr	\args
+#endif
+.endm
+
+
+#endif	/* __ASSEMBLY__ */
+
+#endif	/* _ASM_M68K_SETUP_H */
diff -u --recursive --new-file v2.3.13/linux/include/asm-m68k/setup.h linux/include/asm-m68k/setup.h
--- v2.3.13/linux/include/asm-m68k/setup.h	Tue May 11 09:57:14 1999
+++ linux/include/asm-m68k/setup.h	Sun Aug 15 11:47:29 1999
@@ -315,6 +315,16 @@
 
 #define CPU_TYPE (m68k_cputype)
 
+#ifdef CONFIG_M68KFPU_EMU
+#  ifdef CONFIG_M68KFPU_EMU_ONLY
+#    define FPU_IS_EMU (1)
+#  else
+#    define FPU_IS_EMU (!m68k_fputype)
+#  endif
+#else
+#  define FPU_IS_EMU (0)
+#endif
+
 
     /*
      *  Miscellaneous
diff -u --recursive --new-file v2.3.13/linux/include/linux/arcdevice.h linux/include/linux/arcdevice.h
--- v2.3.13/linux/include/linux/arcdevice.h	Wed Jul 28 14:47:42 1999
+++ linux/include/linux/arcdevice.h	Wed Aug 18 11:38:46 1999
@@ -298,28 +298,28 @@
   int card_type;
   char *card_type_str;
   
-  void (*inthandler) (struct device *dev);
-  int (*arcnet_reset) (struct device *dev, int reset_delay);
-  void (*asetmask) (struct device *dev, u_char mask);
-  void (*acommand) (struct device *dev, u_char command);
-  u_char (*astatus) (struct device *dev);
-  void (*en_dis_able_TX) (struct device *dev, int enable); 
-  void (*prepare_tx)(struct device *dev,u_char *hdr,int hdrlen,
+  void (*inthandler) (struct net_device *dev);
+  int (*arcnet_reset) (struct net_device *dev, int reset_delay);
+  void (*asetmask) (struct net_device *dev, u_char mask);
+  void (*acommand) (struct net_device *dev, u_char command);
+  u_char (*astatus) (struct net_device *dev);
+  void (*en_dis_able_TX) (struct net_device *dev, int enable); 
+  void (*prepare_tx)(struct net_device *dev,u_char *hdr,int hdrlen,
 		     char *data,int length,int daddr,int exceptA, int offset);
   void (*openclose_device)(int open);  
   
-  struct device *adev;	/* RFC1201 protocol device */
+  struct net_device *adev;	/* RFC1201 protocol device */
   
   /* These are last to ensure that the chipset drivers don't depend on the
    * CONFIG_ARCNET_ETH and CONFIG_ARCNET_1051 options. 
    */
   
 #ifdef CONFIG_ARCNET_ETH
-  struct device *edev;	/* Ethernet-Encap device */
+  struct net_device *edev;	/* Ethernet-Encap device */
 #endif
   
 #ifdef CONFIG_ARCNET_1051
-  struct device *sdev;	/* RFC1051 protocol device */
+  struct net_device *sdev;	/* RFC1051 protocol device */
 #endif
 };
 
@@ -327,25 +327,25 @@
  */
 
 #if ARCNET_DEBUG_MAX & D_SKB
-extern void arcnet_dump_skb(struct device *dev,struct sk_buff *skb,
+extern void arcnet_dump_skb(struct net_device *dev,struct sk_buff *skb,
 			    char *desc);
 #else
 #define arcnet_dump_skb(dev,skb,desc) ;
 #endif
 
 #if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX)
-extern void arcnet_dump_packet(struct device *dev,u_char *buffer,int ext,
+extern void arcnet_dump_packet(struct net_device *dev,u_char *buffer,int ext,
 			       char *desc);
 #else
 #define arcnet_dump_packet(dev,buffer,ext,desc) ;
 #endif
 
-extern void arcnet_tx_done(struct device *dev, struct arcnet_local *lp);
+extern void arcnet_tx_done(struct net_device *dev, struct arcnet_local *lp);
 extern void arcnet_makename(char *device);
 extern void arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs);
-extern void arcnet_setup(struct device *dev);
-extern int arcnet_go_tx(struct device *dev,int enable_irq);
-extern void arcnetA_continue_tx(struct device *dev);
+extern void arcnet_setup(struct net_device *dev);
+extern int arcnet_go_tx(struct net_device *dev,int enable_irq);
+extern void arcnetA_continue_tx(struct net_device *dev);
 extern void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr);
 extern void arcnet_use_count(int open);
 
diff -u --recursive --new-file v2.3.13/linux/include/linux/atalk.h linux/include/linux/atalk.h
--- v2.3.13/linux/include/linux/atalk.h	Tue Jun 22 14:41:40 1999
+++ linux/include/linux/atalk.h	Wed Aug 18 16:43:35 1999
@@ -43,7 +43,7 @@
 
 struct atalk_route
 {
-	struct device *dev;
+	struct net_device *dev;
 	struct at_addr target;
 	struct at_addr gateway;
 	int flags;
@@ -52,7 +52,7 @@
 
 struct atalk_iface
 {
-	struct device *dev;
+	struct net_device *dev;
 	struct at_addr address;		/* Our address */
 	int status;			/* What are we doing? */
 #define ATIF_PROBE	1		/* Probing for an address */
@@ -161,16 +161,16 @@
  *	Give a device find its atif control structure
  */
 
-extern __inline__ struct atalk_iface *atalk_find_dev(struct device *dev)
+extern __inline__ struct atalk_iface *atalk_find_dev(struct net_device *dev)
 {
 	return dev->atalk_ptr;
 }
 
-extern struct at_addr *atalk_find_dev_addr(struct device *dev);
-extern struct device *atrtr_get_dev(struct at_addr *sa);
-extern int aarp_send_ddp(struct device *dev,struct sk_buff *skb, struct at_addr *sa, void *hwaddr);
-extern void aarp_send_probe(struct device *dev, struct at_addr *addr);
-extern void aarp_device_down(struct device *dev);
+extern struct at_addr *atalk_find_dev_addr(struct net_device *dev);
+extern struct net_device *atrtr_get_dev(struct at_addr *sa);
+extern int aarp_send_ddp(struct net_device *dev,struct sk_buff *skb, struct at_addr *sa, void *hwaddr);
+extern void aarp_send_probe(struct net_device *dev, struct at_addr *addr);
+extern void aarp_device_down(struct net_device *dev);
 
 #ifdef MODULE
 extern void aarp_cleanup_module(void);
diff -u --recursive --new-file v2.3.13/linux/include/linux/b1lli.h linux/include/linux/b1lli.h
--- v2.3.13/linux/include/linux/b1lli.h	Sun May 23 10:03:42 1999
+++ linux/include/linux/b1lli.h	Thu Aug 12 09:42:33 1999
@@ -1,11 +1,30 @@
 /*
- * $Id: b1lli.h,v 1.6 1999/04/15 19:49:36 calle Exp $
+ * $Id: b1lli.h,v 1.8 1999/07/01 15:26:54 calle Exp $
  *
  * ISDN lowlevel-module for AVM B1-card.
  *
  * Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de)
  *
  * $Log: b1lli.h,v $
+ * Revision 1.8  1999/07/01 15:26:54  calle
+ * complete new version (I love it):
+ * + new hardware independed "capi_driver" interface that will make it easy to:
+ *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ *   - write a CAPI-2.0 for the passive cards
+ *   - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ *   make menuconfig, in the past all supported cards where included
+ *   at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ *   using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+ *
+ * Revision 1.7  1999/06/21 15:24:25  calle
+ * extend information in /proc.
+ *
  * Revision 1.6  1999/04/15 19:49:36  calle
  * fix fuer die B1-PCI. Jetzt geht z.B. auch IRQ 17 ...
  *
@@ -96,7 +115,6 @@
 #define AVM_CARDTYPE_T1		1
 #define AVM_CARDTYPE_M1		2
 #define AVM_CARDTYPE_M2		3
-#define AVM_CARDTYPE_B1PCI	4
 
 typedef struct avmb1_extcarddef {
 	int port;
@@ -113,107 +131,6 @@
 #define AVMB1_GET_CARDINFO	5	/* get cardtype */
 #define AVMB1_REMOVECARD	6	/* remove a card (usefull for T1) */
 
-
-
-/*
- * card states for startup
- */
-
-#define CARD_FREE	0
-#define CARD_DETECTED	1
-#define CARD_LOADING	2
-#define CARD_INITSTATE	4
-#define CARD_RUNNING	5
-#define CARD_ACTIVE	6
-
-#ifdef __KERNEL__
-
-#define	AVMB1_PORTLEN		0x1f
-
-#define AVM_MAXVERSION		8
-
-#define AVM_NAPPS		30
-#define AVM_NNCCI_PER_CHANNEL	4
-
-/*
- * Main driver data
- */
-
-typedef struct avmb1_card {
-	struct avmb1_card *next;
-	int cnr;
-	unsigned int port;
-	unsigned irq;
-	int cardtype;
-	int cardnr; /* for T1-HEMA */
-	volatile unsigned short cardstate;
-	int interrupt;
-	int blocked;
-	int versionlen;
-	char versionbuf[1024];
-	char *version[AVM_MAXVERSION];
-	char msgbuf[128];	/* capimsg msg part */
-	char databuf[2048];	/* capimsg data part */
-	capi_version cversion;
-	char name[10];
-} avmb1_card;
-
-/*
- * Versions
- */
-
-#define	VER_DRIVER	0
-#define	VER_CARDTYPE	1
-#define	VER_HWID	2
-#define	VER_SERIAL	3
-#define	VER_OPTION	4
-#define	VER_PROTO	5
-#define	VER_PROFILE	6
-#define	VER_CAPI	7
-
-
-/* b1lli.c */
-int B1_detect(unsigned int base, int cardtype);
-int T1_detectandinit(unsigned int base, unsigned irq, int cardnr);
-void B1_reset(unsigned int base);
-void T1_reset(unsigned int base);
-int B1_load_t4file(unsigned int base, avmb1_t4file * t4file);
-int B1_load_config(unsigned int base, avmb1_t4file * config);
-int B1_loaded(unsigned int base);
-void B1_setinterrupt(unsigned int base, unsigned irq, int cardtype);
-unsigned char B1_disable_irq(unsigned int base);
-void T1_disable_irq(unsigned int base);
-int B1_valid_irq(unsigned irq, int cardtype);
-int B1_valid_port(unsigned port, int cardtype);
-void B1_handle_interrupt(avmb1_card * card);
-void B1_send_init(unsigned int port,
-	    unsigned int napps, unsigned int nncci, unsigned int cardnr);
-void B1_send_register(unsigned int port,
-		      __u16 appid, __u32 nmsg,
-		      __u32 nb3conn, __u32 nb3blocks, __u32 b3bsize);
-void B1_send_release(unsigned int port, __u16 appid);
-void B1_send_message(unsigned int port, struct sk_buff *skb);
-
-/* b1capi.c */
-void avmb1_handle_new_ncci(avmb1_card * card,
-			   __u16 appl, __u32 ncci, __u32 winsize);
-void avmb1_handle_free_ncci(avmb1_card * card,
-			    __u16 appl, __u32 ncci);
-void avmb1_handle_capimsg(avmb1_card * card, __u16 appl, struct sk_buff *skb);
-void avmb1_card_ready(avmb1_card * card);
-
-/* standard calls, with check and allocation of resources */
-int avmb1_addcard(int port, int irq, int cardtype);
-int avmb1_probecard(int port, int irq, int cardtype);
-
-
-int avmb1_resetcard(int cardnr);
-
-/* calls for pcmcia driver */
-int avmb1_detectcard(int port, int irq, int cardtype);
-int avmb1_registercard(int port, int irq, int cardtype, int allocio);
-int avmb1_unregistercard(int cnr, int freeio);
-
-#endif				/* __KERNEL__ */
+#define	AVMB1_REGISTERCARD_IS_OBSOLETE
 
 #endif				/* _B1LLI_H_ */
diff -u --recursive --new-file v2.3.13/linux/include/linux/b1pcmcia.h linux/include/linux/b1pcmcia.h
--- v2.3.13/linux/include/linux/b1pcmcia.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/b1pcmcia.h	Thu Aug 12 09:42:33 1999
@@ -0,0 +1,36 @@
+/*
+ * $Id: b1pcmcia.h,v 1.1 1999/07/01 15:26:56 calle Exp $
+ *
+ * Exported functions of module b1pcmcia to be called by
+ * avm_cs card services module.
+ *
+ * Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
+ *
+ * $Log: b1pcmcia.h,v $
+ * Revision 1.1  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:
+ *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ *   - write a CAPI-2.0 for the passive cards
+ *   - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ *   make menuconfig, in the past all supported cards where included
+ *   at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ *   using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+ *
+ */
+
+#ifndef _B1PCMCIA_H_
+#define _B1PCMCIA_H_
+
+int b1pcmcia_addcard_b1(unsigned int port, unsigned irq);
+int b1pcmcia_addcard_m1(unsigned int port, unsigned irq);
+int b1pcmcia_addcard_m2(unsigned int port, unsigned irq);
+int b1pcmcia_delcard(unsigned int port, unsigned irq);
+
+#endif	/* _B1PCMCIA_H_ */
diff -u --recursive --new-file v2.3.13/linux/include/linux/concap.h linux/include/linux/concap.h
--- v2.3.13/linux/include/linux/concap.h	Wed Apr  1 16:20:56 1998
+++ linux/include/linux/concap.h	Wed Aug 18 11:38:47 1999
@@ -25,7 +25,7 @@
 /* this manages all data needed by the encapsulation protocol
  */
 struct concap_proto{
-	struct device *net_dev;		/* net device using our service  */
+	struct net_device *net_dev;		/* net device using our service  */
 	struct concap_device_ops *dops; /* callbacks provided by device */
  	struct concap_proto_ops  *pops; /* callbacks provided by us */
 	int flags;
@@ -72,7 +72,7 @@
 	   or when the device driver resets the interface. All services of the
 	   encapsulation protocol may be used after this*/
 	int (*restart)(struct concap_proto *cprot, 
-		       struct device *ndev,
+		       struct net_device *ndev,
 		       struct concap_device_ops *dops);
 
 	/* inactivate an encapsulation protocol instance. The encapsulation
diff -u --recursive --new-file v2.3.13/linux/include/linux/cyclomx.h linux/include/linux/cyclomx.h
--- v2.3.13/linux/include/linux/cyclomx.h	Wed Jun 30 13:38:20 1999
+++ linux/include/linux/cyclomx.h	Sun Aug 15 11:49:08 1999
@@ -56,8 +56,7 @@
 	spinlock_t lock;
 	char in_isr;			/* interrupt-in-service flag */
 	char buff_int_mode_unbusy;      /* flag for carrying out dev_tint */
-	u16 irq_dis_if_send_count;	/* Disabling irqs in if_send*/
-#if LINUX_VERSION_CODE >= 0x020300
+#if (LINUX_VERSION_CODE >= 0x20300)
 	wait_queue_head_t wait_stats;  /* to wait for the STATS indication */
 #else
 	struct wait_queue* wait_stats;  /* to wait for the STATS indication */
@@ -73,7 +72,7 @@
 			u32 lo_svc;
 			u32 hi_svc;
 			TX25Stats stats;
-			unsigned critical;	/* critical section flag */
+			spinlock_t lock;
 			u32 connection_keys;
 		} x;
 #endif
@@ -81,12 +80,12 @@
 } cycx_t;
 
 /* Public Functions */
-void cyclomx_open      (cycx_t* card);			/* cycx_main.c */
-void cyclomx_close     (cycx_t* card);			/* cycx_main.c */
-void cyclomx_set_state (cycx_t* card, int state);	/* cycx_main.c */
+void cyclomx_open      (cycx_t *card);			/* cycx_main.c */
+void cyclomx_close     (cycx_t *card);			/* cycx_main.c */
+void cyclomx_set_state (cycx_t *card, int state);	/* cycx_main.c */
 
 #ifdef CONFIG_CYCLOMX_X25
-int cyx_init (cycx_t* card, wandev_conf_t* conf);	/* cycx_x25.c */
+int cyx_init (cycx_t *card, wandev_conf_t *conf);	/* cycx_x25.c */
 #endif
 #endif	/* __KERNEL__ */
 #endif	/* _CYCLOMX_H */
diff -u --recursive --new-file v2.3.13/linux/include/linux/cycx_drv.h linux/include/linux/cycx_drv.h
--- v2.3.13/linux/include/linux/cycx_drv.h	Wed Jun  2 14:40:22 1999
+++ linux/include/linux/cycx_drv.h	Thu Aug 12 09:46:13 1999
@@ -54,13 +54,11 @@
 } cycxhw_t;
 
 /* Function Prototypes */
-extern int cycx_setup  (cycxhw_t* hw, void* sfm, u32 len);
-extern int cycx_down   (cycxhw_t* hw);
-extern int cycx_inten  (cycxhw_t* hw);
-extern int cycx_intde  (cycxhw_t* hw);
-extern int cycx_intack (cycxhw_t* hw);
-extern int cycx_intr   (cycxhw_t* hw);
-extern int cycx_peek   (cycxhw_t* hw, u32 addr, void* buf, u32 len);
-extern int cycx_poke   (cycxhw_t* hw, u32 addr, void* buf, u32 len);
-extern int cycx_exec   (u32 addr);
+extern int cycx_setup (cycxhw_t *hw, void *sfm, u32 len);
+extern int cycx_down (cycxhw_t *hw);
+extern int cycx_inten (cycxhw_t *hw);
+extern int cycx_intr (cycxhw_t *hw);
+extern int cycx_peek (cycxhw_t *hw, u32 addr, void *buf, u32 len);
+extern int cycx_poke (cycxhw_t *hw, u32 addr, void *buf, u32 len);
+extern int cycx_exec (u32 addr);
 #endif	/* _CYCX_DRV_H */
diff -u --recursive --new-file v2.3.13/linux/include/linux/etherdevice.h linux/include/linux/etherdevice.h
--- v2.3.13/linux/include/linux/etherdevice.h	Tue Jun 22 14:41:40 1999
+++ linux/include/linux/etherdevice.h	Wed Aug 18 16:43:32 1999
@@ -28,18 +28,18 @@
 #include <linux/if_ether.h>
 
 #ifdef __KERNEL__
-extern int		eth_header(struct sk_buff *skb, struct device *dev,
+extern int		eth_header(struct sk_buff *skb, struct net_device *dev,
 				   unsigned short type, void *daddr,
 				   void *saddr, unsigned len);
 extern int		eth_rebuild_header(struct sk_buff *skb);
-extern unsigned short	eth_type_trans(struct sk_buff *skb, struct device *dev);
-extern void		eth_header_cache_update(struct hh_cache *hh, struct device *dev,
+extern unsigned short	eth_type_trans(struct sk_buff *skb, struct net_device *dev);
+extern void		eth_header_cache_update(struct hh_cache *hh, struct net_device *dev,
 						unsigned char * haddr);
 extern int		eth_header_cache(struct neighbour *neigh,
 					 struct hh_cache *hh);
 extern int		eth_header_parse(struct sk_buff *skb,
 					 unsigned char *haddr);
-extern struct device	* init_etherdev(struct device *, int);
+extern struct net_device	* init_etherdev(struct net_device *, int);
 
 #ifdef CONFIG_IP_ROUTER
 static __inline__ void eth_copy_and_sum (struct sk_buff *dest, unsigned char *src, int len, int base)
diff -u --recursive --new-file v2.3.13/linux/include/linux/fb.h linux/include/linux/fb.h
--- v2.3.13/linux/include/linux/fb.h	Mon Aug  9 14:59:23 1999
+++ linux/include/linux/fb.h	Wed Aug 18 10:10:06 1999
@@ -207,6 +207,7 @@
 #ifdef __KERNEL__
 
 #include <linux/fs.h>
+#include <linux/init.h>
 
 
 struct fb_info;
@@ -403,12 +404,6 @@
 extern void fbgen_blank(int blank, struct fb_info *info);
 
 
-struct fb_videomode {
-    const char *name;
-    struct fb_var_screeninfo var;
-};
-
-
 /* drivers/char/fbmem.c */
 extern int register_framebuffer(struct fb_info *fb_info);
 extern int unregister_framebuffer(const struct fb_info *fb_info);
@@ -444,6 +439,30 @@
 #define VESA_VSYNC_SUSPEND	1
 #define VESA_HSYNC_SUSPEND	2
 #define VESA_POWERDOWN		3
+
+
+struct fb_videomode {
+    const char *name;	/* optional */
+    u32 refresh;	/* optional */
+    u32 xres;
+    u32 yres;
+    u32 pixclock;
+    u32 left_margin;
+    u32 right_margin;
+    u32 upper_margin;
+    u32 lower_margin;
+    u32 hsync_len;
+    u32 vsync_len;
+    u32 sync;
+    u32 vmode;
+};
+
+extern int __init fb_find_mode(struct fb_var_screeninfo *var,
+			       struct fb_info *info, const char *mode_option,
+			       const struct fb_videomode *db,
+			       unsigned int dbsize,
+			       const struct fb_videomode *default_mode,
+			       unsigned int default_bpp);
 
 #endif /* __KERNEL__ */
 
diff -u --recursive --new-file v2.3.13/linux/include/linux/fd.h linux/include/linux/fd.h
--- v2.3.13/linux/include/linux/fd.h	Wed Jun 24 14:30:11 1998
+++ linux/include/linux/fd.h	Fri Aug 13 12:16:16 1999
@@ -216,7 +216,7 @@
 	/* Prevent "aliased" accesses. */
 	int fd_ref;
 	int fd_device;
-	int last_checked; /* when was the drive last checked for a disk 
+	unsigned long last_checked; /* when was the drive last checked for a disk 
 			   * change? */
 	
 	char *dmabuf;
diff -u --recursive --new-file v2.3.13/linux/include/linux/fddidevice.h linux/include/linux/fddidevice.h
--- v2.3.13/linux/include/linux/fddidevice.h	Wed Jun  2 13:54:53 1999
+++ linux/include/linux/fddidevice.h	Wed Aug 18 11:38:46 1999
@@ -26,14 +26,14 @@
 
 #ifdef __KERNEL__
 extern int		fddi_header(struct sk_buff *skb,
-				    struct device *dev,
+				    struct net_device *dev,
 				    unsigned short type,
 				    void *daddr,
 				    void *saddr,
 				    unsigned len);
 extern int		fddi_rebuild_header(struct sk_buff *skb);
 extern unsigned short	fddi_type_trans(struct sk_buff *skb,
-				struct device *dev);
+				struct net_device *dev);
 #endif
 
 #endif	/* _LINUX_FDDIDEVICE_H */
diff -u --recursive --new-file v2.3.13/linux/include/linux/firewall.h linux/include/linux/firewall.h
--- v2.3.13/linux/include/linux/firewall.h	Tue Jun 22 14:42:51 1999
+++ linux/include/linux/firewall.h	Wed Aug 18 16:44:42 1999
@@ -19,11 +19,11 @@
 {
 	struct firewall_ops *next;
 	int (*fw_forward)(struct firewall_ops *this, int pf, 
-			struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
+			struct net_device *dev, void *phdr, void *arg, struct sk_buff **pskb);
 	int (*fw_input)(struct firewall_ops *this, int pf, 
-			struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
+			struct net_device *dev, void *phdr, void *arg, struct sk_buff **pskb);
 	int (*fw_output)(struct firewall_ops *this, int pf, 
-			struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
+			struct net_device *dev, void *phdr, void *arg, struct sk_buff **pskb);
 	/* Data falling in the second 486 cache line isn't used directly
 	   during a firewall call and scan, only by insert/delete and other
 	   unusual cases
@@ -37,21 +37,21 @@
 extern int unregister_firewall(int pf, struct firewall_ops *fw);
 extern void fwchain_init(void);
 #ifdef CONFIG_FIREWALL
-extern int call_fw_firewall(int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
-extern int call_in_firewall(int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
-extern int call_out_firewall(int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
+extern int call_fw_firewall(int pf, struct net_device *dev, void *phdr, void *arg, struct sk_buff **pskb);
+extern int call_in_firewall(int pf, struct net_device *dev, void *phdr, void *arg, struct sk_buff **pskb);
+extern int call_out_firewall(int pf, struct net_device *dev, void *phdr, void *arg, struct sk_buff **pskb);
 #else
-extern __inline__ int call_fw_firewall(int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **skb)
+extern __inline__ int call_fw_firewall(int pf, struct net_device *dev, void *phdr, void *arg, struct sk_buff **skb)
 {
 	return FW_ACCEPT;
 }
 
-extern __inline__ int call_in_firewall(int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **skb)
+extern __inline__ int call_in_firewall(int pf, struct net_device *dev, void *phdr, void *arg, struct sk_buff **skb)
 {
 	return FW_ACCEPT;
 }
 
-extern __inline__ int call_out_firewall(int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **skb)
+extern __inline__ int call_out_firewall(int pf, struct net_device *dev, void *phdr, void *arg, struct sk_buff **skb)
 {
 	return FW_ACCEPT;
 }
diff -u --recursive --new-file v2.3.13/linux/include/linux/genhd.h linux/include/linux/genhd.h
--- v2.3.13/linux/include/linux/genhd.h	Tue Jun 22 14:41:39 1999
+++ linux/include/linux/genhd.h	Thu Aug 12 12:26:06 1999
@@ -12,20 +12,6 @@
 #include <linux/config.h>
 #include <linux/types.h>
 
-#define CONFIG_MSDOS_PARTITION 1
-
-#ifdef __alpha__
-#define CONFIG_OSF_PARTITION 1
-#endif
-
-#if defined(__sparc__) || defined(CONFIG_SMD_DISKLABEL)
-#define CONFIG_SUN_PARTITION 1
-#endif
-
-#if defined(CONFIG_SGI) || defined(CONFIG_SGI_DISKLABEL)
-#define CONFIG_SGI_PARTITION 1
-#endif
-
 /* These three have identical behaviour; use the second one if DOS fdisk gets
    confused about extended/logical partitions starting past cylinder 1023. */
 #define DOS_EXTENDED_PARTITION 5
diff -u --recursive --new-file v2.3.13/linux/include/linux/hdlcdrv.h linux/include/linux/hdlcdrv.h
--- v2.3.13/linux/include/linux/hdlcdrv.h	Sun Jun  7 11:13:45 1998
+++ linux/include/linux/hdlcdrv.h	Wed Aug 18 11:38:46 1999
@@ -173,9 +173,9 @@
 	/*
 	 * the routines called by the hdlcdrv routines
 	 */
-	int (*open)(struct device *);
-	int (*close)(struct device *);
-	int (*ioctl)(struct device *, struct ifreq *, 
+	int (*open)(struct net_device *);
+	int (*close)(struct net_device *);
+	int (*ioctl)(struct net_device *, struct ifreq *, 
 		     struct hdlcdrv_ioctl *, int);
 };
 
@@ -361,14 +361,14 @@
 
 /* -------------------------------------------------------------------- */
 
-void hdlcdrv_receiver(struct device *, struct hdlcdrv_state *);
-void hdlcdrv_transmitter(struct device *, struct hdlcdrv_state *);
-void hdlcdrv_arbitrate(struct device *, struct hdlcdrv_state *);
-int hdlcdrv_register_hdlcdrv(struct device *dev, const struct hdlcdrv_ops *ops,
+void hdlcdrv_receiver(struct net_device *, struct hdlcdrv_state *);
+void hdlcdrv_transmitter(struct net_device *, struct hdlcdrv_state *);
+void hdlcdrv_arbitrate(struct net_device *, struct hdlcdrv_state *);
+int hdlcdrv_register_hdlcdrv(struct net_device *dev, const struct hdlcdrv_ops *ops,
 			     unsigned int privsize, char *ifname,
 			     unsigned int baseaddr, unsigned int irq, 
 			     unsigned int dma);
-int hdlcdrv_unregister_hdlcdrv(struct device *dev);
+int hdlcdrv_unregister_hdlcdrv(struct net_device *dev);
 
 /* -------------------------------------------------------------------- */
 
diff -u --recursive --new-file v2.3.13/linux/include/linux/hippidevice.h linux/include/linux/hippidevice.h
--- v2.3.13/linux/include/linux/hippidevice.h	Tue Jun 22 14:41:40 1999
+++ linux/include/linux/hippidevice.h	Wed Aug 18 16:43:36 1999
@@ -27,7 +27,7 @@
 
 #ifdef __KERNEL__
 extern int hippi_header(struct sk_buff *skb,
-			struct device *dev,
+			struct net_device *dev,
 			unsigned short type,
 			void *daddr,
 			void *saddr,
@@ -36,23 +36,23 @@
 extern int hippi_rebuild_header(struct sk_buff *skb);
 
 extern unsigned short hippi_type_trans(struct sk_buff *skb,
-				       struct device *dev);
+				       struct net_device *dev);
 
 extern void hippi_header_cache_bind(struct hh_cache ** hhp,
-				    struct device *dev,
+				    struct net_device *dev,
 				    unsigned short htype,
 				    __u32 daddr);
 
 extern void hippi_header_cache_update(struct hh_cache *hh,
-				      struct device *dev,
+				      struct net_device *dev,
 				      unsigned char * haddr);
 extern int hippi_header_parse(struct sk_buff *skb, unsigned char *haddr);
 
 extern void hippi_net_init(void);
-void hippi_setup(struct device *dev);
+void hippi_setup(struct net_device *dev);
 
-extern struct device *init_hippi_dev(struct device *, int);
-extern void unregister_hipdev(struct device *dev);
+extern struct net_device *init_hippi_dev(struct net_device *, int);
+extern void unregister_hipdev(struct net_device *dev);
 #endif
 
 #endif	/* _LINUX_HIPPIDEVICE_H */
diff -u --recursive --new-file v2.3.13/linux/include/linux/icmpv6.h linux/include/linux/icmpv6.h
--- v2.3.13/linux/include/linux/icmpv6.h	Tue Jun 22 14:42:40 1999
+++ linux/include/linux/icmpv6.h	Wed Aug 18 16:44:29 1999
@@ -136,7 +136,7 @@
 extern void				icmpv6_send(struct sk_buff *skb,
 						    int type, int code,
 						    __u32 info, 
-						    struct device *dev);
+						    struct net_device *dev);
 
 extern int				icmpv6_init(struct net_proto_family *ops);
 extern int				icmpv6_err_convert(int type, int code,
diff -u --recursive --new-file v2.3.13/linux/include/linux/if_eql.h linux/include/linux/if_eql.h
--- v2.3.13/linux/include/linux/if_eql.h	Thu Apr 11 23:49:46 1996
+++ linux/include/linux/if_eql.h	Wed Aug 18 11:38:46 1999
@@ -36,7 +36,7 @@
 #define EQL_SETMASTRCFG (SIOCDEVPRIVATE + 5)
 
 typedef struct slave {
-  struct device *dev;
+  struct net_device *dev;
   long priority;
   long priority_bps;
   long priority_Bps;
@@ -48,7 +48,7 @@
   slave_t *head;
   slave_t *best_slave;
   int num_slaves;
-  struct device *master_dev;
+  struct net_device *master_dev;
   char lock;
 } slave_queue_t;
 
diff -u --recursive --new-file v2.3.13/linux/include/linux/if_frad.h linux/include/linux/if_frad.h
--- v2.3.13/linux/include/linux/if_frad.h	Sat Feb 28 21:15:01 1998
+++ linux/include/linux/if_frad.h	Wed Aug 18 11:38:46 1999
@@ -155,12 +155,12 @@
 struct dlci_local
 {
    struct enet_statistics stats;
-   struct device          *slave;
+   struct net_device          *slave;
    struct dlci_conf       config;
    int                    configured;
 
    /* callback function */
-   void              (*receive)(struct sk_buff *skb, struct device *);
+   void              (*receive)(struct sk_buff *skb, struct net_device *);
 };
 
 struct frad_local
@@ -168,7 +168,7 @@
    struct enet_statistics stats;
 
    /* devices which this FRAD is slaved to */
-   struct device     *master[CONFIG_DLCI_MAX];
+   struct net_device     *master[CONFIG_DLCI_MAX];
    short             dlci[CONFIG_DLCI_MAX];
 
    struct frad_conf  config;
@@ -176,11 +176,11 @@
    int               initialized;	/* mem_start, port, irq set ? */
 
    /* callback functions */
-   int               (*activate)(struct device *, struct device *);
-   int               (*deactivate)(struct device *, struct device *);
-   int               (*assoc)(struct device *, struct device *);
-   int               (*deassoc)(struct device *, struct device *);
-   int               (*dlci_conf)(struct device *, struct device *, int get);
+   int               (*activate)(struct net_device *, struct net_device *);
+   int               (*deactivate)(struct net_device *, struct net_device *);
+   int               (*assoc)(struct net_device *, struct net_device *);
+   int               (*deassoc)(struct net_device *, struct net_device *);
+   int               (*dlci_conf)(struct net_device *, struct net_device *, int get);
 
    /* fields that are used by the Sangoma SDLA cards */
    struct timer_list timer;
diff -u --recursive --new-file v2.3.13/linux/include/linux/if_ltalk.h linux/include/linux/if_ltalk.h
--- v2.3.13/linux/include/linux/if_ltalk.h	Sun Feb  2 05:18:47 1997
+++ linux/include/linux/if_ltalk.h	Wed Aug 18 11:38:46 1999
@@ -6,7 +6,7 @@
 #define LTALK_ALEN		1
 
 #ifdef __KERNEL__
-extern void ltalk_setup(struct device *);
+extern void ltalk_setup(struct net_device *);
 #endif
 
 #endif
diff -u --recursive --new-file v2.3.13/linux/include/linux/if_pppvar.h linux/include/linux/if_pppvar.h
--- v2.3.13/linux/include/linux/if_pppvar.h	Mon Aug  9 14:59:23 1999
+++ linux/include/linux/if_pppvar.h	Wed Aug 18 11:38:46 1999
@@ -127,7 +127,7 @@
 	enum	NPmode sc_npmode[NUM_NP]; /* what to do with each NP */
 	int	 sc_xfer;		/* PID of reserved PPP table */
 	char	name[8];		/* space for unit name */
-	struct device	dev;		/* net device structure */
+	struct net_device	dev;		/* net device structure */
 	struct enet_statistics estats;	/* more detailed stats */
 
 	/* tty output buffer */
diff -u --recursive --new-file v2.3.13/linux/include/linux/if_shaper.h linux/include/linux/if_shaper.h
--- v2.3.13/linux/include/linux/if_shaper.h	Mon Aug  9 14:59:23 1999
+++ linux/include/linux/if_shaper.h	Wed Aug 18 11:38:47 1999
@@ -25,19 +25,19 @@
 				   an empty queue */
         unsigned long locked;
         struct net_device_stats stats;
-	struct device *dev;
+	struct net_device *dev;
 	int  (*hard_start_xmit) (struct sk_buff *skb,
-		struct device *dev);
+		struct net_device *dev);
 	int  (*hard_header) (struct sk_buff *skb,
-		struct device *dev,
+		struct net_device *dev,
 		unsigned short type,
 		void *daddr,
 		void *saddr,
 		unsigned len);
 	int  (*rebuild_header)(struct sk_buff *skb);
 	int (*hard_header_cache)(struct neighbour *neigh, struct hh_cache *hh);
-	void (*header_cache_update)(struct hh_cache *hh, struct device *dev, unsigned char *  haddr);
-	struct net_device_stats* (*get_stats)(struct device *dev);
+	void (*header_cache_update)(struct hh_cache *hh, struct net_device *dev, unsigned char *  haddr);
+	struct net_device_stats* (*get_stats)(struct net_device *dev);
 	wait_queue_head_t  wait_queue;
 	struct timer_list timer;
 };
diff -u --recursive --new-file v2.3.13/linux/include/linux/igmp.h linux/include/linux/igmp.h
--- v2.3.13/linux/include/linux/igmp.h	Wed Jun  9 14:45:36 1999
+++ linux/include/linux/igmp.h	Wed Aug 18 11:38:46 1999
@@ -101,7 +101,7 @@
 	char			loaded;
 };
 
-extern int ip_check_mc(struct device *dev, u32 mc_addr);
+extern int ip_check_mc(struct net_device *dev, u32 mc_addr);
 extern int igmp_rcv(struct sk_buff *, unsigned short);
 extern int ip_mc_join_group(struct sock *sk, struct ip_mreqn *imr);
 extern int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr);
diff -u --recursive --new-file v2.3.13/linux/include/linux/inetdevice.h linux/include/linux/inetdevice.h
--- v2.3.13/linux/include/linux/inetdevice.h	Wed Jun  9 14:45:36 1999
+++ linux/include/linux/inetdevice.h	Wed Aug 18 11:38:47 1999
@@ -23,7 +23,7 @@
 
 struct in_device
 {
-	struct device		*dev;
+	struct net_device		*dev;
 	struct in_ifaddr	*ifa_list;	/* IP ifaddr chain		*/
 	struct ip_mc_list	*mc_list;	/* IP multicast filter chain    */
 	unsigned long		mr_v1_seen;
@@ -68,13 +68,13 @@
 extern int register_inetaddr_notifier(struct notifier_block *nb);
 extern int unregister_inetaddr_notifier(struct notifier_block *nb);
 
-extern struct device 	*ip_dev_find(u32 addr);
+extern struct net_device 	*ip_dev_find(u32 addr);
 extern struct in_ifaddr	*inet_addr_onlink(struct in_device *in_dev, u32 a, u32 b);
 extern int		devinet_ioctl(unsigned int cmd, void *);
 extern void		devinet_init(void);
-extern struct in_device *inetdev_init(struct device *dev);
+extern struct in_device *inetdev_init(struct net_device *dev);
 extern struct in_device	*inetdev_by_index(int);
-extern u32		inet_select_addr(const struct device *dev, u32 dst, int scope);
+extern u32		inet_select_addr(const struct net_device *dev, u32 dst, int scope);
 extern struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, u32 prefix, u32 mask);
 extern void		inet_forward_change(void);
 
diff -u --recursive --new-file v2.3.13/linux/include/linux/ioport.h linux/include/linux/ioport.h
--- v2.3.13/linux/include/linux/ioport.h	Mon Aug  9 14:59:23 1999
+++ linux/include/linux/ioport.h	Sun Aug 15 11:50:35 1999
@@ -8,6 +8,19 @@
 #ifndef _LINUX_IOPORT_H
 #define _LINUX_IOPORT_H
 
+#define DEVICE_IO_NOTSET	(~0)
+#define DEVICE_IO_AUTO		((~0)-1)
+
+#define DEVICE_IO_FLAG_WRITEABLE	(1<<0)
+#define DEVICE_IO_FLAG_CACHEABLE	(1<<1)
+#define DEVICE_IO_FLAG_RANGELENGTH	(1<<2)
+#define DEVICE_IO_FLAG_SHADOWABLE	(1<<4)
+#define DEVICE_IO_FLAG_EXPANSIONROM	(1<<5)
+
+#define DEVICE_IO_TYPE_8BIT		0
+#define DEVICE_IO_TYPE_16BIT		1
+#define DEVICE_IO_TYPE_8AND16BIT	2
+
 /*
  * Resources are tree-like, allowing
  * nesting etc..
@@ -16,6 +29,10 @@
 	const char *name;
 	unsigned long start, end;
 	unsigned long flags;
+	unsigned char bits;		/* decoded bits */
+	unsigned char fixed;		/* fixed range */
+	unsigned short hw_flags;	/* hardware flags */
+	unsigned short type;		/* region type */
 	struct resource *parent, *sibling, *child;
 };
 
diff -u --recursive --new-file v2.3.13/linux/include/linux/irq.h linux/include/linux/irq.h
--- v2.3.13/linux/include/linux/irq.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/irq.h	Wed Aug 18 16:45:11 1999
@@ -0,0 +1,79 @@
+#ifndef __irq_h
+#define __irq_h
+
+#include <asm/irq.h>
+/*
+ * IRQ line status.
+ */
+#define IRQ_INPROGRESS	1	/* IRQ handler active - do not enter! */
+#define IRQ_DISABLED	2	/* IRQ disabled - do not enter! */
+#define IRQ_PENDING	4	/* IRQ pending - replay on enable */
+#define IRQ_REPLAY	8	/* IRQ has been replayed but not acked yet */
+#define IRQ_AUTODETECT	16	/* IRQ is being autodetected */
+#define IRQ_WAITING	32	/* IRQ not yet seen - for autodetection */
+
+/*
+ * Interrupt controller descriptor. This is all we need
+ * to describe about the low-level hardware. 
+ */
+struct hw_interrupt_type {
+	const char * typename;
+	unsigned int (*startup)(unsigned int irq);
+	void (*shutdown)(unsigned int irq);
+	void (*enable)(unsigned int irq);
+	void (*disable)(unsigned int irq);
+	void (*ack)(unsigned int irq);
+	void (*end)(unsigned int irq);
+};
+
+typedef struct hw_interrupt_type  hw_irq_controller;
+
+/*
+ * This is the "IRQ descriptor", which contains various information
+ * about the irq, including what kind of hardware handling it has,
+ * whether it is disabled etc etc.
+ *
+ * Pad this out to 32 bytes for cache and indexing reasons.
+ */
+typedef struct {
+	unsigned int status;	/* IRQ status
+				  - IRQ_INPROGRESS, IRQ_DISABLED */
+	hw_irq_controller *handler;	/* never derefed in arch
+					   independent code */
+	struct irqaction *action;		/* IRQ action list */
+	unsigned int depth;			/* Disable depth for nested irq disables */
+} irq_desc_t;
+
+#include <asm/hw_irq.h> /* the arch dependent stuff */
+
+extern irq_desc_t irq_desc[NR_IRQS];
+
+extern int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
+extern spinlock_t irq_controller_lock;
+extern int setup_irq(unsigned int , struct irqaction * );
+
+#ifdef __SMP__
+
+#include <asm/atomic.h>
+
+static inline void irq_enter(int cpu, unsigned int irq)
+{
+	hardirq_enter(cpu);
+	while (test_bit(0,&global_irq_lock)) {
+		/* nothing */;
+	}
+}
+
+static inline void irq_exit(int cpu, unsigned int irq)
+{
+	hardirq_exit(cpu);
+}
+#else
+#define irq_enter(cpu, irq)	(++local_irq_count[cpu])
+#define irq_exit(cpu, irq)	(--local_irq_count[cpu])
+#endif
+
+extern hw_irq_controller no_irq_type;  /* needed in every arch ? */
+
+#endif /* __asm_h */
+
diff -u --recursive --new-file v2.3.13/linux/include/linux/isapnp.h linux/include/linux/isapnp.h
--- v2.3.13/linux/include/linux/isapnp.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/isapnp.h	Wed Aug 18 16:44:31 1999
@@ -0,0 +1,178 @@
+/*
+ *  ISA Plug & Play support
+ *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ *
+ *
+ *   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 LINUX_ISAPNP_H
+#define LINUX_ISAPNP_H
+
+#include <linux/config.h>
+
+/*
+ *  Configuration registers (TODO: change by specification)
+ */ 
+
+#define ISAPNP_CFG_ACTIVATE		0x30	/* byte */
+#define ISAPNP_CFG_MEM			0x40	/* 4 * dword */
+#define ISAPNP_CFG_PORT			0x60	/* 8 * word */
+#define ISAPNP_CFG_IRQ			0x70	/* 2 * word */
+#define ISAPNP_CFG_DMA			0x74	/* 2 * byte */
+
+/*
+ *
+ */
+
+#define ISAPNP_VENDOR(a,b,c)	(((((a)-'A'+1)&0x3f)<<2)|\
+				((((b)-'A'+1)&0x18)>>3)|((((b)-'A'+1)&7)<<13)|\
+				((((c)-'A'+1)&0x1f)<<8))
+#define ISAPNP_DEVICE(x)	((((x)&0xf000)>>8)|\
+				 (((x)&0x0f00)>>8)|\
+				 (((x)&0x00f0)<<8)|\
+				 (((x)&0x000f)<<8))
+#define ISAPNP_FUNCTION(x)	ISAPNP_DEVICE(x)
+
+/*
+ *
+ */
+
+#ifdef __KERNEL__
+
+#include <linux/pci.h>
+
+#define ISAPNP_PORT_FLAG_16BITADDR	(1<<0)
+#define ISAPNP_PORT_FLAG_FIXED		(1<<1)
+
+struct isapnp_port {
+	unsigned short min;		/* min base number */
+	unsigned short max;		/* max base number */
+	unsigned char align;		/* align boundary */
+	unsigned char size;		/* size of range */
+	unsigned short flags;		/* port flags */
+	struct isapnp_resources *res;	/* parent */
+	struct isapnp_port *next;	/* next port */
+};
+
+struct isapnp_irq {
+	unsigned short map;		/* bitmaks for IRQ lines */
+	unsigned short flags;		/* IRQ flags */
+	struct isapnp_resources *res;	/* parent */
+	struct isapnp_irq *next;	/* next IRQ */
+};
+
+struct isapnp_dma {
+	unsigned char map;		/* bitmask for DMA channels */
+	unsigned char type;		/* DMA type */
+	unsigned char flags;		/* DMA flags */
+	unsigned char speed;		/* DMA speed */
+	struct isapnp_resources *res;	/* parent */
+	struct isapnp_dma *next;	/* next port */
+};
+
+struct isapnp_mem {
+	unsigned int min;		/* min base number */
+	unsigned int max;		/* max base number */
+	unsigned int align;		/* align boundary */
+	unsigned int size;		/* size of range */
+	unsigned short flags;		/* memory flags */
+	unsigned short type;		/* memory type */
+	struct isapnp_resources *res;	/* parent */
+	struct isapnp_mem *next;	/* next memory resource */
+};
+
+struct isapnp_mem32 {
+	/* TODO */
+	unsigned char data[17];
+	struct isapnp_resources *res;	/* parent */
+	struct isapnp_mem32 *next;	/* next 32-bit memory resource */
+};
+
+#define ISAPNP_RES_PRIORITY_PREFERRED	0
+#define ISAPNP_RES_PRIORITY_ACCEPTABLE	1
+#define ISAPNP_RES_PRIORITY_FUNCTIONAL	2
+#define ISAPNP_RES_PRIORITY_INVALID	65535
+
+struct isapnp_resources {
+	unsigned short priority;	/* priority */
+	unsigned short dependent;	/* dependent resources */
+	struct isapnp_port *port;	/* first port */
+	struct isapnp_irq *irq;		/* first IRQ */
+	struct isapnp_dma *dma;		/* first DMA */
+	struct isapnp_mem *mem;		/* first memory resource */
+	struct isapnp_mem32 *mem32;	/* first 32-bit memory */
+	struct pci_dev *dev;		/* parent */
+	struct isapnp_resources *alt;	/* alternative resource (aka dependent resources) */
+	struct isapnp_resources *next;	/* next resource */
+};
+
+#ifdef CONFIG_ISAPNP
+
+/* lowlevel configuration */
+int isapnp_present(void);
+int isapnp_cfg_begin(int csn, int device);
+int isapnp_cfg_end(void);
+unsigned char isapnp_read_byte(unsigned char idx);
+unsigned short isapnp_read_word(unsigned char idx);
+unsigned int isapnp_read_dword(unsigned char idx);
+void isapnp_write_byte(unsigned char idx, unsigned char val);
+void isapnp_write_word(unsigned char idx, unsigned short val);
+void isapnp_write_dword(unsigned char idx, unsigned int val);
+void isapnp_wake(unsigned char csn);
+void isapnp_device(unsigned char device);
+void isapnp_activate(unsigned char device);
+void isapnp_deactivate(unsigned char device);
+/* manager */
+struct pci_bus *isapnp_find_card(unsigned short vendor,
+				 unsigned short device,
+				 struct pci_bus *from);
+struct pci_dev *isapnp_find_dev(struct pci_bus *card,
+				unsigned short vendor,
+				unsigned short function,
+				struct pci_dev *from);
+/* init/main.c */
+int isapnp_init(void);
+
+#else /* !CONFIG_ISAPNP */
+
+/* lowlevel configuration */
+extern inline int isapnp_present(void) { return 0; }
+extern inline int isapnp_cfg_begin(int csn, int device) { return -ENODEV; }
+extern inline int isapnp_cfg_end(void) { return -ENODEV; }
+extern inline unsigned char isapnp_read_byte(unsigned char idx) { return 0xff; }
+extern inline unsigned short isapnp_read_word(unsigned char idx) { return 0xffff; }
+extern inline unsigned int isapnp_read_dword(unsigned char idx) { return 0xffffffff; }
+extern inline void isapnp_write_byte(unsigned char idx, unsigned char val) { ; }
+extern inline void isapnp_write_word(unsigned char idx, unsigned short val) { ; }
+extern inline void isapnp_write_dword(unsigned char idx, unsigned int val) { ; }
+extern void isapnp_wake(unsigned char csn) { ; }
+extern void isapnp_device(unsigned char device) { ; }
+extern void isapnp_activate(unsigned char device) { ; }
+extern void isapnp_deactivate(unsigned char device) { ; }
+/* manager */
+extern struct pci_bus *isapnp_find_card(unsigned short vendor,
+				        unsigned short device,
+				        struct pci_bus *from) { return NULL; }
+extern struct pci_dev *isapnp_find_dev(struct pci_bus *card,
+				       unsigned short vendor,
+				       unsigned short function,
+				       struct pci_dev *from) { return NULL; }
+
+#endif /* CONFIG_ISAPNP */
+
+#endif /* __KERNEL__ */
+#endif /* LINUX_ISAPNP_H */
diff -u --recursive --new-file v2.3.13/linux/include/linux/isdn.h linux/include/linux/isdn.h
--- v2.3.13/linux/include/linux/isdn.h	Thu Jul  8 15:42:21 1999
+++ linux/include/linux/isdn.h	Wed Aug 18 11:38:46 1999
@@ -1,4 +1,4 @@
-/* $Id: isdn.h,v 1.64 1999/04/18 14:57:14 fritz Exp $
+/* $Id: isdn.h,v 1.70 1999/07/31 12:59:58 armin Exp $
  *
  * Main header for the Linux ISDN subsystem (linklevel).
  *
@@ -21,6 +21,25 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: isdn.h,v $
+ * Revision 1.70  1999/07/31 12:59:58  armin
+ * Added tty fax capabilities.
+ *
+ * Revision 1.69  1999/07/13 20:47:53  werner
+ * added channel bit ISDN_USAGE_DISABLED for limiting b-channel access.
+ *
+ * Revision 1.68  1999/07/11 17:07:37  armin
+ * Added tty modem register S23.
+ * Added new layer 2 and 3 protocols for Fax and DSP functions.
+ *
+ * Revision 1.67  1999/07/07 10:17:24  detabc
+ * remove unused messages
+ *
+ * Revision 1.66  1999/07/01 08:35:37  keil
+ * compatibility to 2.3
+ *
+ * Revision 1.65  1999/06/10 11:51:27  paul
+ * fixed comment for NET_DV
+ *
  * Revision 1.64  1999/04/18 14:57:14  fritz
  * Removed TIMRU stuff
  *
@@ -66,26 +85,6 @@
  * brute force fix to avoid Ugh's in isdn_tty_write()
  * cleaned up some dead code
  *
- * Revision 1.52  1998/06/12 11:42:18  detabc
- * cleanup abc
- *
- * Revision 1.51  1998/06/02 12:10:30  detabc
- * wegen einer einstweiliger verfuegung gegen DW ist zur zeit
- * die abc-extension bis zur klaerung der rechtslage nicht verfuegbar
- *
- * Revision 1.50  1998/05/05 23:11:51  detabc
- * add Item to stop icmp-unreach (max. 6 times of dialwait delay)
- *
- * Revision 1.49  1998/05/03 17:45:00  detabc
- * Add Item to send icmp-host-unreach to all packets
- *
- * Revision 1.48  1998/04/26 19:58:14  detabc
- * include the new abc-extension-items from 2.0.xx kernels
- * remove some unused code
- *
- * Revision 1.47  1998/04/21 18:00:25  detabc
- * Add items for secure-callback (abc-extension only)
- *
  * Revision 1.46  1998/04/14 16:28:59  he
  * Fixed user space access with interrupts off and remaining
  * copy_{to,from}_user() -> -EFAULT return codes
@@ -100,12 +99,6 @@
  * Revision 1.43  1998/03/09 17:46:44  he
  * merged in 2.1.89 changes
  *
- * Revision 1.42  1998/03/08 13:53:46  detabc
- * add ABC-variables in structur isdn_devt
- *
- * Revision 1.41  1998/03/08 13:14:37  detabc
- * abc-extension support for kernels > 2.1.x
- * first try (sorry experimental)
  *
  * Revision 1.40  1998/03/08 01:08:29  fritz
  * Increased NET_DV because of TIMRU
@@ -254,6 +247,7 @@
 #ifndef isdn_h
 #define isdn_h
 
+#include <linux/isdn_compat.h>
 #include <linux/config.h>
 #include <linux/ioctl.h>
 
@@ -333,10 +327,11 @@
 #define ISDN_USAGE_VOICE      4
 #define ISDN_USAGE_FAX        5
 #define ISDN_USAGE_MASK       7 /* Mask to get plain usage */
+#define ISDN_USAGE_DISABLED  32 /* This bit is set, if channel is disabled */
 #define ISDN_USAGE_EXCLUSIVE 64 /* This bit is set, if channel is exclusive */
 #define ISDN_USAGE_OUTGOING 128 /* This bit is set, if channel is outgoing  */
 
-#define ISDN_MODEM_ANZREG    23        /* Number of Modem-Registers        */
+#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 */
@@ -358,9 +353,9 @@
   int  outgoing;
 } isdn_net_ioctl_phone;
 
-#define NET_DV 0x05 /* Data version for net_cfg       */
-#define TTY_DV 0x05 /* Data version for iprofd etc.   */
-#define INF_DV 0x01 /* Data version for /dev/isdninfo */
+#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                     */
@@ -464,6 +459,7 @@
 #define USG_MODEM(x)        ((x & ISDN_USAGE_MASK)==ISDN_USAGE_MODEM)
 #define USG_VOICE(x)        ((x & ISDN_USAGE_MASK)==ISDN_USAGE_VOICE)
 #define USG_NET(x)          ((x & ISDN_USAGE_MASK)==ISDN_USAGE_NET)
+#define USG_FAX(x)          ((x & ISDN_USAGE_MASK)==ISDN_USAGE_FAX)
 #define USG_OUTGOING(x)     ((x & ISDN_USAGE_OUTGOING)==ISDN_USAGE_OUTGOING)
 #define USG_MODEMORVOICE(x) (((x & ISDN_USAGE_MASK)==ISDN_USAGE_MODEM) || \
                              ((x & ISDN_USAGE_MASK)==ISDN_USAGE_VOICE)     )
@@ -581,13 +577,13 @@
   ulong                  sqfull_stamp; /* Start-Time of overload           */
   ulong                  slavedelay;   /* Dynamic bundling delaytime       */
   int                    triggercps;   /* BogoCPS needed for trigger slave */
-  struct device          *srobin;      /* Ptr to Master device for slaves  */
+  struct net_device          *srobin;      /* Ptr to Master device for slaves  */
   isdn_net_phone         *phone[2];    /* List of remote-phonenumbers      */
 				       /* phone[0] = Incoming Numbers      */
 				       /* phone[1] = Outgoing Numbers      */
   isdn_net_phone         *dial;        /* Pointer to dialed number         */
-  struct device          *master;      /* Ptr to Master device for slaves  */
-  struct device          *slave;       /* Ptr to Slave device for masters  */
+  struct net_device          *master;      /* Ptr to Master device for slaves  */
+  struct net_device          *slave;       /* Ptr to Slave device for masters  */
   struct isdn_net_local_s *next;       /* Ptr to next link in bundle       */
   struct isdn_net_local_s *last;       /* Ptr to last link in bundle       */
   struct isdn_net_dev_s  *netdev;      /* Ptr to netdev                    */
@@ -599,7 +595,7 @@
 				    struct hh_cache *hh);
                                        /* Ptr to orig. header_cache_update */
   void                   (*org_hcu)(struct hh_cache *,
-				    struct device *,
+				    struct net_device *,
                                     unsigned char *);
   int  pppbind;                        /* ippp device for bindings         */
   int					dialtimeout;	/* How long shall we try on dialing? (jiffies) */
@@ -620,7 +616,7 @@
   isdn_net_local *local;
   isdn_net_local *queue;
   void           *next;                /* Pointer to next isdn-interface   */
-  struct device   dev;	       /* interface to upper levels        */
+  struct net_device   dev;	       /* interface to upper levels        */
 #ifdef CONFIG_ISDN_PPP
   struct mpqueue *mp_last; 
   struct ippp_bundle ib;
@@ -736,15 +732,19 @@
   void                  *dtmf_state;     /* state for dtmf decoder         */
   void                  *silence_state;  /* state for silence detection    */
 #endif
+#ifdef CONFIG_ISDN_TTY_FAX
+  struct T30_s		*fax;		 /* T30 Fax Group 3 data/interface */
+  int			faxonline;	 /* Fax-channel status             */
+#endif
   struct tty_struct 	*tty;            /* Pointer to corresponding tty   */
   atemu                 emu;             /* AT-emulator data               */
   struct termios	normal_termios;  /* For saving termios structs     */
   struct termios	callout_termios;
-#if LINUX_VERSION_CODE < 131841
+#ifdef COMPAT_HAS_NEW_WAITQ
+  wait_queue_head_t	open_wait, close_wait;
+#else
   struct wait_queue	*open_wait;
   struct wait_queue	*close_wait;
-#else
-  wait_queue_head_t	open_wait, close_wait;
 #endif
   struct semaphore      write_sem;
 } modem_info;
@@ -806,10 +806,10 @@
 	int (*command)(isdn_ctrl *);
 	int (*receive_callback)(int, int, struct sk_buff *);
 	int (*writebuf_skb)(int, int, int, struct sk_buff *);
-	int (*net_start_xmit)(struct sk_buff *, struct device *);
-	int (*net_receive)(struct device *, struct sk_buff *);
-	int (*net_open)(struct device *);
-	int (*net_close)(struct device *);
+	int (*net_start_xmit)(struct sk_buff *, struct net_device *);
+	int (*net_receive)(struct net_device *, struct sk_buff *);
+	int (*net_open)(struct net_device *);
+	int (*net_close)(struct net_device *);
 	int priority;
 } isdn_module;
 
@@ -823,10 +823,10 @@
 	ulong               flags;            /* Misc driver Flags                */
 	int                 locks;            /* Number of locks for this driver  */
 	int                 channels;         /* Number of channels               */
-#if LINUX_VERSION_CODE < 131841
-	struct wait_queue  *st_waitq;         /* Wait-Queue for status-read's     */
-#else
+#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                */
@@ -838,12 +838,12 @@
 	unsigned long      DLEflag;           /* Flags: Insert DLE at next read   */
 #endif
 	struct sk_buff_head *rpqueue;         /* Pointers to start of Rcv-Queue   */
-#if LINUX_VERSION_CODE < 131841
-	struct wait_queue  **rcv_waitq;       /* Wait-Queues for B-Channel-Reads  */
-	struct wait_queue  **snd_waitq;       /* Wait-Queue for B-Channel-Send's  */
-#else
+#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;
@@ -860,10 +860,10 @@
 	/*  see ISDN_TIMER_..defines  */
 	int               global_flags;
 	infostruct        *infochain;                /* List of open info-devs.    */
-#if LINUX_VERSION_CODE < 131841
-	struct wait_queue *info_waitq;               /* Wait-Queue for isdninfo    */
-#else
+#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  */
diff -u --recursive --new-file v2.3.13/linux/include/linux/isdn_budget.h linux/include/linux/isdn_budget.h
--- v2.3.13/linux/include/linux/isdn_budget.h	Sun May 23 10:03:42 1999
+++ linux/include/linux/isdn_budget.h	Wed Dec 31 16:00:00 1969
@@ -1,62 +0,0 @@
-/* isdn_budget.h
- *
- * Linux ISDN subsystem, budget-accounting for network interfaces.
- *
- * Copyright 1997       by Christian Lademann <cal@zls.de>
- * 
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
- *
- */
-
-/*
-30.06.97:cal:angelegt
-04.11.97:cal:budget.period: int --> time_t
-*/
-
-#ifndef __isdn_budget_h__
-#define __isdn_budget_h__
-
-#include	<linux/types.h>
-
-#define	ISDN_BUDGET_DIAL		0
-#define	ISDN_BUDGET_CHARGE		1
-#define	ISDN_BUDGET_ONLINE		2
-#define	ISDN_BUDGET_NUM_BUDGET		3
-
-#define	ISDN_BUDGET_INIT		0
-#define	ISDN_BUDGET_CHECK_DIAL		1
-#define	ISDN_BUDGET_CHECK_CHARGE	2
-#define	ISDN_BUDGET_CHECK_ONLINE	3
-#define	ISDN_BUDGET_START_ONLINE	10
-
-#define	ISDN_BUDGET_SET_BUDGET	0
-#define	ISDN_BUDGET_GET_BUDGET	1
-
-typedef struct {
-	char	name [9];		/* Interface */
-	int	command,		/* subcommand */
-		budget,			/* budget-nr. */
-		amount,			/* set/get budget-amount */
-		used;			/* set/get used amount */
-	time_t	period,			/* set/get length of period */
-		period_started;		/* set/get startpoint of period */
-}	isdn_ioctl_budget;
-
-#ifdef __KERNEL__
-extern int	isdn_net_budget(int, struct device *);
-extern int	isdn_budget_ioctl(isdn_ioctl_budget *);
-#endif /* __KERNEL__ */
-
-#endif /* __isdn_budget_h__ */
diff -u --recursive --new-file v2.3.13/linux/include/linux/isdn_compat.h linux/include/linux/isdn_compat.h
--- v2.3.13/linux/include/linux/isdn_compat.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/isdn_compat.h	Thu Aug 12 09:42:34 1999
@@ -0,0 +1,108 @@
+#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
+
+#endif /* __KERNEL__ */
+#endif /* _LINUX_ISDN_COMPAT_H */
diff -u --recursive --new-file v2.3.13/linux/include/linux/isdn_divertif.h linux/include/linux/isdn_divertif.h
--- v2.3.13/linux/include/linux/isdn_divertif.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/isdn_divertif.h	Thu Aug 12 09:42:34 1999
@@ -0,0 +1,62 @@
+/* 
+ * $Id: isdn_divertif.h,v 1.3 1999/07/05 20:22:00 werner Exp $
+ *
+ * Header for the diversion supplementary interface for i4l.
+ *
+ * Copyright 1998       by Werner Cornelius (werner@isdn4linux.de)
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ * $Log: isdn_divertif.h,v $
+ * Revision 1.3  1999/07/05 20:22:00  werner
+ * changes to use diversion sources for all kernel versions.
+ * removed static device, only proc filesystem used
+ *
+ * Revision 1.2  1999/07/04 21:38:38  werner
+ * ported from kernel version 2.0
+ *
+ *
+ */
+
+
+/***********************************************************/
+/* magic value is also used to control version information */
+/***********************************************************/
+#define DIVERT_IF_MAGIC 0x25873401
+#define DIVERT_CMD_REG  0x00  /* register command */
+#define DIVERT_CMD_REL  0x01  /* release command */
+#define DIVERT_NO_ERR   0x00  /* return value no error */
+#define DIVERT_CMD_ERR  0x01  /* invalid cmd */
+#define DIVERT_VER_ERR  0x02  /* magic/version invalid */
+#define DIVERT_REG_ERR  0x03  /* module already registered */
+#define DIVERT_REL_ERR  0x04  /* module not registered */
+#define DIVERT_REG_NAME isdn_register_divert
+
+/***************************************************************/
+/* structure exchanging data between isdn hl and divert module */
+/***************************************************************/ 
+typedef struct
+  { ulong if_magic; /* magic info and version */
+    int cmd; /* command */
+    int (*stat_callback)(isdn_ctrl *); /* supplied by divert module when calling */
+    int (*ll_cmd)(isdn_ctrl *); /* supplied by hl on return */
+    char * (*drv_to_name)(int); /* map a driver id to name, supplied by hl */
+    int (*name_to_drv)(char *); /* map a driver id to name, supplied by hl */
+  } isdn_divert_if;
+
+/*********************/
+/* function register */
+/*********************/
+extern int DIVERT_REG_NAME(isdn_divert_if *);
diff -u --recursive --new-file v2.3.13/linux/include/linux/isdn_ppp.h linux/include/linux/isdn_ppp.h
--- v2.3.13/linux/include/linux/isdn_ppp.h	Wed May 26 16:55:40 1999
+++ linux/include/linux/isdn_ppp.h	Sun Aug 15 11:49:08 1999
@@ -4,6 +4,7 @@
 #define _LINUX_ISDN_PPP_H
 
 #include <linux/config.h>
+#include <linux/isdn_compat.h>
 
 #define CALLTYPE_INCOMING 0x1
 #define CALLTYPE_OUTGOING 0x2
@@ -206,10 +207,10 @@
   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 */
-#if LINUX_VERSION_CODE < 131841
-  struct wait_queue *wq;
-#else
+#ifdef COMPAT_HAS_NEW_WAITQ
   wait_queue_head_t wq;
+#else
+  struct wait_queue *wq;
 #endif
   struct task_struct *tk;
   unsigned int mpppcfg;
@@ -237,6 +238,4 @@
 };
 
 #endif /* __KERNEL__ */
-
 #endif /* _LINUX_ISDN_PPP_H */
-
diff -u --recursive --new-file v2.3.13/linux/include/linux/isdnif.h linux/include/linux/isdnif.h
--- v2.3.13/linux/include/linux/isdnif.h	Sun May 23 10:03:42 1999
+++ linux/include/linux/isdnif.h	Sun Aug 15 11:49:08 1999
@@ -1,4 +1,4 @@
-/* $Id: isdnif.h,v 1.25 1998/06/17 19:51:55 he Exp $
+/* $Id: isdnif.h,v 1.29 1999/07/31 13:00:02 armin Exp $
  *
  * Linux ISDN subsystem
  *
@@ -22,6 +22,19 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: isdnif.h,v $
+ * Revision 1.29  1999/07/31 13:00:02  armin
+ * Added tty fax capabilities.
+ *
+ * Revision 1.28  1999/07/13 20:57:48  werner
+ * added callback ISDN_STAT_DISCH for limiting b-channel resources.
+ *
+ * Revision 1.27  1999/07/11 17:07:39  armin
+ * Added tty modem register S23.
+ * Added new layer 2 and 3 protocols for Fax and DSP functions.
+ *
+ * Revision 1.26  1999/07/01 08:35:44  keil
+ * compatibility to 2.3
+ *
  * Revision 1.25  1998/06/17 19:51:55  he
  * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
  * brute force fix to avoid Ugh's in isdn_tty_write()
@@ -121,6 +134,9 @@
 #ifndef isdnif_h
 #define isdnif_h
 
+#include <linux/config.h>
+#include <linux/isdn_compat.h>
+
 /*
  * Values for general protocol-selection
  */
@@ -145,18 +161,105 @@
 #define ISDN_PROTO_L2_V11019 8   /* V.110 bitrate adaption 19200 Baud */
 #define ISDN_PROTO_L2_V11038 9   /* V.110 bitrate adaption 38400 Baud */
 #define ISDN_PROTO_L2_MODEM  10  /* Analog Modem on Board */
+#define ISDN_PROTO_L2_FAX    11  /* Fax Group 2/3         */
 #define ISDN_PROTO_L2_MAX    15  /* Max. 16 Protocols                 */
 
 /*
  * Values for Layer-3-protocol-selection
  */
 #define ISDN_PROTO_L3_TRANS  0   /* Transparent                 */
+#define ISDN_PROTO_L3_TRANSDSP 1   /* Transparent with DSP    */
+#define ISDN_PROTO_L3_FAX    2   /* Fax Group 2/3             */
 #define ISDN_PROTO_L3_MAX    7   /* Max. 8 Protocols            */
 
 #ifdef __KERNEL__
 
 #include <linux/skbuff.h>
 
+/***************************************************************************/
+/* Extensions made by Werner Cornelius (werner@ikt.de)                     */
+/*                                                                         */ 
+/* The proceed command holds a incoming call in a state to leave processes */
+/* enough time to check whether ist should be accepted.                    */
+/* The PROT_IO Command extends the interface to make protocol dependant    */
+/* features available (call diversion, call waiting...).                   */
+/*                                                                         */ 
+/* The PROT_IO Command is executed with the desired driver id and the arg  */
+/* parameter coded as follows:                                             */
+/* The lower 8 bits of arg contain the desired protocol from ISDN_PTYPE    */
+/* definitions. The upper 24 bits represent the protocol specific cmd/stat.*/
+/* Any additional data is protocol and command specific.                   */
+/* This mechanism also applies to the statcallb callback STAT_PROT.        */    
+/*                                                                         */
+/* This suggested extension permits an easy expansion of protocol specific */
+/* handling. Extensions may be added at any time without changing the HL   */
+/* driver code and not getting conflicts without certifications.           */
+/* The well known CAPI 2.0 interface handles such extensions in a similar  */
+/* way. Perhaps a protocol specific module may be added and separately     */
+/* loaded and linked to the basic isdn module for handling.                */                    
+/***************************************************************************/
+
+/*****************/
+/* DSS1 commands */ 
+/*****************/
+#define DSS1_CMD_INVOKE       ((0x00 << 8) | ISDN_PTYPE_EURO)   /* invoke a supplementary service */
+#define DSS1_CMD_INVOKE_ABORT ((0x01 << 8) | ISDN_PTYPE_EURO)   /* abort a invoke cmd */
+
+/*******************************/
+/* DSS1 Status callback values */
+/*******************************/
+#define DSS1_STAT_INVOKE_RES  ((0x80 << 8) | ISDN_PTYPE_EURO)   /* Result for invocation */
+#define DSS1_STAT_INVOKE_ERR  ((0x81 << 8) | ISDN_PTYPE_EURO)   /* Error Return for invocation */
+#define DSS1_STAT_INVOKE_BRD  ((0x82 << 8) | ISDN_PTYPE_EURO)   /* Deliver invoke broadcast info */
+
+
+/*********************************************************************/
+/* structures for DSS1 commands and callback                         */
+/*                                                                   */
+/* An action is invoked by sending a DSS1_CMD_INVOKE. The ll_id, proc*/
+/* timeout, datalen and data fields must be set before calling.      */
+/*                                                                   */
+/* The return value is a positive hl_id value also delivered in the  */
+/* hl_id field. A value of zero signals no more left hl_id capacitys.*/
+/* A negative return value signals errors in LL. So if the return    */
+/* value is <= 0 no action in LL will be taken -> request ignored    */
+/*                                                                   */
+/* The timeout field must be filled with a positive value specifying */
+/* the amount of time the INVOKED process waits for a reaction from  */
+/* the network.                                                      */
+/* If a response (either error or result) is received during this    */
+/* intervall, a reporting callback is initiated and the process will */
+/* be deleted, the hl identifier will be freed.                      */
+/* If no response is received during the specified intervall, a error*/
+/* callback is initiated with timeout set to -1 and a datalen set    */
+/* to 0.                                                             */
+/* If timeout is set to a value <= 0 during INVOCATION the process is*/
+/* immediately deleted after sending the data. No callback occurs !  */
+/*                                                                   */
+/* A currently waiting process may be aborted with INVOKE_ABORT. No  */
+/* callback will occur when a process has been aborted.              */
+/*                                                                   */
+/* Broadcast invoke frames from the network are reported via the     */
+/* STAT_INVOKE_BRD callback. The ll_id is set to 0, the other fields */
+/* are supplied by the network and not by the HL.                    */   
+/*********************************************************************/
+typedef struct
+  { ulong ll_id; /* ID supplied by LL when executing    */
+		 /* a command and returned by HL for    */
+                 /* INVOKE_RES and INVOKE_ERR           */
+    int hl_id;   /* ID supplied by HL when called       */
+                 /* for executing a cmd and delivered   */
+                 /* for results and errors              */
+                 /* must be supplied by LL when aborting*/  
+    int proc;    /* invoke procedure used by CMD_INVOKE */
+                 /* returned by callback and broadcast  */ 
+    int timeout; /* timeout for INVOKE CMD in ms        */
+                 /* -1  in stat callback when timed out */
+                 /* error value when error callback     */
+    int datalen; /* length of cmd or stat data          */
+    u_char *data;/* pointer to data delivered or send   */
+  } dss1_cmd_stat;
+
 /*
  * Commands from linklevel to lowlevel
  *
@@ -179,7 +282,13 @@
 #define ISDN_CMD_UNLOCK  15       /* Release usage-lock                    */
 #define ISDN_CMD_SUSPEND 16       /* Suspend connection                    */
 #define ISDN_CMD_RESUME  17       /* Resume connection                     */
-#define CAPI_PUT_MESSAGE 18       /* CAPI message send down or up          */
+#define ISDN_CMD_PROCEED 18       /* Proceed with call establishment       */
+#define ISDN_CMD_ALERT   19       /* Alert after Proceeding                */
+#define ISDN_CMD_REDIR   20       /* Redir a incoming call                 */
+#define ISDN_CMD_PROT_IO 21       /* Protocol specific commands            */
+#define CAPI_PUT_MESSAGE 22       /* CAPI message send down or up          */
+#define ISDN_CMD_FAXCMD  23       /* FAX commands to HL-driver             */
+#define ISDN_CMD_AUDIO   24       /* DSP, DTMF, ... settings               */
 
 /*
  * Status-Values delivered from lowlevel to linklevel via
@@ -201,7 +310,20 @@
 #define ISDN_STAT_NODCH   268    /* Signal no D-Channel                   */
 #define ISDN_STAT_ADDCH   269    /* Add more Channels                     */
 #define ISDN_STAT_CAUSE   270    /* Cause-Message                         */
-#define ISDN_STAT_L1ERR   271    /* Signal Layer-1 Error                  */
+#define ISDN_STAT_ICALLW  271    /* Incoming call without B-chan waiting  */
+#define ISDN_STAT_REDIR   272    /* Redir result                          */
+#define ISDN_STAT_PROT    273    /* protocol IO specific callback         */
+#define ISDN_STAT_DISPLAY 274    /* deliver a received display message    */
+#define ISDN_STAT_L1ERR   275    /* Signal Layer-1 Error                  */
+#define ISDN_STAT_FAXIND  276    /* FAX indications from HL-driver        */
+#define ISDN_STAT_AUDIO   277    /* DTMF, DSP indications                 */
+#define ISDN_STAT_DISCH   278    /* Disable/Enable channel usage          */
+
+/*
+ * Audio commands
+ */
+#define ISDN_AUDIO_SETDD	0	/* Set DTMF detection           */
+#define ISDN_AUDIO_DTMF		1	/* Rx/Tx DTMF                   */
 
 /*
  * Values for errcode field
@@ -224,12 +346,15 @@
 #define ISDN_FEATURE_L2_V11019  (0x0001 << ISDN_PROTO_L2_V11019)
 #define ISDN_FEATURE_L2_V11038  (0x0001 << ISDN_PROTO_L2_V11038)
 #define ISDN_FEATURE_L2_MODEM   (0x0001 << ISDN_PROTO_L2_MODEM)
+#define ISDN_FEATURE_L2_FAX	(0x0001 << ISDN_PROTO_L2_FAX)
 
 #define ISDN_FEATURE_L2_MASK    (0x0FFFF) /* Max. 16 protocols */
 #define ISDN_FEATURE_L2_SHIFT   (0)
 
 /* Layer 3 */
 #define ISDN_FEATURE_L3_TRANS   (0x10000 << ISDN_PROTO_L3_TRANS)
+#define ISDN_FEATURE_L3_TRANSDSP (0x10000 << ISDN_PROTO_L3_TRANSDSP)
+#define ISDN_FEATURE_L3_FAX	(0x10000 << ISDN_PROTO_L3_FAX)
 
 #define ISDN_FEATURE_L3_MASK    (0x0FF0000) /* Max. 8 Protocols */
 #define ISDN_FEATURE_L3_SHIFT   (16)
@@ -252,6 +377,84 @@
     unsigned char screen;   /* Screening info      */
 } setup_parm;
 
+
+#ifdef CONFIG_ISDN_TTY_FAX
+/* T.30 Fax G3 */
+
+#define FAXIDLEN 21
+
+typedef struct T30_s {
+	/* session parameters */
+	__u8 resolution		__attribute__ ((packed));
+	__u8 rate		__attribute__ ((packed));
+	__u8 width		__attribute__ ((packed));
+	__u8 length		__attribute__ ((packed));
+	__u8 compression	__attribute__ ((packed));
+	__u8 ecm		__attribute__ ((packed));
+	__u8 binary		__attribute__ ((packed));
+	__u8 scantime		__attribute__ ((packed));
+	__u8 id[FAXIDLEN]	__attribute__ ((packed));
+	/* additional parameters */
+	__u8 phase		__attribute__ ((packed));
+	__u8 direction		__attribute__ ((packed));
+	__u8 code		__attribute__ ((packed));
+	__u8 badlin		__attribute__ ((packed));
+	__u8 badmul		__attribute__ ((packed));
+	__u8 bor		__attribute__ ((packed));
+	__u8 fet		__attribute__ ((packed));
+	__u8 pollid[FAXIDLEN]	__attribute__ ((packed));
+	__u8 cq			__attribute__ ((packed));
+	__u8 cr			__attribute__ ((packed));
+	__u8 ctcrty		__attribute__ ((packed));
+	__u8 minsp		__attribute__ ((packed));
+	__u8 phcto		__attribute__ ((packed));
+	__u8 rel		__attribute__ ((packed));
+	__u8 nbc		__attribute__ ((packed));
+	/* remote station parameters */
+	__u8 r_resolution	__attribute__ ((packed));
+	__u8 r_rate		__attribute__ ((packed));
+	__u8 r_width		__attribute__ ((packed));
+	__u8 r_length		__attribute__ ((packed));
+	__u8 r_compression	__attribute__ ((packed));
+	__u8 r_ecm		__attribute__ ((packed));
+	__u8 r_binary		__attribute__ ((packed));
+	__u8 r_scantime		__attribute__ ((packed));
+	__u8 r_id[FAXIDLEN]	__attribute__ ((packed));
+	__u8 r_code		__attribute__ ((packed));
+} T30_s;
+
+#define ISDN_TTY_FAX_CONN_IN	0
+#define ISDN_TTY_FAX_CONN_OUT	1
+
+#define ISDN_TTY_FAX_FCON	0
+#define ISDN_TTY_FAX_DIS 	1
+#define ISDN_TTY_FAX_FTT 	2
+#define ISDN_TTY_FAX_MCF 	3
+#define ISDN_TTY_FAX_DCS 	4
+#define ISDN_TTY_FAX_TRAIN_OK	5
+#define ISDN_TTY_FAX_EOP 	6
+#define ISDN_TTY_FAX_EOM 	7
+#define ISDN_TTY_FAX_MPS 	8
+#define ISDN_TTY_FAX_DTC 	9
+#define ISDN_TTY_FAX_RID 	10
+#define ISDN_TTY_FAX_HNG 	11
+#define ISDN_TTY_FAX_DT  	12
+#define ISDN_TTY_FAX_FCON_I	13
+#define ISDN_TTY_FAX_DR  	14
+#define ISDN_TTY_FAX_ET  	15
+#define ISDN_TTY_FAX_CFR 	16
+#define ISDN_TTY_FAX_PTS 	17
+#define ISDN_TTY_FAX_SENT	18
+
+#define ISDN_FAX_PHASE_IDLE	0
+#define ISDN_FAX_PHASE_A	1
+#define ISDN_FAX_PHASE_B   	2
+#define ISDN_FAX_PHASE_C   	3
+#define ISDN_FAX_PHASE_D   	4
+#define ISDN_FAX_PHASE_E   	5
+
+#endif /* TTY_FAX */
+
 /* CAPI structs */
 
 /* this is compatible to the old union size */
@@ -274,22 +477,26 @@
 	__u8 para[MAX_CAPI_PARA_LEN];
 } capi_msg;
 
-
 /*
  * Structure for exchanging above infos
  *
  */
 typedef struct {
-  int   driver;                  /* Lowlevel-Driver-ID                    */
-  int   command;                 /* Command or Status (see above)         */
-  ulong arg;                     /* Additional Data                       */
-  union {
-	ulong errcode;               /* Type of error with STAT_L1ERR         */
-	int   length;                /* Amount of bytes sent with STAT_BSENT  */
-	u_char	num[50];	/* Additional Data			*/
-	setup_parm 	setup;	/* For SETUP msg			*/
-	capi_msg  	cmsg;	/* For CAPI like messages		*/
-  } parm;
+	int   driver;		/* Lowlevel-Driver-ID            */
+	int   command;		/* Command or Status (see above) */
+	ulong arg;		/* Additional Data               */
+	union {
+		ulong errcode;	/* Type of error with STAT_L1ERR         */
+		int length;	/* Amount of bytes sent with STAT_BSENT  */
+		u_char num[50];/* Additional Data			*/
+		setup_parm setup;/* For SETUP msg			*/
+		capi_msg cmsg;	/* For CAPI like messages		*/
+		char display[85];/* display message data          */ 
+		dss1_cmd_stat dss1_io; /* DSS1 IO-parameter/result */
+#ifdef CONFIG_ISDN_TTY_FAX
+		T30_s	*fax;	/* Pointer to ttys fax struct		*/
+#endif
+	} parm;
 } isdn_ctrl;
 
 /*
@@ -410,10 +617,6 @@
  *
  */
 extern int register_isdn(isdn_if*);
-
-#ifndef LINUX_VERSION_CODE
-#include <linux/version.h>
-#endif
 #include <asm/uaccess.h>
 
 #endif /* __KERNEL__ */
diff -u --recursive --new-file v2.3.13/linux/include/linux/kernelcapi.h linux/include/linux/kernelcapi.h
--- v2.3.13/linux/include/linux/kernelcapi.h	Thu May 29 21:53:11 1997
+++ linux/include/linux/kernelcapi.h	Thu Aug 12 09:42:34 1999
@@ -1,11 +1,30 @@
 /*
- * $Id: kernelcapi.h,v 1.1 1997/03/04 21:27:33 calle Exp $
+ * $Id: kernelcapi.h,v 1.3 1999/07/01 15:26:56 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.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:
+ *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ *   - write a CAPI-2.0 for the passive cards
+ *   - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ *   make menuconfig, in the past all supported cards where included
+ *   at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ *   using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+ *
+ * Revision 1.2  1999/06/21 15:24:26  calle
+ * extend information in /proc.
+ *
  * Revision 1.1  1997/03/04 21:27:33  calle
  * First version in isdn4linux
  *
@@ -17,17 +36,37 @@
  *
  * 
  */
-#ifndef __KERNEL_CAPI_H__
-#define __KERNEL_CAPI_H__
+#ifndef __KERNELCAPI_H__
+#define __KERNELCAPI_H__
 
 #define CAPI_MAXAPPL	20	/*
 				   * maximum number of applications 
 				 */
-#define CAPI_MAXCONTR	4	/*
+#define CAPI_MAXCONTR	10	/*
 				   * maximum number of controller 
 				 */
 #define CAPI_MAXDATAWINDOW	8
 
+
+typedef struct kcapi_flagdef {
+	int contr;
+	int flag;
+} kcapi_flagdef;
+
+/* new ioctls >= 10 */
+#define KCAPI_CMD_TRACE		10
+
+/* 
+ * flag > 2 => trace also data
+ * flag & 1 => show trace
+ */
+#define KCAPI_TRACE_OFF			0
+#define KCAPI_TRACE_SHORT_NO_DATA	1
+#define KCAPI_TRACE_FULL_NO_DATA	2
+#define KCAPI_TRACE_SHORT		3
+#define KCAPI_TRACE_FULL		4
+
+
 #ifdef __KERNEL__
 
 struct capi_interface {
@@ -58,6 +97,7 @@
 struct capi_interface_user {
 	char name[20];
 	void (*callback) (unsigned int cmd, __u16 contr, void *data);
+	/* internal */
 	struct capi_interface_user *next;
 };
 
@@ -93,4 +133,4 @@
 
 #endif				/* __KERNEL__ */
 
-#endif				/* __KERNEL_CAPI_H__ */
+#endif				/* __KERNELCAPI_H__ */
diff -u --recursive --new-file v2.3.13/linux/include/linux/lp_intern.h linux/include/linux/lp_intern.h
--- v2.3.13/linux/include/linux/lp_intern.h	Fri Dec 20 01:20:03 1996
+++ linux/include/linux/lp_intern.h	Wed Dec 31 16:00:00 1969
@@ -1,22 +0,0 @@
-#ifndef _LINUX_LP_INTERN_H_
-#define _LINUX_LP_INTERN_H_
-
-/*
- * split in two parts by Joerg Dorchain
- * usr/include/linux/lp.h  modified for Amiga by Michael Rausch
- * modified for Atari by Andreas Schwab
- * bug fixed by Jes Sorensen 18/8-94:
- *     It was not possible to compile the kernel only for Atari or Amiga.
- *
- * linux i386 version  c.1991-1992 James Wiegand
- * many modifications copyright (C) 1992 Michael K. Johnson
- * Interrupt support added 1993 Nigel Gamble
- */
-
-#include <linux/types.h>
-#include <linux/lp_m68k.h>
-
-int lp_internal_init(void);
-
-#endif
-
diff -u --recursive --new-file v2.3.13/linux/include/linux/lp_m68k.h linux/include/linux/lp_m68k.h
--- v2.3.13/linux/include/linux/lp_m68k.h	Sat May 15 15:05:37 1999
+++ linux/include/linux/lp_m68k.h	Wed Dec 31 16:00:00 1969
@@ -1,135 +0,0 @@
-#ifndef _LINUX_LP_H
-#define _LINUX_LP_H
-
-/*
- * split in two parts by Joerg Dorchain
- * usr/include/linux/lp.h  modified for Amiga by Michael Rausch
- * modified for Atari by Andreas Schwab
- * bug fixed by Jes Sorensen 18/8-94:
- *     It was not possible to compile the kernel only for Atari or Amiga.
- *
- * linux i386 version  c.1991-1992 James Wiegand
- * many modifications copyright (C) 1992 Michael K. Johnson
- * Interrupt support added 1993 Nigel Gamble
- */
-
-/*
- *  many many printers are we going to support? currently, this is the
- *  hardcoded limit
- */
-#define MAX_LP 5
-
-/*
- * Per POSIX guidelines, this module reserves the LP and lp prefixes
- * These are the lp_table[minor].flags flags...
- */
-#define LP_EXIST 0x0001
-#define LP_BUSY	 0x0004
-#define LP_ABORT 0x0040
-#define LP_CAREFUL 0x0080
-#define LP_ABORTOPEN 0x0100
-
-/* timeout for each character.  This is relative to bus cycles -- it
- * is the count in a busy loop.  THIS IS THE VALUE TO CHANGE if you
- * have extremely slow printing, or if the machine seems to slow down
- * a lot when you print.  If you have slow printing, increase this
- * number and recompile, and if your system gets bogged down, decrease
- * this number.  This can be changed with the tunelp(8) command as well.
- */
-
-#define LP_INIT_CHAR 1000
-
-/* The parallel port specs apparently say that there needs to be
- * a .5usec wait before and after the strobe.  Since there are wildly
- * different computers running linux, I can't come up with a perfect
- * value, but since it worked well on most printers before without,
- * I'll initialize it to 0.
- */
-
-#define LP_INIT_WAIT 0
-
-/* This is the amount of time that the driver waits for the printer to
- * catch up when the printer's buffer appears to be filled.  If you
- * want to tune this and have a fast printer (i.e. HPIIIP), decrease
- * this number, and if you have a slow printer, increase this number.
- * This is in hundredths of a second, the default 2 being .05 second.
- * Or use the tunelp(8) command, which is especially nice if you want
- * change back and forth between character and graphics printing, which
- * are wildly different...
- */
-
-#define LP_INIT_TIME 40
-
-/* IOCTL numbers */
-#define LPCHAR   0x0601  /* corresponds to LP_INIT_CHAR */
-#define LPTIME   0x0602  /* corresponds to LP_INIT_TIME */
-#define LPABORT  0x0604  /* call with TRUE arg to abort on error,
-			    FALSE to retry.  Default is retry.  */
-#define LPSETIRQ 0x0605  /* call with new IRQ number,
-			    or 0 for polling (no IRQ) */
-#define LPGETIRQ 0x0606  /* get the current IRQ number */
-#define LPWAIT   0x0608  /* corresponds to LP_INIT_WAIT */
-#define LPCAREFUL   0x0609  /* call with TRUE arg to require out-of-paper, off-
-			    line, and error indicators good on all writes,
-			    FALSE to ignore them.  Default is ignore. */
-#define LPABORTOPEN 0x060a  /* call with TRUE arg to abort open() on error,
-			    FALSE to ignore error.  Default is ignore.  */
-#define LPGETSTATUS 0x060b  /* return LP_S(minor) */
-#define LPRESET     0x060c  /* reset printer */
-
-/* timeout for printk'ing a timeout, in jiffies (100ths of a second).
-   This is also used for re-checking error conditions if LP_ABORT is
-   not set.  This is the default behavior. */
-
-#define LP_TIMEOUT_INTERRUPT	(60 * HZ)
-#define LP_TIMEOUT_POLLED	(10 * HZ)
-
-
-#define LP_BUFFER_SIZE 1024 /*256*/
-
-enum lp_type  {
-LP_UNKNOWN = 0,
-LP_AMIGA = 1,
-LP_ATARI = 2,
-LP_MFC = 3,
-LP_IOEXT = 4,
-LP_MVME167 = 5,
-LP_BVME6000 = 6
-};
-
-/*
- * warning: this structure is in kernel space and has to fit in one page,
- * i.e. must not be larger than 4k
- */
-struct lp_struct {
-	char *name;
-	unsigned int irq;
-	void (*lp_out)(int,int);	/*output char function*/
-	int (*lp_is_busy)(int);
-	int (*lp_has_pout)(int);
-	int (*lp_is_online)(int);
-	int (*lp_dummy)(int);
-	int (*lp_ioctl)(int, unsigned int, unsigned long);
-	int (*lp_open)(int);		/* for module use counter */
-	void (*lp_release)(int);	/* for module use counter */
-	int flags;		/*for BUSY... */
-	unsigned int chars;	/*busy timeout */
-	unsigned int time;	/*wait time */
-	unsigned int wait;
-	struct wait_queue_head_t lp_wait_q; /*strobe wait */
-	void *base;			/* hardware drivers internal use*/
-	enum lp_type type;
-	char lp_buffer[LP_BUFFER_SIZE];
-	int do_print;
-	unsigned long copy_size,bytes_written;
-};
-
-extern struct lp_struct *lp_table[MAX_LP];
-extern unsigned int lp_irq;
-
-void lp_interrupt(int dev);
-int lp_m68k_init(void);
-int register_parallel(struct lp_struct *, int);
-void unregister_parallel(int);
-
-#endif
diff -u --recursive --new-file v2.3.13/linux/include/linux/lp_mfc.h linux/include/linux/lp_mfc.h
--- v2.3.13/linux/include/linux/lp_mfc.h	Fri Dec 20 01:20:04 1996
+++ linux/include/linux/lp_mfc.h	Wed Dec 31 16:00:00 1969
@@ -1,14 +0,0 @@
-#ifndef _LINUX_LP_MFC_H_
-#define _LINUX_LP_MFC_H_
-
-/*
- * created 6.11.95 Joerg Dorchain
- */
-
-#include <linux/types.h>
-#include <linux/lp_m68k.h>
-
-int lp_mfc_init(void);
-
-#endif
-
diff -u --recursive --new-file v2.3.13/linux/include/linux/mc6821.h linux/include/linux/mc6821.h
--- v2.3.13/linux/include/linux/mc6821.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/mc6821.h	Thu Aug 12 10:27:31 1999
@@ -0,0 +1,51 @@
+#ifndef _MC6821_H_
+#define _MC6821_H_
+
+/*
+ * This file describes the memery mapping of the MC6821 PIA.
+ * The unions describe overlayed registers. Which of them is used is
+ * determined by bit 2 of the corresponding control register.
+ * this files expects the PIA_REG_PADWIDTH to be defined the numeric
+ * value of the register spacing.
+ *
+ * Data came from MFC-31-Developer Kit (from Ralph Seidel,
+ * zodiac@darkness.gun.de) and Motorola Data Sheet (from 
+ * Richard Hirst, srh@gpt.co.uk)
+ *
+ * 6.11.95 copyright Joerg Dorchain (dorchain@mpi-sb.mpg.de)
+ *
+ */
+
+#ifndef PIA_REG_PADWIDTH
+#define PIA_REG_PADWIDTH 255
+#endif
+
+struct pia {
+	union {
+		volatile u_char pra;
+		volatile u_char ddra;
+	} ua;
+	u_char pad1[PIA_REG_PADWIDTH];
+	volatile u_char cra;
+	u_char pad2[PIA_REG_PADWIDTH];
+	union {
+		volatile u_char prb;
+		volatile u_char ddrb;
+	} ub;
+	u_char pad3[PIA_REG_PADWIDTH];
+	volatile u_char crb;
+	u_char pad4[PIA_REG_PADWIDTH];
+};
+
+#define ppra ua.pra
+#define pddra ua.ddra
+#define pprb ub.prb
+#define pddrb ub.ddrb
+
+#define PIA_C1_ENABLE_IRQ (1<<0)
+#define PIA_C1_LOW_TO_HIGH (1<<1)
+#define PIA_DDR (1<<2)
+#define PIA_IRQ2 (1<<6)
+#define PIA_IRQ1 (1<<7)
+
+#endif
diff -u --recursive --new-file v2.3.13/linux/include/linux/mroute.h linux/include/linux/mroute.h
--- v2.3.13/linux/include/linux/mroute.h	Tue Jun 22 14:42:48 1999
+++ linux/include/linux/mroute.h	Wed Aug 18 16:44:38 1999
@@ -138,7 +138,7 @@
 
 struct vif_device
 {
-	struct device 	*dev;			/* Device we are using */
+	struct net_device 	*dev;			/* Device we are using */
 	unsigned long	bytes_in,bytes_out;
 	unsigned long	pkt_in,pkt_out;		/* Statistics 			*/
 	unsigned long	rate_limit;		/* Traffic shaping (NI) 	*/
diff -u --recursive --new-file v2.3.13/linux/include/linux/netdevice.h linux/include/linux/netdevice.h
--- v2.3.13/linux/include/linux/netdevice.h	Tue Jun 22 14:42:35 1999
+++ linux/include/linux/netdevice.h	Wed Aug 18 16:44:28 1999
@@ -166,11 +166,11 @@
  *	data with strictly "high-level" data, and it has to know about
  *	almost every data structure used in the INET module.
  *
- *	FIXME: cleanup struct device such that network protocol info
+ *	FIXME: cleanup struct net_device such that network protocol info
  *	moves out.
  */
 
-struct device
+struct net_device
 {
 
 	/*
@@ -202,11 +202,11 @@
 	unsigned long		interrupt;	/* bitops.. */
 	unsigned long		tbusy;		/* transmitter busy */
 	
-	struct device		*next;
+	struct net_device		*next;
 	
 	/* The device initialization function. Called only once. */
-	int			(*init)(struct device *dev);
-	void			(*destructor)(struct device *dev);
+	int			(*init)(struct net_device *dev);
+	void			(*destructor)(struct net_device *dev);
 
 	/* Interface index. Unique device identifier	*/
 	int			ifindex;
@@ -220,8 +220,8 @@
 	unsigned char		if_port;	/* Selectable AUI, TP,..*/
 	unsigned char		dma;		/* DMA channel		*/
 
-	struct net_device_stats* (*get_stats)(struct device *dev);
-	struct iw_statistics*	(*get_wireless_stats)(struct device *dev);
+	struct net_device_stats* (*get_stats)(struct net_device *dev);
+	struct iw_statistics*	(*get_wireless_stats)(struct net_device *dev);
 
 	/*
 	 * This marks the end of the "visible" part of the structure. All
@@ -254,7 +254,7 @@
 	/* For load balancing driver pair support */
   
 	unsigned long		pkt_queue;	/* Packets queued	*/
-	struct device		*slave;		/* Slave device		*/
+	struct net_device		*slave;		/* Slave device		*/
 
 	/* Protocol specific pointers */
 	
@@ -279,41 +279,41 @@
 	atomic_t		refcnt;
 
 	/* Pointers to interface service routines.	*/
-	int			(*open)(struct device *dev);
-	int			(*stop)(struct device *dev);
+	int			(*open)(struct net_device *dev);
+	int			(*stop)(struct net_device *dev);
 	int			(*hard_start_xmit) (struct sk_buff *skb,
-						    struct device *dev);
+						    struct net_device *dev);
 	int			(*hard_header) (struct sk_buff *skb,
-						struct device *dev,
+						struct net_device *dev,
 						unsigned short type,
 						void *daddr,
 						void *saddr,
 						unsigned len);
 	int			(*rebuild_header)(struct sk_buff *skb);
 #define HAVE_MULTICAST			 
-	void			(*set_multicast_list)(struct device *dev);
+	void			(*set_multicast_list)(struct net_device *dev);
 #define HAVE_SET_MAC_ADDR  		 
-	int			(*set_mac_address)(struct device *dev,
+	int			(*set_mac_address)(struct net_device *dev,
 						   void *addr);
 #define HAVE_PRIVATE_IOCTL
-	int			(*do_ioctl)(struct device *dev,
+	int			(*do_ioctl)(struct net_device *dev,
 					    struct ifreq *ifr, int cmd);
 #define HAVE_SET_CONFIG
-	int			(*set_config)(struct device *dev,
+	int			(*set_config)(struct net_device *dev,
 					      struct ifmap *map);
 #define HAVE_HEADER_CACHE
 	int			(*hard_header_cache)(struct neighbour *neigh,
 						     struct hh_cache *hh);
 	void			(*header_cache_update)(struct hh_cache *hh,
-						       struct device *dev,
+						       struct net_device *dev,
 						       unsigned char *  haddr);
 #define HAVE_CHANGE_MTU
-	int			(*change_mtu)(struct device *dev, int new_mtu);
+	int			(*change_mtu)(struct net_device *dev, int new_mtu);
 
 	int			(*hard_header_parse)(struct sk_buff *skb,
 						     unsigned char *haddr);
-	int			(*neigh_setup)(struct device *dev, struct neigh_parms *);
-	int			(*accept_fastpath)(struct device *, struct dst_entry*);
+	int			(*neigh_setup)(struct net_device *dev, struct neigh_parms *);
+	int			(*accept_fastpath)(struct net_device *, struct dst_entry*);
 
 #ifdef CONFIG_NET_FASTROUTE
 	/* Really, this semaphore may be necessary and for not fastroute code;
@@ -330,8 +330,8 @@
 struct packet_type 
 {
 	unsigned short		type;	/* This is really htons(ether_type).	*/
-	struct device		*dev;	/* NULL is wildcarded here		*/
-	int			(*func) (struct sk_buff *, struct device *,
+	struct net_device		*dev;	/* NULL is wildcarded here		*/
+	int			(*func) (struct sk_buff *, struct net_device *,
 					 struct packet_type *);
 	void			*data;	/* Private to the packet type		*/
 	struct packet_type	*next;
@@ -341,31 +341,31 @@
 #include <linux/interrupt.h>
 #include <linux/notifier.h>
 
-extern struct device		loopback_dev;		/* The loopback */
-extern struct device		*dev_base;		/* All devices */
+extern struct net_device		loopback_dev;		/* The loopback */
+extern struct net_device		*dev_base;		/* All devices */
 extern rwlock_t			dev_base_lock;		/* Device list lock */
 extern int			netdev_dropping;
 extern int			net_cpu_congestion;
 
-extern struct device    *dev_getbyhwaddr(unsigned short type, char *hwaddr);
+extern struct net_device    *dev_getbyhwaddr(unsigned short type, char *hwaddr);
 extern void		dev_add_pack(struct packet_type *pt);
 extern void		dev_remove_pack(struct packet_type *pt);
-extern struct device	*dev_get(const char *name);
-extern struct device	*dev_alloc(const char *name, int *err);
-extern int		dev_alloc_name(struct device *dev, const char *name);
-extern int		dev_open(struct device *dev);
-extern int		dev_close(struct device *dev);
+extern struct net_device	*dev_get(const char *name);
+extern struct net_device	*dev_alloc(const char *name, int *err);
+extern int		dev_alloc_name(struct net_device *dev, const char *name);
+extern int		dev_open(struct net_device *dev);
+extern int		dev_close(struct net_device *dev);
 extern int		dev_queue_xmit(struct sk_buff *skb);
 extern void		dev_loopback_xmit(struct sk_buff *skb);
-extern int		register_netdevice(struct device *dev);
-extern int		unregister_netdevice(struct device *dev);
+extern int		register_netdevice(struct net_device *dev);
+extern int		unregister_netdevice(struct net_device *dev);
 extern int 		register_netdevice_notifier(struct notifier_block *nb);
 extern int		unregister_netdevice_notifier(struct notifier_block *nb);
 extern int		dev_new_index(void);
-extern struct device	*dev_get_by_index(int ifindex);
-extern int		dev_restart(struct device *dev);
+extern struct net_device	*dev_get_by_index(int ifindex);
+extern int		dev_restart(struct net_device *dev);
 
-typedef int gifconf_func_t(struct device * dev, char * bufptr, int len);
+typedef int gifconf_func_t(struct net_device * dev, char * bufptr, int len);
 extern int		register_gifconf(unsigned int family, gifconf_func_t * gifconf);
 extern __inline__ int unregister_gifconf(unsigned int family)
 {
@@ -377,8 +377,8 @@
 extern void		net_bh(void);
 extern int		dev_get_info(char *buffer, char **start, off_t offset, int length, int dummy);
 extern int		dev_ioctl(unsigned int cmd, void *);
-extern int		dev_change_flags(struct device *, unsigned);
-extern void		dev_queue_xmit_nit(struct sk_buff *skb, struct device *dev);
+extern int		dev_change_flags(struct net_device *, unsigned);
+extern void		dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev);
 
 extern void		dev_init(void);
 
@@ -422,35 +422,35 @@
 	}
 }
 
-extern __inline__ void dev_init_buffers(struct device *dev)
+extern __inline__ void dev_init_buffers(struct net_device *dev)
 {
 	/* DO NOTHING */
 }
 
 /* These functions live elsewhere (drivers/net/net_init.c, but related) */
 
-extern void		ether_setup(struct device *dev);
-extern void		fddi_setup(struct device *dev);
-extern void		tr_setup(struct device *dev);
-extern void		tr_freedev(struct device *dev);
-extern int		ether_config(struct device *dev, struct ifmap *map);
+extern void		ether_setup(struct net_device *dev);
+extern void		fddi_setup(struct net_device *dev);
+extern void		tr_setup(struct net_device *dev);
+extern void		tr_freedev(struct net_device *dev);
+extern int		ether_config(struct net_device *dev, struct ifmap *map);
 /* Support for loadable net-drivers */
-extern int		register_netdev(struct device *dev);
-extern void		unregister_netdev(struct device *dev);
-extern int		register_trdev(struct device *dev);
-extern void		unregister_trdev(struct device *dev);
+extern int		register_netdev(struct net_device *dev);
+extern void		unregister_netdev(struct net_device *dev);
+extern int		register_trdev(struct net_device *dev);
+extern void		unregister_trdev(struct net_device *dev);
 /* Functions used for multicast support */
-extern void		dev_mc_upload(struct device *dev);
-extern int 		dev_mc_delete(struct device *dev, void *addr, int alen, int all);
-extern int		dev_mc_add(struct device *dev, void *addr, int alen, int newonly);
-extern void		dev_mc_discard(struct device *dev);
-extern void		dev_set_promiscuity(struct device *dev, int inc);
-extern void		dev_set_allmulti(struct device *dev, int inc);
-extern void		netdev_state_change(struct device *dev);
+extern void		dev_mc_upload(struct net_device *dev);
+extern int 		dev_mc_delete(struct net_device *dev, void *addr, int alen, int all);
+extern int		dev_mc_add(struct net_device *dev, void *addr, int alen, int newonly);
+extern void		dev_mc_discard(struct net_device *dev);
+extern void		dev_set_promiscuity(struct net_device *dev, int inc);
+extern void		dev_set_allmulti(struct net_device *dev, int inc);
+extern void		netdev_state_change(struct net_device *dev);
 /* Load a device via the kmod */
 extern void		dev_load(const char *name);
 extern void		dev_mcast_init(void);
-extern int		netdev_register_fc(struct device *dev, void (*stimul)(struct device *dev));
+extern int		netdev_register_fc(struct net_device *dev, void (*stimul)(struct net_device *dev));
 extern void		netdev_unregister_fc(int bit);
 extern int		netdev_dropping;
 extern int		netdev_max_backlog;
@@ -459,7 +459,7 @@
 #ifdef CONFIG_NET_FASTROUTE
 extern int		netdev_fastroute;
 extern int		netdev_fastroute_obstacles;
-extern void		dev_clear_fastroute(struct device *dev);
+extern void		dev_clear_fastroute(struct net_device *dev);
 extern struct net_fastroute_stats dev_fastroute_stat;
 #endif
 
diff -u --recursive --new-file v2.3.13/linux/include/linux/parport.h linux/include/linux/parport.h
--- v2.3.13/linux/include/linux/parport.h	Mon Aug  9 14:59:23 1999
+++ linux/include/linux/parport.h	Wed Aug 18 16:44:35 1999
@@ -491,7 +491,8 @@
 extern void inc_parport_count(void);
 
 /* If PC hardware is the only type supported, we can optimise a bit.  */
-#if (defined(CONFIG_PARPORT_PC) || defined(CONFIG_PARPORT_PC_MODULE)) && !(defined(CONFIG_PARPORT_AX) || defined(CONFIG_PARPORT_AX_MODULE)) && !(defined(CONFIG_PARPORT_ARC) || defined(CONFIG_PARPORT_ARC_MODULE)) && !(defined(CONFIG_PARPORT_AMIGA) || defined(CONFIG_PARPORT_AMIGA_MODULE)) && !(defined(CONFIG_PARPORT_MFC3) || defined(CONFIG_PARPORT_MFC3_MODULE)) && !(defined(CONFIG_PARPORT_ATARI) || defined(CONFIG_PARPORT_ATARI_MODULE)) && !defined(CONFIG_PARPORT_OTHER) && !(defined(CONFIG_USB_USS720) || defined(CONFIG_USB_USS720_MODULE))
+#if (defined(CONFIG_PARPORT_PC) || defined(CONFIG_PARPORT_PC_MODULE)) && !(defined(CONFIG_PARPORT_AX) || defined(CONFIG_PARPORT_AX_MODULE)) && !(defined(CONFIG_PARPORT_ARC) || defined(CONFIG_PARPORT_ARC_MODULE)) && !(defined(CONFIG_PARPORT_AMIGA) || defined(CONFIG_PARPORT_AMIGA_MODULE)) && !(defined(CONFIG_PARPORT_MFC3) || defined(CONFIG_PARPORT_MFC3_MODULE)) && !(defined(CONFIG_PARPORT_ATARI) || defined(CONFIG_PARPORT_ATARI_MODULE)) && !defined(CONFIG_PARPORT_OTHER) && !(defined(CONFIG_USB_USS720) || defined(CONFIG_USB_USS720_MODULE)) && !defined(CONFIG_PARPORT_OTHER) && !(defined(CONFIG_USB_USS720) || defined(CONFIG_USB_USS720_MODULE))
+
 #undef PARPORT_NEED_GENERIC_OPS
 #include <linux/parport_pc.h>
 #define parport_write_data(p,x)            parport_pc_write_data(p,x)
diff -u --recursive --new-file v2.3.13/linux/include/linux/pci.h linux/include/linux/pci.h
--- v2.3.13/linux/include/linux/pci.h	Mon Aug  9 14:59:23 1999
+++ linux/include/linux/pci.h	Wed Aug 18 16:43:30 1999
@@ -1208,11 +1208,41 @@
 #include <linux/config.h>
 #include <linux/ioport.h>
 
+#define DEVICE_COUNT_COMPATIBLE	4
+#define DEVICE_COUNT_DMA	2
+#define DEVICE_COUNT_RESOURCE	12
+
+#define DEVICE_IRQ_NOTSET	0xffffffff
+#define DEVICE_IRQ_AUTO		0xfffffffe
+#define DEVICE_DMA_NOTSET	0xff
+#define DEVICE_DMA_AUTO		0xfe
+
+#define DEVICE_IRQ_FLAG_HIGHEDGE	(1<<0)
+#define DEVICE_IRQ_FLAG_LOWEDGE		(1<<1)
+#define DEVICE_IRQ_FLAG_HIGHLEVEL	(1<<2)
+#define DEVICE_IRQ_FLAG_LOWLEVEL	(1<<3)
+
+#define DEVICE_DMA_TYPE_8BIT		0
+#define DEVICE_DMA_TYPE_8AND16BIT	1
+#define DEVICE_DMA_TYPE_16BIT		2
+
+#define DEVICE_DMA_FLAG_MASTER		(1<<0)
+#define DEVICE_DMA_FLAG_BYTE		(1<<1)
+#define DEVICE_DMA_FLAG_WORD		(1<<2)
+
+#define DEVICE_DMA_SPEED_COMPATIBLE	0
+#define DEVICE_DMA_SPEED_TYPEA		1
+#define DEVICE_DMA_SPEED_TYPEB		2
+#define DEVICE_DMA_SPEED_TYPEF		3
+
 /*
  * There is one pci_dev structure for each slot-number/function-number
  * combination:
  */
 struct pci_dev {
+	int active;			/* device is active */
+	int ro;				/* Read/Only */
+
 	struct pci_bus	*bus;		/* bus this device is on */
 	struct pci_dev	*sibling;	/* next device on this bus */
 	struct pci_dev	*next;		/* chain of all devices */
@@ -1227,6 +1257,12 @@
 	unsigned int	hdr_type;	/* PCI header type */
 	unsigned int	master : 1;	/* set if device is master capable */
 
+	unsigned short	regs;
+	
+	/* device is compatible with these IDs */
+	unsigned short vendor_compatible[DEVICE_COUNT_COMPATIBLE];
+	unsigned short device_compatible[DEVICE_COUNT_COMPATIBLE];
+
 	char		name[48];
 
 	/*
@@ -1241,12 +1277,23 @@
 	 * cannot generate interrupts at all.
 	 */
 	unsigned int	irq;		/* irq generated by this device */
+	unsigned short	irq_flags;	/* irq type */
+	unsigned int	irq2;
+	unsigned short	irq2_flags;	
+	unsigned char	dma[DEVICE_COUNT_DMA];
+	unsigned char	dma_type[DEVICE_COUNT_DMA];
+	unsigned char	dma_flags[DEVICE_COUNT_DMA];
+	unsigned char	dma_speed[DEVICE_COUNT_DMA];
 
 	/* Base registers for this device, can be adjusted by
 	 * pcibios_fixup() as necessary.
 	 */
-	struct resource resource[6];
+	struct resource resource[DEVICE_COUNT_RESOURCE];
 	unsigned long	rom_address;
+
+	int (*prepare)(struct pci_dev *dev);
+	int (*activate)(struct pci_dev *dev);
+	int (*deactivate)(struct pci_dev *dev);
 };
 
 struct pci_bus {
@@ -1264,6 +1311,15 @@
 	unsigned char	primary;	/* number of primary bridge */
 	unsigned char	secondary;	/* number of secondary bridge */
 	unsigned char	subordinate;	/* max number of subordinate buses */
+
+	char		name[48];
+	unsigned short	vendor;
+	unsigned short	device;
+	unsigned int	serial;		/* serial number */
+	unsigned char	pnpver;		/* Plug & Play version */
+	unsigned char	productver;	/* product version */
+	unsigned char	checksum;	/* if zero - checksum passed */
+	unsigned char	pad1;
 };
 
 extern struct pci_bus	pci_root;	/* root bus */
diff -u --recursive --new-file v2.3.13/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h
--- v2.3.13/linux/include/linux/proc_fs.h	Mon Aug  9 14:59:23 1999
+++ linux/include/linux/proc_fs.h	Wed Aug 18 16:44:06 1999
@@ -194,6 +194,7 @@
 	PROC_SCSI_ESP,
 	PROC_SCSI_QLOGICPTI,
 	PROC_SCSI_AMIGA7XX,
+	PROC_SCSI_MVME147,
 	PROC_SCSI_MVME16x,
 	PROC_SCSI_BVME6000,
 	PROC_SCSI_A3000,
diff -u --recursive --new-file v2.3.13/linux/include/linux/scc.h linux/include/linux/scc.h
--- v2.3.13/linux/include/linux/scc.h	Fri Dec 18 13:57:21 1998
+++ linux/include/linux/scc.h	Wed Aug 18 11:38:46 1999
@@ -221,7 +221,7 @@
 	
 	int init;			/* channel exists? */
 
-	struct device *dev;		/* link to device control structure */
+	struct net_device *dev;		/* link to device control structure */
 	struct net_device_stats dev_stat;/* device statistics */
 
 	char brand;			/* manufacturer of the board */
diff -u --recursive --new-file v2.3.13/linux/include/linux/sched.h linux/include/linux/sched.h
--- v2.3.13/linux/include/linux/sched.h	Mon Aug  9 14:59:23 1999
+++ linux/include/linux/sched.h	Wed Aug 18 16:43:38 1999
@@ -716,6 +716,7 @@
 	add_wait_queue(&wq, &__wait);					\
 	for (;;) {							\
 		current->state = TASK_UNINTERRUPTIBLE;			\
+		mb();							\
 		if (condition)						\
 			break;						\
 		schedule();						\
@@ -739,6 +740,7 @@
 	add_wait_queue(&wq, &__wait);					\
 	for (;;) {							\
 		current->state = TASK_INTERRUPTIBLE;			\
+		mb();							\
 		if (condition)						\
 			break;						\
 		if (!signal_pending(current)) {				\
diff -u --recursive --new-file v2.3.13/linux/include/linux/skbuff.h linux/include/linux/skbuff.h
--- v2.3.13/linux/include/linux/skbuff.h	Tue Jun 22 14:42:05 1999
+++ linux/include/linux/skbuff.h	Wed Aug 18 16:44:22 1999
@@ -48,7 +48,7 @@
 	struct sk_buff_head * list;		/* List we are on				*/
 	struct sock	*sk;			/* Socket we are owned by 			*/
 	struct timeval	stamp;			/* Time we arrived				*/
-	struct device	*dev;			/* Device we arrived on/are leaving by		*/
+	struct net_device	*dev;			/* Device we arrived on/are leaving by		*/
 
 	/* Transport layer header */
 	union
diff -u --recursive --new-file v2.3.13/linux/include/linux/swap.h linux/include/linux/swap.h
--- v2.3.13/linux/include/linux/swap.h	Mon Aug  9 14:59:23 1999
+++ linux/include/linux/swap.h	Wed Aug 18 16:43:30 1999
@@ -85,7 +85,6 @@
 
 /* linux/mm/page_io.c */
 extern void rw_swap_page(int, struct page *, int);
-extern void rw_swap_page_nocache(int, unsigned long, char *);
 extern void rw_swap_page_nolock(int, unsigned long, char *, int);
 extern void swap_after_unlock_page (unsigned long entry);
 
diff -u --recursive --new-file v2.3.13/linux/include/linux/sysctl.h linux/include/linux/sysctl.h
--- v2.3.13/linux/include/linux/sysctl.h	Mon Aug  9 14:59:23 1999
+++ linux/include/linux/sysctl.h	Wed Aug 18 09:45:10 1999
@@ -140,7 +140,8 @@
 	NET_X25=13,
 	NET_TR=14,
 	NET_DECNET=15,
-	NET_ECONET=16
+	NET_ECONET=16,
+	NET_KHTTPD=17
 };
 
 /* /proc/sys/bus/isa */
@@ -407,6 +408,23 @@
 	NET_DECNET_DEBUG_LEVEL = 255
 };
 
+/* /proc/sys/net/khttpd/ */
+enum {
+	NET_KHTTPD_DOCROOT	= 1,
+	NET_KHTTPD_START	= 2,
+	NET_KHTTPD_STOP		= 3,
+	NET_KHTTPD_UNLOAD	= 4,
+	NET_KHTTPD_CLIENTPORT	= 5,
+	NET_KHTTPD_PERMREQ	= 6,
+	NET_KHTTPD_PERMFORBID	= 7,
+	NET_KHTTPD_LOGGING	= 8,
+	NET_KHTTPD_SERVERPORT	= 9,
+	NET_KHTTPD_DYNAMICSTRING= 10,
+	NET_KHTTPD_SLOPPYMIME   = 11,
+	NET_KHTTPD_THREADS	= 12,
+	NET_KHTTPD_MAXCONNECT	= 13
+};
+
 /* /proc/sys/net/decnet/conf/<dev> */
 enum {
 	NET_DECNET_CONF_LOOPBACK = -2,
@@ -520,6 +538,10 @@
 				void *, size_t *);
 extern int proc_dointvec_jiffies(ctl_table *, int, struct file *,
 				 void *, size_t *);
+extern int proc_doulongvec_minmax(ctl_table *, int, struct file *,
+				  void *, size_t *);
+extern int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int,
+				      struct file *, void *, size_t *);
 
 extern int do_sysctl (int *name, int nlen,
 		      void *oldval, size_t *oldlenp,
diff -u --recursive --new-file v2.3.13/linux/include/linux/trdevice.h linux/include/linux/trdevice.h
--- v2.3.13/linux/include/linux/trdevice.h	Fri Jul 10 13:51:41 1998
+++ linux/include/linux/trdevice.h	Wed Aug 18 11:38:46 1999
@@ -28,12 +28,12 @@
 #include <linux/if_tr.h>
 
 #ifdef __KERNEL__
-extern int		tr_header(struct sk_buff *skb, struct device *dev,
+extern int		tr_header(struct sk_buff *skb, struct net_device *dev,
 				   unsigned short type, void *daddr,
 				   void *saddr, unsigned len);
 extern int		tr_rebuild_header(struct sk_buff *skb);
-extern unsigned short	tr_type_trans(struct sk_buff *skb, struct device *dev);
-extern struct device    * init_trdev(struct device *, int);
+extern unsigned short	tr_type_trans(struct sk_buff *skb, struct net_device *dev);
+extern struct net_device    * init_trdev(struct net_device *, int);
 
 #endif
 
diff -u --recursive --new-file v2.3.13/linux/include/linux/wanpipe.h linux/include/linux/wanpipe.h
--- v2.3.13/linux/include/linux/wanpipe.h	Mon Jan 12 14:46:27 1998
+++ linux/include/linux/wanpipe.h	Wed Aug 18 11:38:47 1999
@@ -104,7 +104,7 @@
  */
 typedef struct load_sharing
 {
-        struct device*  dev_ptr;
+        struct net_device*  dev_ptr;
         struct load_sharing* next;
 } load_sharing_t;
 
diff -u --recursive --new-file v2.3.13/linux/include/linux/wanrouter.h linux/include/linux/wanrouter.h
--- v2.3.13/linux/include/linux/wanrouter.h	Tue Jun 22 14:43:49 1999
+++ linux/include/linux/wanrouter.h	Wed Aug 18 16:45:49 1999
@@ -355,12 +355,12 @@
 	int (*update) (struct wan_device* wandev);
 	int (*ioctl) (struct wan_device* wandev, unsigned cmd,
 		unsigned long arg);
-	int (*new_if) (struct wan_device* wandev, struct device* dev,
+	int (*new_if) (struct wan_device* wandev, struct net_device* dev,
 		wanif_conf_t* conf);
-	int (*del_if) (struct wan_device* wandev, struct device* dev);
+	int (*del_if) (struct wan_device* wandev, struct net_device* dev);
 					/****** maintained by the router ****/
 	struct wan_device* next;	/* -> next device */
-	struct device* dev;		/* list of network interfaces */
+	struct net_device* dev;		/* list of network interfaces */
 	unsigned ndev;			/* number of interfaces */
 	struct proc_dir_entry dent;	/* proc filesystem entry */
 } wan_device_t;
@@ -368,8 +368,8 @@
 /* Public functions available for device drivers */
 extern int register_wan_device(wan_device_t* wandev);
 extern int unregister_wan_device(char* name);
-unsigned short wanrouter_type_trans(struct sk_buff* skb, struct device* dev);
-int wanrouter_encapsulate(struct sk_buff* skb, struct device* dev);
+unsigned short wanrouter_type_trans(struct sk_buff* skb, struct net_device* dev);
+int wanrouter_encapsulate(struct sk_buff* skb, struct net_device* dev);
 
 /* Proc interface functions. These must not be called by the drivers! */
 extern int wanrouter_proc_init (void);
diff -u --recursive --new-file v2.3.13/linux/include/net/addrconf.h linux/include/net/addrconf.h
--- v2.3.13/linux/include/net/addrconf.h	Wed Jun  9 14:45:36 1999
+++ linux/include/net/addrconf.h	Wed Aug 18 11:38:47 1999
@@ -52,11 +52,11 @@
 extern int			addrconf_set_dstaddr(void *arg);
 
 extern struct inet6_ifaddr *	ipv6_chk_addr(struct in6_addr *addr,
-					      struct device *dev, int nd);
+					      struct net_device *dev, int nd);
 extern int			ipv6_get_saddr(struct dst_entry *dst, 
 					       struct in6_addr *daddr,
 					       struct in6_addr *saddr);
-extern int			ipv6_get_lladdr(struct device *dev, struct in6_addr *);
+extern int			ipv6_get_lladdr(struct net_device *dev, struct in6_addr *);
 
 /*
  *	multicast prototypes (mcast.c)
@@ -70,22 +70,22 @@
 extern void			ipv6_sock_mc_close(struct sock *sk);
 extern int			inet6_mc_check(struct sock *sk, struct in6_addr *addr);
 
-extern int			ipv6_dev_mc_inc(struct device *dev,
+extern int			ipv6_dev_mc_inc(struct net_device *dev,
 						struct in6_addr *addr);
-extern int			ipv6_dev_mc_dec(struct device *dev,
+extern int			ipv6_dev_mc_dec(struct net_device *dev,
 						struct in6_addr *addr);
 extern void			ipv6_mc_up(struct inet6_dev *idev);
 extern void			ipv6_mc_down(struct inet6_dev *idev);
 extern void			ipv6_mc_destroy_dev(struct inet6_dev *idev);
 extern void			addrconf_dad_failure(struct inet6_ifaddr *ifp);
 
-extern int			ipv6_chk_mcast_addr(struct device *dev,
+extern int			ipv6_chk_mcast_addr(struct net_device *dev,
 						    struct in6_addr *addr);
 
-extern void			addrconf_prefix_rcv(struct device *dev,
+extern void			addrconf_prefix_rcv(struct net_device *dev,
 						    u8 *opt, int len);
 
-extern struct inet6_dev *	ipv6_get_idev(struct device *dev);
+extern struct inet6_dev *	ipv6_get_idev(struct net_device *dev);
 
 extern void			addrconf_forwarding_on(void);
 /*
diff -u --recursive --new-file v2.3.13/linux/include/net/arp.h linux/include/net/arp.h
--- v2.3.13/linux/include/net/arp.h	Tue Jun 22 14:42:42 1999
+++ linux/include/net/arp.h	Wed Aug 18 16:44:34 1999
@@ -8,16 +8,16 @@
 extern struct neigh_table arp_tbl;
 
 extern void	arp_init(void);
-extern int	arp_rcv(struct sk_buff *skb, struct device *dev,
+extern int	arp_rcv(struct sk_buff *skb, struct net_device *dev,
 			struct packet_type *pt);
 extern int	arp_find(unsigned char *haddr, struct sk_buff *skb);
 extern int	arp_ioctl(unsigned int cmd, void *arg);
 extern void     arp_send(int type, int ptype, u32 dest_ip, 
-			 struct device *dev, u32 src_ip, 
+			 struct net_device *dev, u32 src_ip, 
 			 unsigned char *dest_hw, unsigned char *src_hw, unsigned char *th);
 extern int	arp_bind_neighbour(struct dst_entry *dst);
-extern int	arp_mc_map(u32 addr, u8 *haddr, struct device *dev, int dir);
-extern void	arp_ifdown(struct device *dev);
+extern int	arp_mc_map(u32 addr, u8 *haddr, struct net_device *dev, int dir);
+extern void	arp_ifdown(struct net_device *dev);
 
 extern struct neigh_ops arp_broken_ops;
 
diff -u --recursive --new-file v2.3.13/linux/include/net/ax25.h linux/include/net/ax25.h
--- v2.3.13/linux/include/net/ax25.h	Tue Jun 22 14:42:40 1999
+++ linux/include/net/ax25.h	Wed Aug 18 16:44:31 1999
@@ -148,7 +148,7 @@
 typedef struct ax25_route {
 	struct ax25_route	*next;
 	ax25_address		callsign;
-	struct device		*dev;
+	struct net_device		*dev;
 	ax25_digi		*digipeat;
 	char			ip_mode;
 } ax25_route;
@@ -165,8 +165,8 @@
 
 typedef struct ax25_dev {
 	struct ax25_dev		*next;
-	struct device		*dev;
-	struct device		*forward;
+	struct net_device		*dev;
+	struct net_device		*forward;
 	struct ctl_table	systable[AX25_MAX_VALUES+1];
 	int			values[AX25_MAX_VALUES];
 #if defined(CONFIG_AX25_DAMA_SLAVE) || defined(CONFIG_AX25_DAMA_MASTER)
@@ -200,9 +200,9 @@
 extern ax25_cb *volatile ax25_list;
 extern void ax25_free_cb(ax25_cb *);
 extern void ax25_insert_socket(ax25_cb *);
-struct sock *ax25_find_listener(ax25_address *, int, struct device *, int);
+struct sock *ax25_find_listener(ax25_address *, int, struct net_device *, int);
 struct sock *ax25_find_socket(ax25_address *, ax25_address *, int);
-extern ax25_cb *ax25_find_cb(ax25_address *, ax25_address *, ax25_digi *, struct device *);
+extern ax25_cb *ax25_find_cb(ax25_address *, ax25_address *, ax25_digi *, struct net_device *);
 extern struct sock *ax25_addr_match(ax25_address *);
 extern void ax25_send_to_raw(struct sock *, struct sk_buff *, int);
 extern void ax25_destroy_socket(ax25_cb *);
@@ -224,12 +224,12 @@
 
 /* ax25_dev.c */
 extern ax25_dev *ax25_dev_list;
-extern ax25_dev *ax25_dev_ax25dev(struct device *);
+extern ax25_dev *ax25_dev_ax25dev(struct net_device *);
 extern ax25_dev *ax25_addr_ax25dev(ax25_address *);
-extern void ax25_dev_device_up(struct device *);
-extern void ax25_dev_device_down(struct device *);
+extern void ax25_dev_device_up(struct net_device *);
+extern void ax25_dev_device_down(struct net_device *);
 extern int  ax25_fwd_ioctl(unsigned int, struct ax25_fwd_struct *);
-extern struct device *ax25_fwd_dev(struct device *);
+extern struct net_device *ax25_fwd_dev(struct net_device *);
 extern void ax25_dev_free(void);
 
 /* ax25_ds_in.c */
@@ -260,23 +260,23 @@
 extern void ax25_protocol_release(unsigned int);
 extern int  ax25_linkfail_register(void (*)(ax25_cb *, int));
 extern void ax25_linkfail_release(void (*)(ax25_cb *, int));
-extern int  ax25_listen_register(ax25_address *, struct device *);
-extern void ax25_listen_release(ax25_address *, struct device *);
+extern int  ax25_listen_register(ax25_address *, struct net_device *);
+extern void ax25_listen_release(ax25_address *, struct net_device *);
 extern int  (*ax25_protocol_function(unsigned int))(struct sk_buff *, ax25_cb *);
-extern int  ax25_listen_mine(ax25_address *, struct device *);
+extern int  ax25_listen_mine(ax25_address *, struct net_device *);
 extern void ax25_link_failed(ax25_cb *, int);
 extern int  ax25_protocol_is_registered(unsigned int);
 
 /* ax25_in.c */
 extern int  ax25_rx_iframe(ax25_cb *, struct sk_buff *);
-extern int  ax25_kiss_rcv(struct sk_buff *, struct device *, struct packet_type *);
+extern int  ax25_kiss_rcv(struct sk_buff *, struct net_device *, struct packet_type *);
 
 /* ax25_ip.c */
-extern int  ax25_encapsulate(struct sk_buff *, struct device *, unsigned short, void *, void *, unsigned int);
+extern int  ax25_encapsulate(struct sk_buff *, struct net_device *, unsigned short, void *, void *, unsigned int);
 extern int  ax25_rebuild_header(struct sk_buff *);
 
 /* ax25_out.c */
-extern ax25_cb *ax25_send_frame(struct sk_buff *, int, ax25_address *, ax25_address *, ax25_digi *, struct device *);
+extern ax25_cb *ax25_send_frame(struct sk_buff *, int, ax25_address *, ax25_address *, ax25_digi *, struct net_device *);
 extern void ax25_output(ax25_cb *, int, struct sk_buff *);
 extern void ax25_kick(ax25_cb *);
 extern void ax25_transmit_buffer(ax25_cb *, struct sk_buff *, int);
@@ -284,11 +284,11 @@
 extern int  ax25_check_iframes_acked(ax25_cb *, unsigned short);
 
 /* ax25_route.c */
-extern void ax25_rt_device_down(struct device *);
+extern void ax25_rt_device_down(struct net_device *);
 extern int  ax25_rt_ioctl(unsigned int, void *);
 extern int  ax25_rt_get_info(char *, char **, off_t, int, int);
 extern int  ax25_rt_autobind(ax25_cb *, ax25_address *);
-extern ax25_route *ax25_rt_find_route(ax25_address *, struct device *);
+extern ax25_route *ax25_rt_find_route(ax25_address *, struct net_device *);
 extern struct sk_buff *ax25_rt_build_path(struct sk_buff *, ax25_address *, ax25_address *, ax25_digi *);
 extern void ax25_rt_free(void);
 
@@ -316,7 +316,7 @@
 extern int  ax25_validate_nr(ax25_cb *, unsigned short);
 extern int  ax25_decode(ax25_cb *, struct sk_buff *, int *, int *, int *);
 extern void ax25_send_control(ax25_cb *, int, int, int);
-extern void ax25_return_dm(struct device *, ax25_address *, ax25_address *, ax25_digi *);
+extern void ax25_return_dm(struct net_device *, ax25_address *, ax25_address *, ax25_digi *);
 extern void ax25_calculate_t1(ax25_cb *);
 extern void ax25_calculate_rtt(ax25_cb *);
 extern void ax25_disconnect(ax25_cb *, int);
diff -u --recursive --new-file v2.3.13/linux/include/net/br.h linux/include/net/br.h
--- v2.3.13/linux/include/net/br.h	Sun Mar  7 15:25:23 1999
+++ linux/include/net/br.h	Wed Aug 18 11:38:47 1999
@@ -160,7 +160,7 @@
 	unsigned short   designated_port;	  /* (4.5.5.7)	 */
 	unsigned int     top_change_ack;	  /* (4.5.5.8)	 */
 	unsigned int     config_pending;	  /* (4.5.5.9)	 */
-	struct device *dev;	
+	struct net_device *dev;	
 	struct fdb *fdb;	/* head of per port fdb chain */
 } Port_data;
 
diff -u --recursive --new-file v2.3.13/linux/include/net/datalink.h linux/include/net/datalink.h
--- v2.3.13/linux/include/net/datalink.h	Tue Oct 24 06:26:07 1995
+++ linux/include/net/datalink.h	Wed Aug 18 11:38:47 1999
@@ -6,7 +6,7 @@
 	unsigned char	type[8];
 	const char	*string_name;
 	unsigned short	header_length;
-	int	(*rcvfunc)(struct sk_buff *, struct device *, 
+	int	(*rcvfunc)(struct sk_buff *, struct net_device *, 
 				struct packet_type *);
 	void	(*datalink_header)(struct datalink_proto *, struct sk_buff *,
 					unsigned char *);
diff -u --recursive --new-file v2.3.13/linux/include/net/dn_dev.h linux/include/net/dn_dev.h
--- v2.3.13/linux/include/net/dn_dev.h	Wed May 26 09:36:35 1999
+++ linux/include/net/dn_dev.h	Wed Aug 18 11:38:48 1999
@@ -79,10 +79,10 @@
 	int priority;             /* Priority to be a router        */
 	char *name;               /* Name for sysctl                */
 	int ctl_name;             /* Index for sysctl               */
-	int  (*up)(struct device *);
-	void (*down)(struct device *);
-	void (*timer1)(struct device *);
-	void (*timer3)(struct device *);
+	int  (*up)(struct net_device *);
+	void (*down)(struct net_device *);
+	void (*timer1)(struct net_device *);
+	void (*timer3)(struct net_device *);
 	int (*setsrc)(struct sk_buff *skb);
 	int (*neigh_setup)(struct neighbour *);
 	void *sysctl;
@@ -91,7 +91,7 @@
 
 struct dn_dev {
 	struct dn_ifaddr *ifa_list;
-	struct device *dev;
+	struct net_device *dev;
 	struct dn_dev_parms parms;
 	char use_long;
         struct timer_list timer;
@@ -169,12 +169,12 @@
 extern void dn_dev_veri_pkt(struct sk_buff *skb);
 extern void dn_dev_hello(struct sk_buff *skb);
 
-extern void dn_dev_up(struct device *);
-extern void dn_dev_down(struct device *);
+extern void dn_dev_up(struct net_device *);
+extern void dn_dev_down(struct net_device *);
 
-extern struct device *decnet_default_device;
+extern struct net_device *decnet_default_device;
 
-static __inline__ int dn_dev_islocal(struct device *dev, dn_address addr)
+static __inline__ int dn_dev_islocal(struct net_device *dev, dn_address addr)
 {
 	struct dn_dev *dn_db = dev->dn_ptr;
 	struct dn_ifaddr *ifa;
diff -u --recursive --new-file v2.3.13/linux/include/net/dn_neigh.h linux/include/net/dn_neigh.h
--- v2.3.13/linux/include/net/dn_neigh.h	Wed May 26 09:36:35 1999
+++ linux/include/net/dn_neigh.h	Wed Aug 18 11:38:48 1999
@@ -22,7 +22,7 @@
 extern void dn_neigh_router_hello(struct sk_buff *skb);
 extern void dn_neigh_endnode_hello(struct sk_buff *skb);
 extern void dn_neigh_pointopoint_hello(struct sk_buff *skb);
-extern int dn_neigh_elist(struct device *dev, unsigned char *ptr, int n);
+extern int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n);
 
 extern struct neigh_table dn_neigh_table;
 
diff -u --recursive --new-file v2.3.13/linux/include/net/dst.h linux/include/net/dst.h
--- v2.3.13/linux/include/net/dst.h	Tue Jun 22 14:42:38 1999
+++ linux/include/net/dst.h	Wed Aug 18 16:44:34 1999
@@ -29,7 +29,7 @@
 	struct dst_entry        *next;
 	atomic_t		refcnt;		/* tree/hash references	*/
 	atomic_t		use;		/* client references	*/
-	struct device	        *dev;
+	struct net_device	        *dev;
 	int			obsolete;
 	unsigned long		lastuse;
 	unsigned long		expires;
diff -u --recursive --new-file v2.3.13/linux/include/net/if_inet6.h linux/include/net/if_inet6.h
--- v2.3.13/linux/include/net/if_inet6.h	Wed Jun  9 14:45:36 1999
+++ linux/include/net/if_inet6.h	Wed Aug 18 11:38:47 1999
@@ -74,7 +74,7 @@
 struct ifmcaddr6
 {
 	struct in6_addr		mca_addr;
-	struct device		*dev;
+	struct net_device		*dev;
 	struct ifmcaddr6	*next;
 	struct ifmcaddr6	*if_next;
 	struct timer_list	mca_timer;
@@ -105,7 +105,7 @@
 
 struct inet6_dev 
 {
-	struct device		*dev;
+	struct net_device		*dev;
 
 	struct inet6_ifaddr	*addr_list;
 	struct ifmcaddr6	*mc_list;
diff -u --recursive --new-file v2.3.13/linux/include/net/ip.h linux/include/net/ip.h
--- v2.3.13/linux/include/net/ip.h	Tue Jun 22 14:42:42 1999
+++ linux/include/net/ip.h	Wed Aug 18 16:44:36 1999
@@ -76,7 +76,7 @@
 #define IP_FRAG_TIME	(30 * HZ)		/* fragment lifetime	*/
 
 extern void		ip_mc_dropsocket(struct sock *);
-extern void		ip_mc_dropdevice(struct device *dev);
+extern void		ip_mc_dropdevice(struct net_device *dev);
 extern int		ip_mc_procinfo(char *, char **, off_t, int, int);
 
 /*
@@ -86,7 +86,7 @@
 extern void		ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,
 					      u32 saddr, u32 daddr,
 					      struct ip_options *opt);
-extern int		ip_rcv(struct sk_buff *skb, struct device *dev,
+extern int		ip_rcv(struct sk_buff *skb, struct net_device *dev,
 			       struct packet_type *pt);
 extern int		ip_local_deliver(struct sk_buff *skb);
 extern int		ip_mr_input(struct sk_buff *skb);
@@ -139,7 +139,7 @@
 extern __inline__ int ip_finish_output(struct sk_buff *skb)
 {
 	struct dst_entry *dst = skb->dst;
-	struct device *dev = dst->dev;
+	struct net_device *dev = dst->dev;
 	struct hh_cache *hh = dst->hh;
 
 	skb->dev = dev;
diff -u --recursive --new-file v2.3.13/linux/include/net/ip6_route.h linux/include/net/ip6_route.h
--- v2.3.13/linux/include/net/ip6_route.h	Thu Aug 27 19:33:08 1998
+++ linux/include/net/ip6_route.h	Wed Aug 18 11:38:47 1999
@@ -40,15 +40,15 @@
 extern int			ip6_del_rt(struct rt6_info *);
 
 extern int			ip6_rt_addr_add(struct in6_addr *addr,
-						struct device *dev);
+						struct net_device *dev);
 
 extern int			ip6_rt_addr_del(struct in6_addr *addr,
-						struct device *dev);
+						struct net_device *dev);
 
 extern void			rt6_sndmsg(int type, struct in6_addr *dst,
 					   struct in6_addr *src,
 					   struct in6_addr *gw,
-					   struct device *dev, 
+					   struct net_device *dev, 
 					   int dstlen, int srclen,
 					   int metric, __u32 flags);
 
@@ -61,9 +61,9 @@
  *
  */
 extern struct rt6_info *	rt6_get_dflt_router(struct in6_addr *addr,
-						    struct device *dev);
+						    struct net_device *dev);
 extern struct rt6_info *	rt6_add_dflt_router(struct in6_addr *gwaddr,
-						    struct device *dev);
+						    struct net_device *dev);
 
 extern void			rt6_purge_dflt_routers(int lst_resort);
 
@@ -74,7 +74,7 @@
 
 extern void			rt6_pmtu_discovery(struct in6_addr *daddr,
 						   struct in6_addr *saddr,
-						   struct device *dev,
+						   struct net_device *dev,
 						   u32 pmtu);
 
 struct nlmsghdr;
@@ -84,8 +84,8 @@
 extern int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg);
 extern int inet6_rtm_getroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg);
 
-extern void rt6_ifdown(struct device *dev);
-extern void rt6_mtu_change(struct device *dev, unsigned mtu);
+extern void rt6_ifdown(struct net_device *dev);
+extern void rt6_mtu_change(struct net_device *dev, unsigned mtu);
 
 /*
  *	Store a destination cache entry in a socket
diff -u --recursive --new-file v2.3.13/linux/include/net/ip_fib.h linux/include/net/ip_fib.h
--- v2.3.13/linux/include/net/ip_fib.h	Sun Mar 21 07:22:00 1999
+++ linux/include/net/ip_fib.h	Wed Aug 18 11:38:47 1999
@@ -36,7 +36,7 @@
 
 struct fib_nh
 {
-	struct device		*nh_dev;
+	struct net_device		*nh_dev;
 	unsigned		nh_flags;
 	unsigned char		nh_scope;
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
@@ -200,11 +200,11 @@
 extern int inet_rtm_getroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg);
 extern int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb);
 extern int fib_validate_source(u32 src, u32 dst, u8 tos, int oif,
-			       struct device *dev, u32 *spec_dst, u32 *itag);
+			       struct net_device *dev, u32 *spec_dst, u32 *itag);
 extern void fib_select_multipath(const struct rt_key *key, struct fib_result *res);
 
 /* Exported by fib_semantics.c */
-extern int 		ip_fib_check_default(u32 gw, struct device *dev);
+extern int 		ip_fib_check_default(u32 gw, struct net_device *dev);
 extern void		fib_release_info(struct fib_info *);
 extern int		fib_semantic_match(int type, struct fib_info *,
 					   const struct rt_key *, struct fib_result*);
@@ -214,8 +214,8 @@
 extern int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
 			 u8 tb_id, u8 type, u8 scope, void *dst, int dst_len, u8 tos,
 			 struct fib_info *fi);
-extern int fib_sync_down(u32 local, struct device *dev, int force);
-extern int fib_sync_up(struct device *dev);
+extern int fib_sync_down(u32 local, struct net_device *dev, int force);
+extern int fib_sync_up(struct net_device *dev);
 extern int fib_convert_rtentry(int cmd, struct nlmsghdr *nl, struct rtmsg *rtm,
 			       struct kern_rta *rta, struct rtentry *r);
 extern void fib_node_get_info(int type, int dead, struct fib_info *fi, u32 prefix, u32 mask, char *buffer);
diff -u --recursive --new-file v2.3.13/linux/include/net/ip_masq.h linux/include/net/ip_masq.h
--- v2.3.13/linux/include/net/ip_masq.h	Tue Jun 22 14:42:50 1999
+++ linux/include/net/ip_masq.h	Wed Aug 18 16:44:42 1999
@@ -149,7 +149,7 @@
 extern struct ip_masq *ip_masq_s_tab[IP_MASQ_TAB_SIZE];
 extern const char * ip_masq_state_name(int state);
 extern struct ip_masq_hook *ip_masq_user_hook;
-extern u32 ip_masq_select_addr(struct device *dev, u32 dst, int scope);
+extern u32 ip_masq_select_addr(struct net_device *dev, u32 dst, int scope);
 /*
  * 	
  *	IP_MASQ_APP: IP application masquerading definitions 
diff -u --recursive --new-file v2.3.13/linux/include/net/ipip.h linux/include/net/ipip.h
--- v2.3.13/linux/include/net/ipip.h	Sun Nov 30 14:00:39 1997
+++ linux/include/net/ipip.h	Wed Aug 18 11:38:47 1999
@@ -9,7 +9,7 @@
 struct ip_tunnel
 {
 	struct ip_tunnel	*next;
-	struct device		*dev;
+	struct net_device		*dev;
 	struct net_device_stats	stat;
 
 	int			recursion;	/* Depth of hard_start_xmit recursion */
diff -u --recursive --new-file v2.3.13/linux/include/net/ipv6.h linux/include/net/ipv6.h
--- v2.3.13/linux/include/net/ipv6.h	Tue Jun 22 14:43:46 1999
+++ linux/include/net/ipv6.h	Wed Aug 18 16:44:36 1999
@@ -232,7 +232,7 @@
  */
 
 extern int			ipv6_rcv(struct sk_buff *skb, 
-					 struct device *dev, 
+					 struct net_device *dev, 
 					 struct packet_type *pt);
 
 /*
@@ -245,7 +245,7 @@
 
 extern int			ip6_nd_hdr(struct sock *sk,
 					   struct sk_buff *skb,
-					   struct device *dev,
+					   struct net_device *dev,
 					   struct in6_addr *saddr,
 					   struct in6_addr *daddr,
 					   int proto, int len);
diff -u --recursive --new-file v2.3.13/linux/include/net/ipx.h linux/include/net/ipx.h
--- v2.3.13/linux/include/net/ipx.h	Tue Jun 22 14:42:40 1999
+++ linux/include/net/ipx.h	Wed Aug 18 16:44:31 1999
@@ -49,7 +49,7 @@
 	unsigned char	if_node[IPX_NODE_LEN];
 
 	/* physical device info */
-	struct device	*if_dev;
+	struct net_device	*if_dev;
 	struct datalink_proto	*if_dlink;
 	unsigned short	if_dlink_type;
 
diff -u --recursive --new-file v2.3.13/linux/include/net/irda/irda_device.h linux/include/net/irda/irda_device.h
--- v2.3.13/linux/include/net/irda/irda_device.h	Mon Jun  7 16:18:58 1999
+++ linux/include/net/irda/irda_device.h	Wed Aug 18 11:38:47 1999
@@ -109,7 +109,7 @@
 	char description[32];  /* Something like "irda0 <-> ttyS0" */
 
 	struct irlap_cb *irlap; /* The link layer we are connected to  */
-	struct device netdev;   /* Yes! we are some kind of netdevice */
+	struct net_device netdev;   /* Yes! we are some kind of netdevice */
 	struct enet_statistics stats;
 
  	int flags;            /* Interface flags (see defs above) */
@@ -160,7 +160,7 @@
 void irda_device_unregister_dongle(struct dongle *dongle);
 int irda_device_register_dongle(struct dongle *dongle);
 
-int irda_device_setup(struct device *dev);
+int irda_device_setup(struct net_device *dev);
 
 void setup_dma(int channel, char *buffer, int count, int mode);
 
diff -u --recursive --new-file v2.3.13/linux/include/net/irda/irlan_common.h linux/include/net/irda/irlan_common.h
--- v2.3.13/linux/include/net/irda/irlan_common.h	Mon Jun  7 16:18:58 1999
+++ linux/include/net/irda/irlan_common.h	Wed Aug 18 11:38:47 1999
@@ -163,7 +163,7 @@
 
 	int    magic;
 	char   ifname[9];
-	struct device dev;        /* Ethernet device structure*/
+	struct net_device dev;        /* Ethernet device structure*/
 	struct enet_statistics stats;
 
 	__u32 saddr;              /* Source device address */
diff -u --recursive --new-file v2.3.13/linux/include/net/irda/irlan_eth.h linux/include/net/irda/irlan_eth.h
--- v2.3.13/linux/include/net/irda/irlan_eth.h	Mon Jun  7 16:18:58 1999
+++ linux/include/net/irda/irlan_eth.h	Wed Aug 18 11:38:47 1999
@@ -25,16 +25,16 @@
 #ifndef IRLAN_ETH_H
 #define IRLAN_ETH_H
 
-int  irlan_eth_init(struct device *dev);
-int  irlan_eth_open(struct device *dev);
-int  irlan_eth_close(struct device *dev);
+int  irlan_eth_init(struct net_device *dev);
+int  irlan_eth_open(struct net_device *dev);
+int  irlan_eth_close(struct net_device *dev);
 int  irlan_eth_receive(void *instance, void *sap, struct sk_buff *skb);
-int  irlan_eth_xmit(struct sk_buff *skb, struct device *dev);
+int  irlan_eth_xmit(struct sk_buff *skb, struct net_device *dev);
 
 void irlan_eth_flow_indication( void *instance, void *sap, LOCAL_FLOW flow);
-void irlan_eth_send_gratuitous_arp(struct device *dev);
+void irlan_eth_send_gratuitous_arp(struct net_device *dev);
 
-void irlan_eth_set_multicast_list( struct device *dev);
-struct enet_statistics *irlan_eth_get_stats(struct device *dev);
+void irlan_eth_set_multicast_list( struct net_device *dev);
+struct enet_statistics *irlan_eth_get_stats(struct net_device *dev);
 
 #endif
diff -u --recursive --new-file v2.3.13/linux/include/net/irda/irlap.h linux/include/net/irda/irlap.h
--- v2.3.13/linux/include/net/irda/irlap.h	Sun May 30 10:27:04 1999
+++ linux/include/net/irda/irlap.h	Wed Aug 18 11:38:47 1999
@@ -90,7 +90,7 @@
 	int magic;
 
 	struct irda_device *irdev;
-	struct device      *netdev;
+	struct net_device      *netdev;
 
 	/* Connection state */
 	volatile IRLAP_STATE state;       /* Current state */
diff -u --recursive --new-file v2.3.13/linux/include/net/irda/irlpt_cli.h linux/include/net/irda/irlpt_cli.h
--- v2.3.13/linux/include/net/irda/irlpt_cli.h	Sat Apr 24 17:50:06 1999
+++ linux/include/net/irda/irlpt_cli.h	Wed Aug 18 11:38:47 1999
@@ -28,7 +28,7 @@
 
 /* Debug function */
 
-/* int  client_init( struct device *dev); */
+/* int  client_init( struct net_device *dev); */
 
 /*
  * if it's static, it doesn't go in here.
diff -u --recursive --new-file v2.3.13/linux/include/net/irda/irlpt_server.h linux/include/net/irda/irlpt_server.h
--- v2.3.13/linux/include/net/irda/irlpt_server.h	Sun Mar  7 15:26:43 1999
+++ linux/include/net/irda/irlpt_server.h	Wed Aug 18 11:38:48 1999
@@ -35,7 +35,7 @@
 #include <linux/netdevice.h>
 #include <linux/miscdevice.h>
 
-/* int  server_init( struct device *dev); */
+/* int  server_init( struct net_device *dev); */
 
 extern struct irlpt_cb *irlpt_server;
 
diff -u --recursive --new-file v2.3.13/linux/include/net/irda/irport.h linux/include/net/irda/irport.h
--- v2.3.13/linux/include/net/irda/irport.h	Mon Jun  7 16:18:58 1999
+++ linux/include/net/irda/irport.h	Wed Aug 18 11:38:48 1999
@@ -56,7 +56,7 @@
 void irport_change_speed(struct irda_device *idev, int speed);
 void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 
-int  irport_hard_xmit(struct sk_buff *skb, struct device *dev);
+int  irport_hard_xmit(struct sk_buff *skb, struct net_device *dev);
 void irport_wait_until_sent(struct irda_device *idev);
 
 #endif
diff -u --recursive --new-file v2.3.13/linux/include/net/llc.h linux/include/net/llc.h
--- v2.3.13/linux/include/net/llc.h	Wed Dec 10 09:45:16 1997
+++ linux/include/net/llc.h	Wed Aug 18 11:38:47 1999
@@ -70,7 +70,7 @@
 	unsigned char local_sap;
 	unsigned char remote_sap ;
 	char remote_mac[MAX_ADDR_LEN];  /* MAC address of remote session partner */ 
-	struct device *dev;		/* Device we are attached to */
+	struct net_device *dev;		/* Device we are attached to */
 		     
 	unsigned char llc_mode;		/* See doc 7.1 on p70 */
 #define MODE_ADM 1
diff -u --recursive --new-file v2.3.13/linux/include/net/ndisc.h linux/include/net/ndisc.h
--- v2.3.13/linux/include/net/ndisc.h	Tue Jun 22 14:43:18 1999
+++ linux/include/net/ndisc.h	Wed Aug 18 16:44:34 1999
@@ -62,13 +62,13 @@
 
 extern int			ndisc_rcv(struct sk_buff *skb, unsigned long len);
 
-extern void			ndisc_send_ns(struct device *dev,
+extern void			ndisc_send_ns(struct net_device *dev,
 					      struct neighbour *neigh,
 					      struct in6_addr *solicit,
 					      struct in6_addr *daddr,
 					      struct in6_addr *saddr);
 
-extern void			ndisc_send_rs(struct device *dev,
+extern void			ndisc_send_rs(struct net_device *dev,
 					      struct in6_addr *saddr,
 					      struct in6_addr *daddr);
 
@@ -79,7 +79,7 @@
 						    struct neighbour *neigh,
 						    struct in6_addr *target);
 
-extern int			ndisc_mc_map(struct in6_addr *addr, char *buf, struct device *dev, int dir);
+extern int			ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int dir);
 
 
 struct rt6_info *		dflt_rt_lookup(void);
@@ -101,7 +101,7 @@
 
 extern void			igmp6_cleanup(void);
 
-extern __inline__ struct neighbour * ndisc_get_neigh(struct device *dev, struct in6_addr *addr)
+extern __inline__ struct neighbour * ndisc_get_neigh(struct net_device *dev, struct in6_addr *addr)
 {
 
 	if (dev) {
diff -u --recursive --new-file v2.3.13/linux/include/net/neighbour.h linux/include/net/neighbour.h
--- v2.3.13/linux/include/net/neighbour.h	Tue Jun 22 14:42:35 1999
+++ linux/include/net/neighbour.h	Wed Aug 18 16:44:28 1999
@@ -89,7 +89,7 @@
 	struct neighbour	*next;
 	struct neigh_table	*tbl;
 	struct neigh_parms	*parms;
-	struct device		*dev;
+	struct net_device		*dev;
 	unsigned long		used;
 	unsigned long		confirmed;
 	unsigned long		updated;
@@ -123,7 +123,7 @@
 struct pneigh_entry
 {
 	struct pneigh_entry	*next;
-	struct device		*dev;
+	struct net_device		*dev;
 	u8			key[0];
 };
 
@@ -168,29 +168,29 @@
 extern int			neigh_table_clear(struct neigh_table *tbl);
 extern struct neighbour *	neigh_lookup(struct neigh_table *tbl,
 					     const void *pkey,
-					     struct device *dev);
+					     struct net_device *dev);
 extern struct neighbour *	neigh_create(struct neigh_table *tbl,
 					     const void *pkey,
-					     struct device *dev);
+					     struct net_device *dev);
 extern void			neigh_destroy(struct neighbour *neigh);
 extern int			__neigh_event_send(struct neighbour *neigh, struct sk_buff *skb);
 extern int			neigh_update(struct neighbour *neigh, u8 *lladdr, u8 new, int override, int arp);
-extern int			neigh_ifdown(struct neigh_table *tbl, struct device *dev);
+extern int			neigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
 extern int			neigh_resolve_output(struct sk_buff *skb);
 extern int			neigh_connected_output(struct sk_buff *skb);
 extern int			neigh_compat_output(struct sk_buff *skb);
 extern struct neighbour 	*neigh_event_ns(struct neigh_table *tbl,
 						u8 *lladdr, void *saddr,
-						struct device *dev);
+						struct net_device *dev);
 
-extern struct neigh_parms	*neigh_parms_alloc(struct device *dev, struct neigh_table *tbl);
+extern struct neigh_parms	*neigh_parms_alloc(struct net_device *dev, struct neigh_table *tbl);
 extern void			neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms);
 extern unsigned long		neigh_rand_reach_time(unsigned long base);
 
 extern void			pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
 					       struct sk_buff *skb);
-extern struct pneigh_entry	*pneigh_lookup(struct neigh_table *tbl, const void *key, struct device *dev, int creat);
-extern int			pneigh_delete(struct neigh_table *tbl, const void *key, struct device *dev);
+extern struct pneigh_entry	*pneigh_lookup(struct neigh_table *tbl, const void *key, struct net_device *dev, int creat);
+extern int			pneigh_delete(struct neigh_table *tbl, const void *key, struct net_device *dev);
 
 struct netlink_callback;
 struct nlmsghdr;
@@ -199,7 +199,7 @@
 extern int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
 extern void neigh_app_ns(struct neighbour *n);
 
-extern int			neigh_sysctl_register(struct device *dev, struct neigh_parms *p,
+extern int			neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
 						      int p_id, int pdev_id, char *p_name);
 extern void			neigh_sysctl_unregister(struct neigh_parms *p);
 
@@ -249,7 +249,7 @@
 }
 
 extern __inline__ struct neighbour *
-__neigh_lookup(struct neigh_table *tbl, const void *pkey, struct device *dev, int creat)
+__neigh_lookup(struct neigh_table *tbl, const void *pkey, struct net_device *dev, int creat)
 {
 	struct neighbour *n = neigh_lookup(tbl, pkey, dev);
 
diff -u --recursive --new-file v2.3.13/linux/include/net/netrom.h linux/include/net/netrom.h
--- v2.3.13/linux/include/net/netrom.h	Sat Apr 11 17:18:15 1998
+++ linux/include/net/netrom.h	Wed Aug 18 11:38:47 1999
@@ -56,7 +56,7 @@
 
 typedef struct {
 	ax25_address		user_addr, source_addr, dest_addr;
-	struct device		*device;
+	struct net_device		*device;
 	unsigned char		my_index,   my_id;
 	unsigned char		your_index, your_id;
 	unsigned char		state, condition, bpqext, window;
@@ -79,7 +79,7 @@
 	ax25_address    callsign;
 	ax25_digi       *digipeat;
 	ax25_cb		*ax25;
-	struct device   *dev;
+	struct net_device   *dev;
 	unsigned char   quality;
 	unsigned char   locked;
 	unsigned short  count;
@@ -114,12 +114,12 @@
 extern int  sysctl_netrom_transport_no_activity_timeout;
 extern int  sysctl_netrom_routing_control;
 extern int  sysctl_netrom_link_fails_count;
-extern int  nr_rx_frame(struct sk_buff *, struct device *);
+extern int  nr_rx_frame(struct sk_buff *, struct net_device *);
 extern void nr_destroy_socket(struct sock *);
 
 /* nr_dev.c */
-extern int  nr_rx_ip(struct sk_buff *, struct device *);
-extern int  nr_init(struct device *);
+extern int  nr_rx_ip(struct sk_buff *, struct net_device *);
+extern int  nr_init(struct net_device *);
 
 #include <net/nrcall.h>
 
@@ -141,9 +141,9 @@
 extern void nr_check_iframes_acked(struct sock *, unsigned short);
 
 /* nr_route.c */
-extern void nr_rt_device_down(struct device *);
-extern struct device *nr_dev_first(void);
-extern struct device *nr_dev_get(ax25_address *);
+extern void nr_rt_device_down(struct net_device *);
+extern struct net_device *nr_dev_first(void);
+extern struct net_device *nr_dev_get(ax25_address *);
 extern int  nr_rt_ioctl(unsigned int, void *);
 extern void nr_link_failed(ax25_cb *, int);
 extern int  nr_route_frame(struct sk_buff *, ax25_cb *);
diff -u --recursive --new-file v2.3.13/linux/include/net/p8022.h linux/include/net/p8022.h
--- v2.3.13/linux/include/net/p8022.h	Sun Mar 24 22:58:22 1996
+++ linux/include/net/p8022.h	Wed Aug 18 11:38:47 1999
@@ -1,7 +1,7 @@
 #ifndef _NET_P8022_H
 #define _NET_P8022_H
 
-extern struct datalink_proto *register_8022_client(unsigned char type, int (*rcvfunc)(struct sk_buff *, struct device *, struct packet_type *));
+extern struct datalink_proto *register_8022_client(unsigned char type, int (*rcvfunc)(struct sk_buff *, struct net_device *, struct packet_type *));
 extern void unregister_8022_client(unsigned char type);
 
 #endif
diff -u --recursive --new-file v2.3.13/linux/include/net/pkt_sched.h linux/include/net/pkt_sched.h
--- v2.3.13/linux/include/net/pkt_sched.h	Wed Jun  9 14:45:36 1999
+++ linux/include/net/pkt_sched.h	Wed Aug 18 11:38:47 1999
@@ -86,7 +86,7 @@
 	u32			handle;
 	atomic_t		refcnt;
 	struct sk_buff_head	q;
-	struct device 		*dev;
+	struct net_device 		*dev;
 
 	struct tc_stats		stats;
 	unsigned long		tx_timeo;
@@ -412,15 +412,15 @@
 
 int register_qdisc(struct Qdisc_ops *qops);
 int unregister_qdisc(struct Qdisc_ops *qops);
-struct Qdisc *qdisc_lookup(struct device *dev, u32 handle);
-struct Qdisc *qdisc_lookup_class(struct device *dev, u32 handle);
-void dev_init_scheduler(struct device *dev);
-void dev_shutdown(struct device *dev);
-void dev_activate(struct device *dev);
-void dev_deactivate(struct device *dev);
+struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle);
+struct Qdisc *qdisc_lookup_class(struct net_device *dev, u32 handle);
+void dev_init_scheduler(struct net_device *dev);
+void dev_shutdown(struct net_device *dev);
+void dev_activate(struct net_device *dev);
+void dev_deactivate(struct net_device *dev);
 void qdisc_reset(struct Qdisc *qdisc);
 void qdisc_destroy(struct Qdisc *qdisc);
-struct Qdisc * qdisc_create_dflt(struct device *dev, struct Qdisc_ops *ops);
+struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops);
 int qdisc_new_estimator(struct tc_stats *stats, struct rtattr *opt);
 void qdisc_kill_estimator(struct tc_stats *stats);
 struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, struct rtattr *tab);
@@ -430,7 +430,7 @@
 int pktsched_init(void);
 
 extern void qdisc_run_queues(void);
-extern int qdisc_restart(struct device *dev);
+extern int qdisc_restart(struct net_device *dev);
 
 extern spinlock_t qdisc_runqueue_lock;
 
@@ -466,7 +466,7 @@
  * BH must be disabled on this CPU.
  */
 
-extern __inline__ void qdisc_wakeup(struct device *dev)
+extern __inline__ void qdisc_wakeup(struct net_device *dev)
 {
 	if (!dev->tbusy) {
 		spin_lock(&dev->queue_lock);
@@ -479,7 +479,7 @@
 /* Calculate maximal size of packet seen by hard_start_xmit
    routine of this device.
  */
-extern __inline__ unsigned psched_mtu(struct device *dev)
+extern __inline__ unsigned psched_mtu(struct net_device *dev)
 {
 	unsigned mtu = dev->mtu;
 	return dev->hard_header ? mtu + dev->hard_header_len : mtu;
diff -u --recursive --new-file v2.3.13/linux/include/net/psnap.h linux/include/net/psnap.h
--- v2.3.13/linux/include/net/psnap.h	Sun Mar 24 22:58:22 1996
+++ linux/include/net/psnap.h	Wed Aug 18 11:38:47 1999
@@ -1,7 +1,7 @@
 #ifndef _NET_PSNAP_H
 #define _NET_PSNAP_H
 
-extern struct datalink_proto *register_snap_client(unsigned char *desc, int (*rcvfunc)(struct sk_buff *, struct device *, struct packet_type *));
+extern struct datalink_proto *register_snap_client(unsigned char *desc, int (*rcvfunc)(struct sk_buff *, struct net_device *, struct packet_type *));
 extern void unregister_snap_client(unsigned char *desc);
 
 #endif
diff -u --recursive --new-file v2.3.13/linux/include/net/rose.h linux/include/net/rose.h
--- v2.3.13/linux/include/net/rose.h	Wed Oct  7 15:52:55 1998
+++ linux/include/net/rose.h	Wed Aug 18 11:38:47 1999
@@ -84,7 +84,7 @@
 	ax25_address		callsign;
 	ax25_digi		*digipeat;
 	ax25_cb			*ax25;
-	struct device		*dev;
+	struct net_device		*dev;
 	unsigned short		count;
 	unsigned short		use;
 	unsigned int		number;
@@ -121,7 +121,7 @@
 	ax25_address		source_digis[ROSE_MAX_DIGIS];
 	ax25_address		dest_digis[ROSE_MAX_DIGIS];
 	struct rose_neigh	*neighbour;
-	struct device		*device;
+	struct net_device		*device;
 	unsigned int		lci, rand;
 	unsigned char		state, condition, qbitincl, defer;
 	unsigned char		cause, diagnostic;
@@ -156,12 +156,12 @@
 extern struct sock *rose_find_socket(unsigned int, struct rose_neigh *);
 extern void rose_kill_by_neigh(struct rose_neigh *);
 extern unsigned int rose_new_lci(struct rose_neigh *);
-extern int  rose_rx_call_request(struct sk_buff *, struct device *, struct rose_neigh *, unsigned int);
+extern int  rose_rx_call_request(struct sk_buff *, struct net_device *, struct rose_neigh *, unsigned int);
 extern void rose_destroy_socket(struct sock *);
 
 /* rose_dev.c */
-extern int  rose_rx_ip(struct sk_buff *, struct device *);
-extern int  rose_init(struct device *);
+extern int  rose_rx_ip(struct sk_buff *, struct net_device *);
+extern int  rose_init(struct net_device *);
 
 #include <net/rosecall.h>
 
@@ -197,12 +197,12 @@
 extern int  rose_add_loopback_neigh(void);
 extern int  rose_add_loopback_node(rose_address *);
 extern void rose_del_loopback_node(rose_address *);
-extern void rose_rt_device_down(struct device *);
-extern void rose_link_device_down(struct device *);
-extern struct device *rose_dev_first(void);
-extern struct device *rose_dev_get(rose_address *);
+extern void rose_rt_device_down(struct net_device *);
+extern void rose_link_device_down(struct net_device *);
+extern struct net_device *rose_dev_first(void);
+extern struct net_device *rose_dev_get(rose_address *);
 extern struct rose_route *rose_route_free_lci(unsigned int, struct rose_neigh *);
-extern struct device *rose_ax25_dev_get(char *);
+extern struct net_device *rose_ax25_dev_get(char *);
 extern struct rose_neigh *rose_get_neigh(rose_address *, unsigned char *, unsigned char *);
 extern int  rose_rt_ioctl(unsigned int, void *);
 extern void rose_link_failed(ax25_cb *, int);
diff -u --recursive --new-file v2.3.13/linux/include/net/route.h linux/include/net/route.h
--- v2.3.13/linux/include/net/route.h	Tue Jun 22 14:42:40 1999
+++ linux/include/net/route.h	Wed Aug 18 16:44:34 1999
@@ -100,11 +100,11 @@
 
 extern void		ip_rt_init(void);
 extern void		ip_rt_redirect(u32 old_gw, u32 dst, u32 new_gw,
-				       u32 src, u8 tos, struct device *dev);
+				       u32 src, u8 tos, struct net_device *dev);
 extern void		ip_rt_advice(struct rtable **rp, int advice);
 extern void		rt_cache_flush(int how);
 extern int		ip_route_output(struct rtable **, u32 dst, u32 src, u32 tos, int oif);
-extern int		ip_route_input(struct sk_buff*, u32 dst, u32 src, u8 tos, struct device *devin);
+extern int		ip_route_input(struct sk_buff*, u32 dst, u32 src, u8 tos, struct net_device *devin);
 extern unsigned short	ip_rt_frag_needed(struct iphdr *iph, unsigned short new_mtu);
 extern void		ip_rt_update_pmtu(struct dst_entry *dst, unsigned mtu);
 extern void		ip_rt_send_redirect(struct sk_buff *skb);
diff -u --recursive --new-file v2.3.13/linux/include/net/tcp.h linux/include/net/tcp.h
--- v2.3.13/linux/include/net/tcp.h	Thu Jul  8 15:42:21 1999
+++ linux/include/net/tcp.h	Wed Aug 18 16:44:39 1999
@@ -85,6 +85,7 @@
 extern struct tcp_bind_bucket *tcp_bucket_create(unsigned short snum);
 extern void tcp_bucket_unlock(struct sock *sk);
 extern int tcp_port_rover;
+extern struct sock *tcp_v4_lookup_listener(u32 addr, unsigned short hnum, int dif);						
 
 /* Level-1 socket-demux cache. */
 #define TCP_NUM_REGS		32
diff -u --recursive --new-file v2.3.13/linux/include/net/x25.h linux/include/net/x25.h
--- v2.3.13/linux/include/net/x25.h	Mon Oct  5 17:33:35 1998
+++ linux/include/net/x25.h	Wed Aug 18 11:38:47 1999
@@ -102,12 +102,12 @@
 	struct x25_route	*next;
 	x25_address		address;	/* Start of address range */
 	unsigned int		sigdigits;	/* Number of sig digits */
-	struct device		*dev;		/* More than one for MLP */
+	struct net_device		*dev;		/* More than one for MLP */
 };
 
 struct x25_neigh {
 	struct x25_neigh	*next;
-	struct device		*dev;
+	struct net_device		*dev;
 	unsigned int		state;
 	unsigned int		extended;
 	struct sk_buff_head	queue;
@@ -153,8 +153,8 @@
 
 /* x25_dev.c */
 extern void x25_send_frame(struct sk_buff *, struct x25_neigh *);
-extern int  x25_lapb_receive_frame(struct sk_buff *, struct device *, struct packet_type *);
-extern int  x25_llc_receive_frame(struct sk_buff *, struct device *, struct packet_type *);
+extern int  x25_lapb_receive_frame(struct sk_buff *, struct net_device *, struct packet_type *);
+extern int  x25_llc_receive_frame(struct sk_buff *, struct net_device *, struct packet_type *);
 extern void x25_establish_link(struct x25_neigh *);
 extern void x25_terminate_link(struct x25_neigh *);
 
@@ -169,8 +169,8 @@
 
 /* x25_link.c */
 extern void x25_link_control(struct sk_buff *, struct x25_neigh *, unsigned short);
-extern void x25_link_device_up(struct device *);
-extern void x25_link_device_down(struct device *);
+extern void x25_link_device_up(struct net_device *);
+extern void x25_link_device_down(struct net_device *);
 extern void x25_link_established(struct x25_neigh *);
 extern void x25_link_terminated(struct x25_neigh *);
 extern void x25_transmit_restart_request(struct x25_neigh *);
@@ -179,7 +179,7 @@
 extern void x25_transmit_clear_request(struct x25_neigh *, unsigned int, unsigned char);
 extern void x25_transmit_link(struct sk_buff *, struct x25_neigh *);
 extern int  x25_subscr_ioctl(unsigned int, void *);
-extern struct x25_neigh *x25_get_neigh(struct device *);
+extern struct x25_neigh *x25_get_neigh(struct net_device *);
 extern void x25_link_free(void);
 
 /* x25_out.c */
@@ -188,9 +188,9 @@
 extern void x25_enquiry_response(struct sock *);
 
 /* x25_route.c */
-extern struct device *x25_get_route(x25_address *);
-extern struct device *x25_dev_get(char *);
-extern void x25_route_device_down(struct device *);
+extern struct net_device *x25_get_route(x25_address *);
+extern struct net_device *x25_dev_get(char *);
+extern void x25_route_device_down(struct net_device *);
 extern int  x25_route_ioctl(unsigned int, void *);
 extern int  x25_routes_get_info(char *, char **, off_t, int, int);
 extern void x25_route_free(void);
diff -u --recursive --new-file v2.3.13/linux/init/main.c linux/init/main.c
--- v2.3.13/linux/init/main.c	Mon Aug  9 14:59:23 1999
+++ linux/init/main.c	Sun Aug 15 11:50:35 1999
@@ -52,6 +52,10 @@
 extern void nubus_init(void);
 #endif
 
+#ifdef CONFIG_ISAPNP
+#include <linux/isapnp.h>
+#endif
+
 /*
  * Versions of gcc older than that listed below may actually compile
  * and link okay, but the end product can have subtle run time bugs.
@@ -631,6 +635,9 @@
 #endif
 #ifdef CONFIG_MAC
 	nubus_init();
+#endif
+#ifdef CONFIG_ISAPNP
+	isapnp_init();
 #endif
 
 	/* Networking initialization needs a process context */ 
diff -u --recursive --new-file v2.3.13/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v2.3.13/linux/kernel/ksyms.c	Mon Aug  9 14:59:23 1999
+++ linux/kernel/ksyms.c	Wed Aug 18 11:19:11 1999
@@ -277,6 +277,8 @@
 EXPORT_SYMBOL(proc_dointvec);
 EXPORT_SYMBOL(proc_dointvec_jiffies);
 EXPORT_SYMBOL(proc_dointvec_minmax);
+EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax);
+EXPORT_SYMBOL(proc_doulongvec_minmax);
 
 /* interrupt handling */
 EXPORT_SYMBOL(request_irq);
diff -u --recursive --new-file v2.3.13/linux/kernel/printk.c linux/kernel/printk.c
--- v2.3.13/linux/kernel/printk.c	Mon Aug  9 14:59:23 1999
+++ linux/kernel/printk.c	Mon Aug 16 23:58:59 1999
@@ -46,6 +46,7 @@
 static unsigned long logged_chars = 0;
 struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];
 static int preferred_console = -1;
+spinlock_t console_lock = SPIN_LOCK_UNLOCKED;
 
 /*
  *	Setup a list of consoles. Called from init/main.c
@@ -117,12 +118,11 @@
  */
 int do_syslog(int type, char * buf, int len)
 {
-	unsigned long i, j, count, flags;
+	unsigned long i, j, count;
 	int do_clear = 0;
 	char c;
 	int error = -EPERM;
 
-	lock_kernel();
 	error = 0;
 	switch (type) {
 	case 0:		/* Close log */
@@ -143,18 +143,19 @@
 		if (error)
 			goto out;
 		i = 0;
+		spin_lock_irq(&console_lock);
 		while (log_size && i < len) {
 			c = *((char *) log_buf+log_start);
 			log_start++;
 			log_size--;
 			log_start &= LOG_BUF_LEN-1;
-			sti();
+			spin_unlock_irq(&console_lock);
 			__put_user(c,buf);
 			buf++;
 			i++;
-			cli();
+			spin_lock_irq(&console_lock);
 		}
-		sti();
+		spin_unlock_irq(&console_lock);
 		error = i;
 		break;
 	case 4:		/* Read/clear last kernel messages */
@@ -170,43 +171,59 @@
 		error = verify_area(VERIFY_WRITE,buf,len);
 		if (error)
 			goto out;
-		/*
-		 * The logged_chars, log_start, and log_size values may
-		 * change from an interrupt, so we disable interrupts.
-		 */
-		__save_flags(flags);
-		__cli();
 		count = len;
 		if (count > LOG_BUF_LEN)
 			count = LOG_BUF_LEN;
+		/* The logged_chars, log_start, and log_size are serialized
+		   by the console_lock (the console_lock can be acquired also
+		   from irqs by printk). */
+		spin_lock_irq(&console_lock);
 		if (count > logged_chars)
 			count = logged_chars;
 		j = log_start + log_size - count;
-		__restore_flags(flags);
+		spin_unlock_irq(&console_lock);
+		/* While writing data to the userspace buffer printk may
+		   trash our information but the _only_ thing we care is to
+		   have a coherent `j' value. */
 		for (i = 0; i < count; i++) {
 			c = *((char *) log_buf+(j++ & (LOG_BUF_LEN-1)));
 			__put_user(c, buf++);
 		}
 		if (do_clear)
+		{
+			/* the increment done in printk may undo our
+			   not atomic assigment if we do it without the
+			   console lock held. */
+			spin_lock_irq(&console_lock);
 			logged_chars = 0;
+			spin_unlock_irq(&console_lock);
+		}
 		error = i;
 		break;
 	case 5:		/* Clear ring buffer */
+		spin_lock_irq(&console_lock);
 		logged_chars = 0;
+		spin_unlock_irq(&console_lock);
 		break;
 	case 6:		/* Disable logging to console */
+		spin_lock_irq(&console_lock);
 		console_loglevel = minimum_console_loglevel;
+		spin_unlock_irq(&console_lock);
 		break;
 	case 7:		/* Enable logging to console */
+		spin_lock_irq(&console_lock);
 		console_loglevel = default_console_loglevel;
+		spin_unlock_irq(&console_lock);
 		break;
 	case 8:
 		error = -EINVAL;
 		if (len < 1 || len > 8)
 			goto out;
+		spin_lock_irq(&console_lock);
 		if (len < minimum_console_loglevel)
 			len = minimum_console_loglevel;
 		console_loglevel = len;
+		spin_unlock_irq(&console_lock);
 		error = 0;
 		break;
 	default:
@@ -214,7 +231,6 @@
 		break;
 	}
 out:
-	unlock_kernel();
 	return error;
 }
 
@@ -226,8 +242,6 @@
 }
 
 
-spinlock_t console_lock;
-
 asmlinkage int printk(const char *fmt, ...)
 {
 	va_list args;
@@ -295,21 +309,26 @@
 	struct console *c = console_drivers;
 	int len = strlen(s);
 
+	spin_lock_irq(&console_lock);
 	while(c) {
 		if ((c->flags & CON_ENABLED) && c->write)
 			c->write(c, s, len);
 		c = c->next;
 	}
+	spin_unlock_irq(&console_lock);
 }
 
 void unblank_console(void)
 {
 	struct console *c = console_drivers;
+
+	spin_lock_irq(&console_lock);
 	while(c) {
 		if ((c->flags & CON_ENABLED) && c->unblank)
 			c->unblank();
 		c = c->next;
 	}
+	spin_unlock_irq(&console_lock);
 }
 
 /*
@@ -321,11 +340,12 @@
 void register_console(struct console * console)
 {
 	int	i,j,len;
-	int	p = log_start;
+	int	p;
 	char	buf[16];
 	signed char msg_level = -1;
 	char	*q;
 
+	spin_lock_irq(&console_lock);
 	/*
 	 *	See if we want to use this console driver. If we
 	 *	didn't select a console we take the first one
@@ -364,7 +384,7 @@
 	}
 
 	if (!(console->flags & CON_ENABLED))
-		return;
+		goto out;
 
 	/*
 	 *	Put this console in the list - keep the
@@ -377,12 +397,12 @@
 		console->next = console_drivers->next;
 		console_drivers->next = console;
 	}
-	if ((console->flags & CON_PRINTBUFFER) == 0) return;
+	if ((console->flags & CON_PRINTBUFFER) == 0) goto out;
 
 	/*
 	 *	Print out buffered log messages.
 	 */
-	for (i=0,j=0; i < log_size; i++) {
+	for (p=log_start,i=0,j=0; i < log_size; i++) {
 		buf[j++] = log_buf[p];
 		p++; p &= LOG_BUF_LEN-1;
 		if (buf[j-1] != '\n' && i < log_size - 1 && j < sizeof(buf)-1)
@@ -401,26 +421,32 @@
 			msg_level = -1;
 		j = 0;
 	}
+ out:
+	spin_unlock_irq(&console_lock);
 }
 
 
 int unregister_console(struct console * console)
 {
         struct console *a,*b;
+	int ret = 0;
 	
+	spin_lock_irq(&console_lock);
 	if (console_drivers == console) {
 		console_drivers=console->next;
-		return (0);
+		goto out;
 	}
 	for (a=console_drivers->next, b=console_drivers ;
 	     a; b=a, a=b->next) {
 		if (a == console) {
 			b->next = a->next;
-			return 0;
+			goto out;
 		}  
 	}
-	
-	return (1);
+	ret = 1;
+ out:
+	spin_unlock_irq(&console_lock);
+	return ret;
 }
 	
 /*
diff -u --recursive --new-file v2.3.13/linux/kernel/sysctl.c linux/kernel/sysctl.c
--- v2.3.13/linux/kernel/sysctl.c	Mon Aug  9 14:59:23 1999
+++ linux/kernel/sysctl.c	Thu Aug 12 10:19:59 1999
@@ -8,7 +8,10 @@
  * Added kernel/java-{interpreter,appletviewer}, 96/5/10, Mike Shaver.
  * Dynamic registration fixes, Stephen Tweedie.
  * Added kswapd-interval, ctrl-alt-del, printk stuff, 1/8/97, Chris Horn.
- * Made sysctl support optional via CONFIG_SYSCTL, 1/10/97, Chris Horn.
+ * Made sysctl support optional via CONFIG_SYSCTL, 1/10/97, Chris
+ *  Horn.
+ * Added proc_doulongvec_ms_jiffies_minmax, 09/08/99, Carlos H. Bauer.
+ * Added proc_doulongvec_minmax, 09/08/99, Carlos H. Bauer.
  */
 
 #include <linux/config.h>
@@ -912,6 +915,131 @@
 	return 0;
 }
 
+
+/*
+ * an unsigned long function version
+ */
+
+static int do_proc_doulongvec_minmax(ctl_table *table, int write,
+				     struct file *filp,
+				     void *buffer, size_t *lenp,
+				     unsigned long convmul,
+				     unsigned long convdiv)
+{
+#define TMPBUFLEN 20
+	unsigned long *i, *min, *max, val;
+	int vleft, first=1, len, left, neg;
+	char buf[TMPBUFLEN], *p;
+	
+	if (!table->data || !table->maxlen || !*lenp ||
+	    (filp->f_pos && !write)) {
+		*lenp = 0;
+		return 0;
+	}
+	
+	i = (unsigned long *) table->data;
+	min = (unsigned long *) table->extra1;
+	max = (unsigned long *) table->extra2;
+	vleft = table->maxlen / sizeof(unsigned long);
+	left = *lenp;
+	
+	for (; left && vleft--; i++, first=0) {
+		if (write) {
+			while (left) {
+				char c;
+				if(get_user(c, (char *) buffer))
+					return -EFAULT;
+				if (!isspace(c))
+					break;
+				left--;
+				((char *) buffer)++;
+			}
+			if (!left)
+				break;
+			neg = 0;
+			len = left;
+			if (len > TMPBUFLEN-1)
+				len = TMPBUFLEN-1;
+			if(copy_from_user(buf, buffer, len))
+				return -EFAULT;
+			buf[len] = 0;
+			p = buf;
+			if (*p == '-' && left > 1) {
+				neg = 1;
+				left--, p++;
+			}
+			if (*p < '0' || *p > '9')
+				break;
+			val = simple_strtoul(p, &p, 0) * convmul / convdiv ;
+			len = p-buf;
+			if ((len < left) && *p && !isspace(*p))
+				break;
+			if (neg)
+				val = -val;
+			buffer += len;
+			left -= len;
+
+			if(neg)
+				continue;
+			if (min && val < *min++)
+				continue;
+			if (max && val > *max++)
+				continue;
+			*i = val;
+		} else {
+			p = buf;
+			if (!first)
+				*p++ = '\t';
+			sprintf(p, "%lu", convdiv * (*i) / convmul);
+			len = strlen(buf);
+			if (len > left)
+				len = left;
+			if(copy_to_user(buffer, buf, len))
+				return -EFAULT;
+			left -= len;
+			buffer += len;
+		}
+	}
+
+	if (!write && !first && left) {
+		if(put_user('\n', (char *) buffer))
+			return -EFAULT;
+		left--, buffer++;
+	}
+	if (write) {
+		p = (char *) buffer;
+		while (left) {
+			char c;
+			if(get_user(c, p++))
+				return -EFAULT;
+			if (!isspace(c))
+				break;
+			left--;
+		}
+	}
+	if (write && first)
+		return -EINVAL;
+	*lenp -= left;
+	filp->f_pos += *lenp;
+	return 0;
+#undef TMPBUFLEN
+}
+
+int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
+			   void *buffer, size_t *lenp)
+{
+    return do_proc_doulongvec_minmax(table, write, filp, buffer, lenp, 1l, 1l);
+}
+
+int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
+				      struct file *filp,
+				      void *buffer, size_t *lenp)
+{
+    return do_proc_doulongvec_minmax(table, write, filp, buffer,
+				     lenp, HZ, 1000l);
+}
+
+
 /* Like proc_dointvec, but converts seconds to jiffies */
 int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
 			  void *buffer, size_t *lenp)
@@ -951,6 +1079,20 @@
 	return -ENOSYS;
 }
 
+int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
+		    void *buffer, size_t *lenp)
+{
+	return -ENOSYS;
+}
+
+int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
+				      struct file *filp,
+				      void *buffer, size_t *lenp)
+{
+    return -ENOSYS;
+}
+
+
 #endif /* CONFIG_PROC_FS */
 
 
@@ -1149,9 +1291,22 @@
 }
 
 int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
+			  void *buffer, size_t *lenp)
+{
+	return -ENOSYS;
+}
+
+int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
 		    void *buffer, size_t *lenp)
 {
 	return -ENOSYS;
+}
+
+int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
+				      struct file *filp,
+				      void *buffer, size_t *lenp)
+{
+    return -ENOSYS;
 }
 
 struct ctl_table_header * register_sysctl_table(ctl_table * table, 
diff -u --recursive --new-file v2.3.13/linux/mm/filemap.c linux/mm/filemap.c
--- v2.3.13/linux/mm/filemap.c	Mon Aug  9 14:59:23 1999
+++ linux/mm/filemap.c	Fri Aug 13 11:49:39 1999
@@ -1304,7 +1304,6 @@
 	if (!page)
 		goto no_cached_page;
 
-found_page:
 	/*
 	 * Ok, found a page in the page cache, now we need to check
 	 * that it's up-to-date.  First check whether we'll need an
@@ -1316,12 +1315,8 @@
 			goto failure;
 	}
 
-	if (!Page_Uptodate(page)) {
-		lock_page(page);
-		if (!Page_Uptodate(page))
-			goto page_not_uptodate;
-		UnlockPage(page);
-	}
+	if (!Page_Uptodate(page))
+		goto page_not_uptodate;
 
 success:
 	/*
@@ -1360,44 +1355,28 @@
 	for (i = 1 << page_cluster; i > 0; --i, reada += PAGE_CACHE_SIZE)
 		new_page = try_to_read_ahead(file, reada, new_page);
 
-	if (!new_page)
-		new_page = page_cache_alloc();
-	if (!new_page)
-		goto no_page;
-
 	/*
-	 * During getting the above page we might have slept,
-	 * so we need to re-check the situation with the page
-	 * cache.. The page we just got may be useful if we
-	 * can't share, so don't get rid of it here.
+	 * The page we want has now been added to the page cache.
+	 * In the unlikely event that someone removed it in the
+	 * meantime, we'll just come back here and read it again.
 	 */
-	page = __find_get_page(inode, offset, hash);
-	if (page)
-		goto found_page;
-
-	/*
-	 * Now, create a new page-cache page from the page we got
-	 */
-	page = page_cache_entry(new_page);
-	if (add_to_page_cache_unique(page, inode, offset, hash))
-		goto retry_find;
-
-	/*
-	 * Now it's ours and locked, we can do initial IO to it:
-	 */
-	new_page = 0;
+	goto retry_find;
 
 page_not_uptodate:
+	lock_page(page);
+	if (Page_Uptodate(page)) {
+		UnlockPage(page);
+		goto success;
+	}
+
 	error = inode->i_op->readpage(file, page);
 
 	if (!error) {
 		wait_on_page(page);
-		if (PageError(page))
-			goto page_read_error;
-		goto success;
+		if (Page_Uptodate(page))
+			goto success;
 	}
 
-page_read_error:
 	/*
 	 * Umm, take care of errors if the page isn't up-to-date.
 	 * Try to re-read it _once_. We do this synchronously,
diff -u --recursive --new-file v2.3.13/linux/mm/mlock.c linux/mm/mlock.c
--- v2.3.13/linux/mm/mlock.c	Thu Jul  8 15:42:21 1999
+++ linux/mm/mlock.c	Thu Aug 12 12:22:36 1999
@@ -130,7 +130,7 @@
 	struct vm_area_struct * vma, * next;
 	int error;
 
-	if (!capable(CAP_IPC_LOCK))
+	if (on && !capable(CAP_IPC_LOCK))
 		return -EPERM;
 	len = (len + ~PAGE_MASK) & PAGE_MASK;
 	end = start + len;
diff -u --recursive --new-file v2.3.13/linux/mm/page_io.c linux/mm/page_io.c
--- v2.3.13/linux/mm/page_io.c	Mon Aug  9 14:59:23 1999
+++ linux/mm/page_io.c	Wed Aug 18 10:49:38 1999
@@ -18,8 +18,6 @@
 
 #include <asm/pgtable.h>
 
-static DECLARE_WAIT_QUEUE_HEAD(lock_queue);
-
 /*
  * Reads or writes a swap page.
  * wait=1: start I/O and wait for completion. wait=0: start asynchronous I/O.
@@ -167,24 +165,6 @@
 	if (page->inode != &swapper_inode)
 		PAGE_BUG(page);
 	rw_swap_page_base(rw, entry, page, wait, 1);
-}
-
-/*
- * Setting up a new swap file needs a simple wrapper just to read the 
- * swap signature.  SysV shared memory also needs a simple wrapper.
- */
-void rw_swap_page_nocache(int rw, unsigned long entry, char *buf)
-{
-	struct page *page = mem_map + MAP_NR(buf);
-	
-	if (TryLockPage(page))
-		PAGE_BUG(page);
-	if (PageSwapCache(page))
-		PAGE_BUG(page);
-	if (page->inode)
-		PAGE_BUG(page);
-	page->offset = entry;
-	rw_swap_page_base(rw, entry, page, 1, 1);
 }
 
 /*
diff -u --recursive --new-file v2.3.13/linux/mm/vmscan.c linux/mm/vmscan.c
--- v2.3.13/linux/mm/vmscan.c	Mon Aug  9 14:59:23 1999
+++ linux/mm/vmscan.c	Mon Aug 16 17:54:49 1999
@@ -50,10 +50,7 @@
 	if (pte_val(pte) != pte_val(*page_table))
 		goto out_failed_unlock;
 
-	/*
-	 * Dont be too eager to get aging right if
-	 * memory is dangerously low.
-	 */
+	/* Don't look at this pte if it's been accessed recently. */
 	if (pte_young(pte)) {
 		/*
 		 * Transfer the "accessed" bit from the page
diff -u --recursive --new-file v2.3.13/linux/net/802/fddi.c linux/net/802/fddi.c
--- v2.3.13/linux/net/802/fddi.c	Sun Nov 15 09:52:28 1998
+++ linux/net/802/fddi.c	Wed Aug 18 11:38:48 1999
@@ -51,7 +51,7 @@
  * daddr=NULL	means leave destination address (eg unresolved arp)
  */
 
-int fddi_header(struct sk_buff	*skb, struct device *dev, unsigned short type,
+int fddi_header(struct sk_buff	*skb, struct net_device *dev, unsigned short type,
 		void *daddr, void *saddr, unsigned len)
 {
 	int hl = FDDI_K_SNAP_HLEN;
@@ -120,7 +120,7 @@
  * the proper pointer to the start of packet data (skb->data).
  */
  
-unsigned short fddi_type_trans(struct sk_buff *skb, struct device *dev)
+unsigned short fddi_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
 	struct fddihdr *fddi = (struct fddihdr *)skb->data;
 	unsigned short type;
diff -u --recursive --new-file v2.3.13/linux/net/802/hippi.c linux/net/802/hippi.c
--- v2.3.13/linux/net/802/hippi.c	Wed Oct  7 11:13:49 1998
+++ linux/net/802/hippi.c	Wed Aug 18 11:38:48 1999
@@ -57,7 +57,7 @@
  * daddr=NULL	means leave destination address (eg unresolved arp)
  */
 
-int hippi_header(struct sk_buff *skb, struct device *dev,
+int hippi_header(struct sk_buff *skb, struct net_device *dev,
 		 unsigned short type, void *daddr, void *saddr,
 		 unsigned len)
 {
@@ -133,7 +133,7 @@
  *	Determine the packet's protocol ID.
  */
  
-unsigned short hippi_type_trans(struct sk_buff *skb, struct device *dev)
+unsigned short hippi_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
 	struct hippi_hdr *hip;
 	
diff -u --recursive --new-file v2.3.13/linux/net/802/p8022.c linux/net/802/p8022.c
--- v2.3.13/linux/net/802/p8022.c	Wed May 20 18:55:16 1998
+++ linux/net/802/p8022.c	Wed Aug 18 11:38:48 1999
@@ -47,7 +47,7 @@
 	return proto;
 }
 
-int p8022_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
+int p8022_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
 {
 	struct datalink_proto	*proto;
 
@@ -68,7 +68,7 @@
 static void p8022_datalink_header(struct datalink_proto *dl,
 		struct sk_buff *skb, unsigned char *dest_node)
 {
-	struct device	*dev = skb->dev;
+	struct net_device	*dev = skb->dev;
 	unsigned char	*rawp;
 
 	rawp = skb_push(skb,3);
@@ -96,7 +96,7 @@
 	dev_add_pack(&p8022_packet_type);
 }
 
-struct datalink_proto *register_8022_client(unsigned char type, int (*rcvfunc)(struct sk_buff *, struct device *, struct packet_type *))
+struct datalink_proto *register_8022_client(unsigned char type, int (*rcvfunc)(struct sk_buff *, struct net_device *, struct packet_type *))
 {
 	struct datalink_proto	*proto;
 
diff -u --recursive --new-file v2.3.13/linux/net/802/p8023.c linux/net/802/p8023.c
--- v2.3.13/linux/net/802/p8023.c	Thu Jan  2 05:13:27 1997
+++ linux/net/802/p8023.c	Wed Aug 18 11:38:48 1999
@@ -27,7 +27,7 @@
 static void p8023_datalink_header(struct datalink_proto *dl, 
 		struct sk_buff *skb, unsigned char *dest_node)
 {
-	struct device	*dev = skb->dev;
+	struct net_device	*dev = skb->dev;
 	dev->hard_header(skb, dev, ETH_P_802_3, dest_node, NULL, skb->len);
 }
 
diff -u --recursive --new-file v2.3.13/linux/net/802/psnap.c linux/net/802/psnap.c
--- v2.3.13/linux/net/802/psnap.c	Fri Jul 10 13:51:41 1998
+++ linux/net/802/psnap.c	Wed Aug 18 11:38:48 1999
@@ -39,7 +39,7 @@
  *	A SNAP packet has arrived
  */
 
-int snap_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
+int snap_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
 {
 	static struct packet_type psnap_packet_type =
 	{
@@ -100,7 +100,7 @@
  *	Register SNAP clients. We don't yet use this for IP.
  */
 
-struct datalink_proto *register_snap_client(unsigned char *desc, int (*rcvfunc)(struct sk_buff *, struct device *, struct packet_type *))
+struct datalink_proto *register_snap_client(unsigned char *desc, int (*rcvfunc)(struct sk_buff *, struct net_device *, struct packet_type *))
 {
 	struct datalink_proto	*proto;
 
diff -u --recursive --new-file v2.3.13/linux/net/802/tr.c linux/net/802/tr.c
--- v2.3.13/linux/net/802/tr.c	Sat Apr 24 17:51:48 1999
+++ linux/net/802/tr.c	Wed Aug 18 11:38:48 1999
@@ -36,8 +36,8 @@
 #include <linux/init.h>
 #include <net/arp.h>
 
-static void tr_source_route(struct sk_buff *skb, struct trh_hdr *trh, struct device *dev);
-static void tr_add_rif_info(struct trh_hdr *trh, struct device *dev);
+static void tr_source_route(struct sk_buff *skb, struct trh_hdr *trh, struct net_device *dev);
+static void tr_add_rif_info(struct trh_hdr *trh, struct net_device *dev);
 static void rif_check_expire(unsigned long dummy);
 
 #define TR_SR_DEBUG 0
@@ -85,7 +85,7 @@
  *	makes this a little more exciting than on ethernet.
  */
  
-int tr_header(struct sk_buff *skb, struct device *dev, unsigned short type,
+int tr_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
               void *daddr, void *saddr, unsigned len) 
 {
 	struct trh_hdr *trh;
@@ -144,7 +144,7 @@
 {
 	struct trh_hdr *trh=(struct trh_hdr *)skb->data;
 	struct trllc *trllc=(struct trllc *)(skb->data+sizeof(struct trh_hdr));
-	struct device *dev = skb->dev;
+	struct net_device *dev = skb->dev;
 
 	/*
 	 *	FIXME: We don't yet support IPv6 over token rings
@@ -173,7 +173,7 @@
  *	it via SNAP.
  */
  
-unsigned short tr_type_trans(struct sk_buff *skb, struct device *dev) 
+unsigned short tr_type_trans(struct sk_buff *skb, struct net_device *dev) 
 {
 
 	struct trh_hdr *trh=(struct trh_hdr *)skb->data;
@@ -225,7 +225,7 @@
  *	We try to do source routing... 
  */
 
-static void tr_source_route(struct sk_buff *skb,struct trh_hdr *trh,struct device *dev) 
+static void tr_source_route(struct sk_buff *skb,struct trh_hdr *trh,struct net_device *dev) 
 {
 	int i, slack;
 	unsigned int hash;
@@ -313,7 +313,7 @@
  *	routing.
  */
  
-static void tr_add_rif_info(struct trh_hdr *trh, struct device *dev)
+static void tr_add_rif_info(struct trh_hdr *trh, struct net_device *dev)
 {
 	int i;
 	unsigned int hash, rii_p = 0;
diff -u --recursive --new-file v2.3.13/linux/net/Config.in linux/net/Config.in
--- v2.3.13/linux/net/Config.in	Wed May 26 09:36:36 1999
+++ linux/net/Config.in	Wed Aug 18 09:45:10 1999
@@ -23,6 +23,9 @@
 	    source net/ipv6/Config.in
     fi
   fi
+  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+	source net/khttpd/Config.in
+  fi
 fi
 
 comment ' '
diff -u --recursive --new-file v2.3.13/linux/net/Makefile linux/net/Makefile
--- v2.3.13/linux/net/Makefile	Wed May 26 09:36:36 1999
+++ linux/net/Makefile	Wed Aug 18 09:45:10 1999
@@ -10,7 +10,7 @@
 MOD_SUB_DIRS := ipv4
 ALL_SUB_DIRS := 802 ax25 bridge core ethernet ipv4 ipv6 ipx unix appletalk \
 		netrom rose lapb x25 wanrouter netlink sched packet sunrpc \
-		econet irda decnet
+		econet irda decnet khttpd
 SUB_DIRS     := core ethernet sched
 MOD_LIST_NAME := NET_MISC_MODULES
 
@@ -35,6 +35,14 @@
 else
   ifeq ($(CONFIG_IPV6),m)
   MOD_SUB_DIRS += ipv6
+  endif
+endif
+
+ifeq ($(CONFIG_KHTTPD),y)
+SUB_DIRS += khttpd
+else
+  ifeq ($(CONFIG_KHTTPD),m)
+  MOD_SUB_DIRS += khttpd
   endif
 endif
 
diff -u --recursive --new-file v2.3.13/linux/net/appletalk/aarp.c linux/net/appletalk/aarp.c
--- v2.3.13/linux/net/appletalk/aarp.c	Mon Apr 12 16:18:26 1999
+++ linux/net/appletalk/aarp.c	Wed Aug 18 11:38:48 1999
@@ -75,7 +75,7 @@
 	int status;				/* Used for proxy AARP */
 	unsigned long expires_at;		/* Entry expiry time */
 	struct at_addr target_addr;		/* DDP Address */
-	struct device *dev;			/* Device to use */
+	struct net_device *dev;			/* Device to use */
 	char hwaddr[6];				/* Physical i/f address of target/router */
 	unsigned short xmit_count;		/* When this hits 10 we give up */
 	struct aarp_entry *next;		/* Next entry in chain */
@@ -113,7 +113,7 @@
 static void aarp_send_query(struct aarp_entry *a)
 {
 	static char aarp_eth_multicast[ETH_ALEN]={ 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF };
-	struct device *dev=a->dev;
+	struct net_device *dev=a->dev;
 	int len=dev->hard_header_len+sizeof(struct elapaarp)+aarp_dl->header_length;
 	struct sk_buff *skb=alloc_skb(len, GFP_ATOMIC);
 	struct elapaarp *eah;
@@ -173,7 +173,7 @@
 	a->xmit_count++;
 }
 
-static void aarp_send_reply(struct device *dev, struct at_addr *us, struct at_addr *them, unsigned char *sha)
+static void aarp_send_reply(struct net_device *dev, struct at_addr *us, struct at_addr *them, unsigned char *sha)
 {
 	int len=dev->hard_header_len+sizeof(struct elapaarp)+aarp_dl->header_length;
 	struct sk_buff *skb=alloc_skb(len, GFP_ATOMIC);
@@ -234,7 +234,7 @@
  *	Send probe frames. Called from aarp_probe_network and aarp_proxy_probe_network.
  */
  
-void aarp_send_probe(struct device *dev, struct at_addr *us)
+void aarp_send_probe(struct net_device *dev, struct at_addr *us)
 {
 	int len=dev->hard_header_len+sizeof(struct elapaarp)+aarp_dl->header_length;
 	struct sk_buff *skb=alloc_skb(len, GFP_ATOMIC);
@@ -340,7 +340,7 @@
  *	and remove them.
  */
  
-static void aarp_expire_device(struct aarp_entry **n, struct device *dev)
+static void aarp_expire_device(struct aarp_entry **n, struct net_device *dev)
 {
 	struct aarp_entry *t;
 	while((*n)!=NULL)
@@ -412,7 +412,7 @@
  * Find an entry. We might return an expired but not yet purged entry. We
  * don't care as it will do no harm.
  */
-static struct aarp_entry *aarp_find_entry(struct aarp_entry *list, struct device *dev, struct at_addr *sat)
+static struct aarp_entry *aarp_find_entry(struct aarp_entry *list, struct net_device *dev, struct at_addr *sat)
 {
 	unsigned long flags;
 	save_flags(flags);
@@ -428,7 +428,7 @@
 	return list;
 }
 
-void aarp_proxy_remove(struct device *dev, struct at_addr *sa)
+void aarp_proxy_remove(struct net_device *dev, struct at_addr *sa)
 {
 	struct aarp_entry *a;
 	int hash;
@@ -442,7 +442,7 @@
 	}
 }
 
-struct at_addr* aarp_proxy_find(struct device *dev, struct at_addr *sa)
+struct at_addr* aarp_proxy_find(struct net_device *dev, struct at_addr *sa)
 {
 	struct aarp_entry *a;
 	int hash;
@@ -581,7 +581,7 @@
 /*
  *	Send a DDP frame
  */
-int aarp_send_ddp(struct device *dev,struct sk_buff *skb, struct at_addr *sa, void *hwaddr)
+int aarp_send_ddp(struct net_device *dev,struct sk_buff *skb, struct at_addr *sa, void *hwaddr)
 {
 	static char ddp_eth_multicast[ETH_ALEN]={ 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF };
 	int hash;
@@ -806,7 +806,7 @@
  *	This is called by the SNAP driver whenever we see an AARP SNAP
  *	frame. We currently only support Ethernet.
  */
-static int aarp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
+static int aarp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
 {
 	struct elapaarp *ea=(struct elapaarp *)skb->h.raw;
 	struct aarp_entry *a;
@@ -1038,7 +1038,7 @@
 /*
  * Remove the AARP entries associated with a device.
  */
-void aarp_device_down(struct device *dev)
+void aarp_device_down(struct net_device *dev)
 {
 	int ct = 0;
 
diff -u --recursive --new-file v2.3.13/linux/net/appletalk/ddp.c linux/net/appletalk/ddp.c
--- v2.3.13/linux/net/appletalk/ddp.c	Thu Jul  8 15:42:21 1999
+++ linux/net/appletalk/ddp.c	Wed Aug 18 11:38:48 1999
@@ -92,7 +92,7 @@
 
 extern void aarp_probe_network(struct atalk_iface *atif);
 extern int  aarp_proxy_probe_network(struct atalk_iface *atif, struct at_addr *sa);
-extern void aarp_proxy_remove(struct device *dev, struct at_addr *sa);
+extern void aarp_proxy_remove(struct net_device *dev, struct at_addr *sa);
 
 
 #undef APPLETALK_DEBUG
@@ -283,7 +283,7 @@
  * Drop a device. Doesn't drop any of its routes - that is the caller's
  * problem. Called when we down the interface or delete the address.
  */
-static void atif_drop_device(struct device *dev)
+static void atif_drop_device(struct net_device *dev)
 {
 	struct atalk_iface **iface = &atalk_iface_list;
 	struct atalk_iface *tmp;
@@ -303,7 +303,7 @@
 
 }
 
-static struct atalk_iface *atif_add_device(struct device *dev, struct at_addr *sa)
+static struct atalk_iface *atif_add_device(struct net_device *dev, struct at_addr *sa)
 {
 	struct atalk_iface *iface = (struct atalk_iface *)
 		kmalloc(sizeof(*iface), GFP_KERNEL);
@@ -452,7 +452,7 @@
 }
 
 
-struct at_addr *atalk_find_dev_addr(struct device *dev)
+struct at_addr *atalk_find_dev_addr(struct net_device *dev)
 {
 	struct atalk_iface *iface=dev->atalk_ptr;
 
@@ -491,7 +491,7 @@
  * Find a match for 'any network' - ie any of our interfaces with that
  * node number will do just nicely.
  */
-static struct atalk_iface *atalk_find_anynet(int node, struct device *dev)
+static struct atalk_iface *atalk_find_anynet(int node, struct net_device *dev)
 {
 	struct atalk_iface *iface=dev->atalk_ptr;
 
@@ -589,7 +589,7 @@
  * Given an AppleTalk network, find the device to use. This can be
  * a simple lookup.
  */
-struct device *atrtr_get_dev(struct at_addr *sa)
+struct net_device *atrtr_get_dev(struct at_addr *sa)
 {
 	struct atalk_route *atr=atrtr_find(sa);
 
@@ -602,7 +602,7 @@
 /*
  * Set up a default router.
  */
-static void atrtr_set_default(struct device *dev)
+static void atrtr_set_default(struct net_device *dev)
 {
 	atrtr_default.dev = dev;
 	atrtr_default.flags = RTF_UP;
@@ -615,7 +615,7 @@
  * entry in the list. While it uses netranges we always set them to one
  * entry to work like netatalk.
  */
-static int atrtr_create(struct rtentry *r, struct device *devhint)
+static int atrtr_create(struct rtentry *r, struct net_device *devhint)
 {
 	struct sockaddr_at *ta=(struct sockaddr_at *)&r->rt_dst;
 	struct sockaddr_at *ga=(struct sockaddr_at *)&r->rt_gateway;
@@ -725,7 +725,7 @@
  * Called when a device is downed. Just throw away any routes
  * via it.
  */
-void atrtr_device_down(struct device *dev)
+void atrtr_device_down(struct net_device *dev)
 {
 	struct atalk_route **r = &atalk_router_list;
 	struct atalk_route *tmp;
@@ -748,7 +748,7 @@
 /*
  * Actually down the interface.
  */
-static inline void atalk_dev_down(struct device *dev)
+static inline void atalk_dev_down(struct net_device *dev)
 {
 	atrtr_device_down(dev);	/* Remove all routes for the device */
 	aarp_device_down(dev);	/* Remove AARP entries for the device */
@@ -764,7 +764,7 @@
 	if(event == NETDEV_DOWN)
 	{
 		/* Discard any use of this */
-	        atalk_dev_down((struct device *) ptr);
+	        atalk_dev_down((struct net_device *) ptr);
 	}
 
 	return (NOTIFY_DONE);
@@ -783,7 +783,7 @@
 	static char aarp_mcast[6] = {0x09, 0x00, 0x00, 0xFF, 0xFF, 0xFF};
 	struct netrange *nr;
 	struct sockaddr_at *sa;
-	struct device *dev;
+	struct net_device *dev;
 	struct atalk_iface *atif;
 	int ct;
 	int limit;
@@ -1012,7 +1012,7 @@
 static int atrtr_ioctl(unsigned int cmd, void *arg)
 {
 	struct rtentry rt;
-	struct device *dev = NULL;
+	struct net_device *dev = NULL;
 
 	if(copy_from_user(&rt, arg, sizeof(rt)))
 		return (-EFAULT);
@@ -1422,7 +1422,7 @@
  * extracted. PPP should probably pass frames marked as for this layer.
  * [ie ARPHRD_ETHERTALK]
  */
-static int atalk_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
+static int atalk_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
 {
 	struct sock *sock;
 	struct ddpehdr *ddp=(void *)skb->h.raw;
@@ -1593,7 +1593,7 @@
          */
         if(skb->data[12] == 22)
         {
-                struct device *dev;
+                struct net_device *dev;
 
 		/* This needs to be able to handle ipddp"N" devices */
                 if((dev = dev_get("ipddp0")) == NULL)
@@ -1645,7 +1645,7 @@
  * Caller must provide enough headroom on the packet to pull the short
  * header and append a long one.
  */
-static int ltalk_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
+static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
 {
 	struct ddpehdr *ddp;
 	struct at_addr *ap;
@@ -1712,7 +1712,7 @@
 	struct sockaddr_at *usat=(struct sockaddr_at *)msg->msg_name;
 	struct sockaddr_at local_satalk, gsat;
 	struct sk_buff *skb;
-	struct device *dev;
+	struct net_device *dev;
 	struct ddpehdr *ddp;
 	int size;
 	struct atalk_route *rt;
diff -u --recursive --new-file v2.3.13/linux/net/ax25/af_ax25.c linux/net/ax25/af_ax25.c
--- v2.3.13/linux/net/ax25/af_ax25.c	Thu Jul  8 15:42:21 1999
+++ linux/net/ax25/af_ax25.c	Wed Aug 18 11:38:48 1999
@@ -188,7 +188,7 @@
 /*
  *	Kill all bound sockets on a dropped device.
  */
-static void ax25_kill_by_device(struct device *dev)
+static void ax25_kill_by_device(struct net_device *dev)
 {
 	ax25_dev *ax25_dev;
 	ax25_cb *s;
@@ -209,7 +209,7 @@
  */
 static int ax25_device_event(struct notifier_block *this,unsigned long event, void *ptr)
 {
-	struct device *dev = (struct device *)ptr;
+	struct net_device *dev = (struct net_device *)ptr;
 
 	/* Reject non AX.25 devices */
 	if (dev->type != ARPHRD_AX25)
@@ -251,7 +251,7 @@
  *	Find a socket that wants to accept the SABM we have just
  *	received.
  */
-struct sock *ax25_find_listener(ax25_address *addr, int digi, struct device *dev, int type)
+struct sock *ax25_find_listener(ax25_address *addr, int digi, struct net_device *dev, int type)
 {
 	unsigned long flags;
 	ax25_cb *s;
@@ -302,7 +302,7 @@
  *	Find an AX.25 control block given both ends. It will only pick up
  *	floating AX.25 control blocks or non Raw socket bound control blocks.
  */
-ax25_cb *ax25_find_cb(ax25_address *src_addr, ax25_address *dest_addr, ax25_digi *digi, struct device *dev)
+ax25_cb *ax25_find_cb(ax25_address *src_addr, ax25_address *dest_addr, ax25_digi *digi, struct net_device *dev)
 {
 	ax25_cb *s;
 	unsigned long flags;
diff -u --recursive --new-file v2.3.13/linux/net/ax25/ax25_dev.c linux/net/ax25/ax25_dev.c
--- v2.3.13/linux/net/ax25/ax25_dev.c	Mon Jul  7 08:19:59 1997
+++ linux/net/ax25/ax25_dev.c	Wed Aug 18 11:38:48 1999
@@ -42,7 +42,7 @@
 
 ax25_dev *ax25_dev_list = NULL;
 
-ax25_dev *ax25_dev_ax25dev(struct device *dev)
+ax25_dev *ax25_dev_ax25dev(struct net_device *dev)
 {
 	ax25_dev *ax25_dev;
 
@@ -68,7 +68,7 @@
  *	This is called when an interface is brought up. These are
  *	reasonable defaults.
  */
-void ax25_dev_device_up(struct device *dev)
+void ax25_dev_device_up(struct net_device *dev)
 {
 	ax25_dev *ax25_dev;
 	unsigned long flags;
@@ -112,7 +112,7 @@
 #endif
 }
 
-void ax25_dev_device_down(struct device *dev)
+void ax25_dev_device_down(struct net_device *dev)
 {
 	ax25_dev *s, *ax25_dev;
 	unsigned long flags;
@@ -196,7 +196,7 @@
 	return 0;
 }
 
-struct device *ax25_fwd_dev(struct device *dev)
+struct net_device *ax25_fwd_dev(struct net_device *dev)
 {
 	ax25_dev *ax25_dev;
 
diff -u --recursive --new-file v2.3.13/linux/net/ax25/ax25_iface.c linux/net/ax25/ax25_iface.c
--- v2.3.13/linux/net/ax25/ax25_iface.c	Mon Jul  7 08:19:59 1997
+++ linux/net/ax25/ax25_iface.c	Wed Aug 18 11:38:48 1999
@@ -50,7 +50,7 @@
 static struct listen_struct {
 	struct listen_struct *next;
 	ax25_address  callsign;
-	struct device *dev;
+	struct net_device *dev;
 } *listen_list = NULL;
 
 int ax25_protocol_register(unsigned int pid, int (*func)(struct sk_buff *, ax25_cb *))
@@ -168,7 +168,7 @@
 	restore_flags(flags);
 }
 
-int ax25_listen_register(ax25_address *callsign, struct device *dev)
+int ax25_listen_register(ax25_address *callsign, struct net_device *dev)
 {
 	struct listen_struct *listen;
 	unsigned long flags;
@@ -193,7 +193,7 @@
 	return 1;
 }
 
-void ax25_listen_release(ax25_address *callsign, struct device *dev)
+void ax25_listen_release(ax25_address *callsign, struct net_device *dev)
 {
 	struct listen_struct *s, *listen = listen_list;
 	unsigned long flags;
@@ -237,7 +237,7 @@
 	return NULL;
 }
 
-int ax25_listen_mine(ax25_address *callsign, struct device *dev)
+int ax25_listen_mine(ax25_address *callsign, struct net_device *dev)
 {
 	struct listen_struct *listen;
 
diff -u --recursive --new-file v2.3.13/linux/net/ax25/ax25_in.c linux/net/ax25/ax25_in.c
--- v2.3.13/linux/net/ax25/ax25_in.c	Fri Dec 18 13:56:21 1998
+++ linux/net/ax25/ax25_in.c	Wed Aug 18 11:38:48 1999
@@ -213,7 +213,7 @@
 	return queued;
 }
 
-static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_addr, struct packet_type *ptype)
+static int ax25_rcv(struct sk_buff *skb, struct net_device *dev, ax25_address *dev_addr, struct packet_type *ptype)
 {
 	struct sock *make;
 	struct sock *sk;
@@ -469,7 +469,7 @@
 /*
  *	Receive an AX.25 frame via a SLIP interface.
  */
-int ax25_kiss_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *ptype)
+int ax25_kiss_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype)
 {
 	skb->sk = NULL;		/* Initially we don't know who it's for */
 	skb->destructor = NULL;	/* Who initializes this, dammit?! */
diff -u --recursive --new-file v2.3.13/linux/net/ax25/ax25_ip.c linux/net/ax25/ax25_ip.c
--- v2.3.13/linux/net/ax25/ax25_ip.c	Fri Nov 13 10:29:43 1998
+++ linux/net/ax25/ax25_ip.c	Wed Aug 18 11:38:48 1999
@@ -55,7 +55,7 @@
 
 #ifdef CONFIG_INET
 
-int ax25_encapsulate(struct sk_buff *skb, struct device *dev, unsigned short type, void *daddr, void *saddr, unsigned len)
+int ax25_encapsulate(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len)
 {
   	/* header is an AX.25 UI frame from us to them */
  	unsigned char *buff = skb_push(skb, AX25_HEADER_LEN);
@@ -106,7 +106,7 @@
 {
 	struct sk_buff *ourskb;
 	unsigned char *bp  = skb->data;
-	struct device *dev;
+	struct net_device *dev;
 	ax25_address *src, *dst;
 	ax25_route *route;
 	ax25_dev *ax25_dev;
@@ -197,7 +197,7 @@
 
 #else	/* INET */
 
-int ax25_encapsulate(struct sk_buff *skb, struct device *dev, unsigned short type, void *daddr, void *saddr, unsigned len)
+int ax25_encapsulate(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len)
 {
 	return -AX25_HEADER_LEN;
 }
diff -u --recursive --new-file v2.3.13/linux/net/ax25/ax25_out.c linux/net/ax25/ax25_out.c
--- v2.3.13/linux/net/ax25/ax25_out.c	Fri Dec 18 13:56:21 1998
+++ linux/net/ax25/ax25_out.c	Wed Aug 18 11:38:48 1999
@@ -58,7 +58,7 @@
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 
-ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen, ax25_address *src, ax25_address *dest, ax25_digi *digi, struct device *dev)
+ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen, ax25_address *src, ax25_address *dest, ax25_digi *digi, struct net_device *dev)
 {
 	ax25_dev *ax25_dev;
 	ax25_cb *ax25;
diff -u --recursive --new-file v2.3.13/linux/net/ax25/ax25_route.c linux/net/ax25/ax25_route.c
--- v2.3.13/linux/net/ax25/ax25_route.c	Wed May 20 18:55:17 1998
+++ linux/net/ax25/ax25_route.c	Wed Aug 18 11:38:48 1999
@@ -66,7 +66,7 @@
 
 static ax25_route *ax25_route_list = NULL;
 
-static ax25_route *ax25_find_route(ax25_address *, struct device *);
+static ax25_route *ax25_find_route(ax25_address *, struct net_device *);
 
 /*
  * small macro to drop non-digipeated digipeaters and reverse path
@@ -84,7 +84,7 @@
 	ax25_digi_invert(in, out);
 }
 
-void ax25_rt_device_down(struct device *dev)
+void ax25_rt_device_down(struct net_device *dev)
 {
 	ax25_route *s, *t, *ax25_rt = ax25_route_list;
 	
@@ -300,7 +300,7 @@
 /*
  *	Find AX.25 route
  */
-static ax25_route *ax25_find_route(ax25_address *addr, struct device *dev)
+static ax25_route *ax25_find_route(ax25_address *addr, struct net_device *dev)
 {
 	ax25_route *ax25_spe_rt = NULL;
 	ax25_route *ax25_def_rt = NULL;
@@ -387,7 +387,7 @@
  *	dl1bke 960117: build digipeater path
  *	dl1bke 960301: use the default route if it exists
  */
-ax25_route *ax25_rt_find_route(ax25_address *addr, struct device *dev)
+ax25_route *ax25_rt_find_route(ax25_address *addr, struct net_device *dev)
 {
 	static ax25_route route;
 	ax25_route *ax25_rt;
diff -u --recursive --new-file v2.3.13/linux/net/ax25/ax25_subr.c linux/net/ax25/ax25_subr.c
--- v2.3.13/linux/net/ax25/ax25_subr.c	Wed Jul 22 13:45:58 1998
+++ linux/net/ax25/ax25_subr.c	Wed Aug 18 11:38:48 1999
@@ -227,7 +227,7 @@
  *
  *	Note: src here is the sender, thus it's the target of the DM
  */
-void ax25_return_dm(struct device *dev, ax25_address *src, ax25_address *dest, ax25_digi *digi)
+void ax25_return_dm(struct net_device *dev, ax25_address *src, ax25_address *dest, ax25_digi *digi)
 {
 	struct sk_buff *skb;
 	char *dptr;
diff -u --recursive --new-file v2.3.13/linux/net/bridge/br.c linux/net/bridge/br.c
--- v2.3.13/linux/net/bridge/br.c	Thu Jul  8 15:42:21 1999
+++ linux/net/bridge/br.c	Wed Aug 18 11:38:49 1999
@@ -133,12 +133,12 @@
 static int br_device_event(struct notifier_block *dnot, unsigned long event, void *ptr);
 static void br_tick(unsigned long arg);
 static int br_forward(struct sk_buff *skb, int port);	/* 3.7 */
-static int br_port_cost(struct device *dev);	/* 4.10.2 */
+static int br_port_cost(struct net_device *dev);	/* 4.10.2 */
 static void br_bpdu(struct sk_buff *skb, int port); /* consumes skb */
 static int br_cmp(unsigned int *a, unsigned int *b);
 static int send_tcn_bpdu(int port_no, Tcn_bpdu *bpdu);
 static int send_config_bpdu(int port_no, Config_bpdu *config_bpdu);
-static int find_port(struct device *dev);
+static int find_port(struct net_device *dev);
 static void br_add_local_mac(unsigned char *mac);
 static int br_flood(struct sk_buff *skb, int port);
 static int br_drop(struct sk_buff *skb);
@@ -1175,7 +1175,7 @@
 static struct sk_buff *alloc_bridge_skb(int port_no, int pdu_size, char *pdu_name)
 {
 	struct sk_buff *skb;
-	struct device *dev = port_info[port_no].dev;
+	struct net_device *dev = port_info[port_no].dev;
 	struct ethhdr *eth;
 	int size = dev->hard_header_len + BRIDGE_LLC1_HS + pdu_size;
 	unsigned char *llc_buffer;
@@ -1297,7 +1297,7 @@
 
 static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
 {
-	struct device *dev = ptr;
+	struct net_device *dev = ptr;
 	int i;
 
 	/* check for loopback devices */
@@ -1838,7 +1838,7 @@
 	return(0);
 }
 
-static int find_port(struct device *dev)
+static int find_port(struct net_device *dev)
 {
 	int i;
 
@@ -1853,7 +1853,7 @@
  *	10,100,1Gbit ethernet.
  */
  
-static int br_port_cost(struct device *dev)	/* 4.10.2 */
+static int br_port_cost(struct net_device *dev)	/* 4.10.2 */
 {
 	if (strncmp(dev->name, "lec", 3) == 0)	/* ATM Lan Emulation (LANE) */
 		return(7);                      /* 155 Mbs */
diff -u --recursive --new-file v2.3.13/linux/net/core/dev.c linux/net/core/dev.c
--- v2.3.13/linux/net/core/dev.c	Mon Aug  9 14:59:23 1999
+++ linux/net/core/dev.c	Wed Aug 18 11:38:48 1999
@@ -159,7 +159,7 @@
 struct net_fastroute_stats dev_fastroute_stat;
 #endif
 
-static void dev_clear_backlog(struct device *dev);
+static void dev_clear_backlog(struct net_device *dev);
 
 
 /******************************************************************************************
@@ -259,9 +259,9 @@
  *	Find an interface by name.
  */
  
-struct device *dev_get(const char *name)
+struct net_device *dev_get(const char *name)
 {
-	struct device *dev;
+	struct net_device *dev;
 
 	read_lock(&dev_base_lock);
 	for (dev = dev_base; dev != NULL; dev = dev->next) {
@@ -273,9 +273,9 @@
 	return dev;
 }
 
-struct device * dev_get_by_index(int ifindex)
+struct net_device * dev_get_by_index(int ifindex)
 {
-	struct device *dev;
+	struct net_device *dev;
 
 	read_lock(&dev_base_lock);
 	for (dev = dev_base; dev != NULL; dev = dev->next) {
@@ -287,9 +287,9 @@
 	return dev;
 }
 
-struct device *dev_getbyhwaddr(unsigned short type, char *ha)
+struct net_device *dev_getbyhwaddr(unsigned short type, char *ha)
 {
-	struct device *dev;
+	struct net_device *dev;
 
 	read_lock(&dev_base_lock);
 	for (dev = dev_base; dev != NULL; dev = dev->next) {
@@ -307,7 +307,7 @@
  *	id. Not efficient for many devices, not called a lot..
  */
 
-int dev_alloc_name(struct device *dev, const char *name)
+int dev_alloc_name(struct net_device *dev, const char *name)
 {
 	int i;
 	/*
@@ -322,9 +322,9 @@
 	return -ENFILE;	/* Over 100 of the things .. bail out! */
 }
 
-struct device *dev_alloc(const char *name, int *err)
+struct net_device *dev_alloc(const char *name, int *err)
 {
-	struct device *dev=kmalloc(sizeof(struct device)+16, GFP_KERNEL);
+	struct net_device *dev=kmalloc(sizeof(struct net_device)+16, GFP_KERNEL);
 	if(dev==NULL)
 	{
 		*err=-ENOBUFS;
@@ -340,7 +340,7 @@
 	return dev;
 }
 
-void netdev_state_change(struct device *dev)
+void netdev_state_change(struct net_device *dev)
 {
 	if (dev->flags&IFF_UP)
 		notifier_call_chain(&netdev_chain, NETDEV_CHANGE, dev);
@@ -376,7 +376,7 @@
  *	Prepare an interface for use. 
  */
  
-int dev_open(struct device *dev)
+int dev_open(struct net_device *dev)
 {
 	int ret = 0;
 
@@ -434,7 +434,7 @@
 
 #ifdef CONFIG_NET_FASTROUTE
 
-static __inline__ void dev_do_clear_fastroute(struct device *dev)
+static __inline__ void dev_do_clear_fastroute(struct net_device *dev)
 {
 	if (dev->accept_fastpath) {
 		int i;
@@ -444,7 +444,7 @@
 	}
 }
 
-void dev_clear_fastroute(struct device *dev)
+void dev_clear_fastroute(struct net_device *dev)
 {
 	if (dev) {
 		dev_do_clear_fastroute(dev);
@@ -461,7 +461,7 @@
  *	Completely shutdown an interface.
  */
  
-int dev_close(struct device *dev)
+int dev_close(struct net_device *dev)
 {
 	if (!(dev->flags&IFF_UP))
 		return 0;
@@ -520,7 +520,7 @@
  *	taps currently in use.
  */
 
-void dev_queue_xmit_nit(struct sk_buff *skb, struct device *dev)
+void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct packet_type *ptype;
 	get_fast_time(&skb->stamp);
@@ -590,7 +590,7 @@
 
 int dev_queue_xmit(struct sk_buff *skb)
 {
-	struct device *dev = skb->dev;
+	struct net_device *dev = skb->dev;
 	struct Qdisc  *q;
 
 	/* Grab device queue */
@@ -667,11 +667,11 @@
 
 static struct
 {
-	void (*stimul)(struct device *);
-	struct device *dev;
+	void (*stimul)(struct net_device *);
+	struct net_device *dev;
 } netdev_fc_slots[32];
 
-int netdev_register_fc(struct device *dev, void (*stimul)(struct device *dev))
+int netdev_register_fc(struct net_device *dev, void (*stimul)(struct net_device *dev))
 {
 	int bit = 0;
 	unsigned long flags;
@@ -722,7 +722,7 @@
 }
 #endif
 
-static void dev_clear_backlog(struct device *dev)
+static void dev_clear_backlog(struct net_device *dev)
 {
 	struct sk_buff *prev, *curr;
 
@@ -1041,7 +1041,7 @@
 
 static int dev_ifname(struct ifreq *arg)
 {
-	struct device *dev;
+	struct net_device *dev;
 	struct ifreq ifr;
 	int err;
 
@@ -1072,7 +1072,7 @@
 static int dev_ifconf(char *arg)
 {
 	struct ifconf ifc;
-	struct device *dev;
+	struct net_device *dev;
 	char *pos;
 	int len;
 	int total;
@@ -1142,7 +1142,7 @@
  */
 
 #ifdef CONFIG_PROC_FS
-static int sprintf_stats(char *buffer, struct device *dev)
+static int sprintf_stats(char *buffer, struct net_device *dev)
 {
 	struct net_device_stats *stats = (dev->get_stats ? dev->get_stats(dev): NULL);
 	int size;
@@ -1181,7 +1181,7 @@
 	off_t pos=0;
 	int size;
 	
-	struct device *dev;
+	struct net_device *dev;
 
 
 	size = sprintf(buffer, 
@@ -1258,7 +1258,7 @@
  * Print one entry of /proc/net/wireless
  * This is a clone of /proc/net/dev (just above)
  */
-static int sprintf_wireless_stats(char *buffer, struct device *dev)
+static int sprintf_wireless_stats(char *buffer, struct net_device *dev)
 {
 	/* Get stats from the driver */
 	struct iw_statistics *stats = (dev->get_wireless_stats ?
@@ -1298,7 +1298,7 @@
 	off_t		pos = 0;
 	int		size;
 	
-	struct device *	dev;
+	struct net_device *	dev;
 
 	size = sprintf(buffer,
 		       "Inter-|sta|  Quality       |  Discarded packets\n"
@@ -1332,7 +1332,7 @@
 #endif	/* CONFIG_PROC_FS */
 #endif	/* CONFIG_NET_RADIO */
 
-void dev_set_promiscuity(struct device *dev, int inc)
+void dev_set_promiscuity(struct net_device *dev, int inc)
 {
 	unsigned short old_flags = dev->flags;
 
@@ -1353,7 +1353,7 @@
 	}
 }
 
-void dev_set_allmulti(struct device *dev, int inc)
+void dev_set_allmulti(struct net_device *dev, int inc)
 {
 	unsigned short old_flags = dev->flags;
 
@@ -1364,7 +1364,7 @@
 		dev_mc_upload(dev);
 }
 
-int dev_change_flags(struct device *dev, unsigned flags)
+int dev_change_flags(struct net_device *dev, unsigned flags)
 {
 	int ret;
 	int old_flags = dev->flags;
@@ -1428,7 +1428,7 @@
  
 static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd)
 {
-	struct device *dev;
+	struct net_device *dev;
 	int err;
 
 	if ((dev = dev_get(ifr->ifr_name)) == NULL)
@@ -1724,9 +1724,9 @@
 static int dev_boot_phase = 1;
 
 
-int register_netdevice(struct device *dev)
+int register_netdevice(struct net_device *dev)
 {
-	struct device *d, **dp;
+	struct net_device *d, **dp;
 
 	spin_lock_init(&dev->queue_lock);
 	spin_lock_init(&dev->xmit_lock);
@@ -1787,9 +1787,9 @@
 	return 0;
 }
 
-int unregister_netdevice(struct device *dev)
+int unregister_netdevice(struct net_device *dev)
 {
-	struct device *d, **dp;
+	struct net_device *d, **dp;
 
 	/* If device is running, close it first. */
 	if (dev->flags & IFF_UP)
@@ -1886,7 +1886,7 @@
 
 __initfunc(int net_dev_init(void))
 {
-	struct device *dev, **dp;
+	struct net_device *dev, **dp;
 
 #ifdef CONFIG_NET_SCHED
 	pktsched_init();
diff -u --recursive --new-file v2.3.13/linux/net/core/dev_mcast.c linux/net/core/dev_mcast.c
--- v2.3.13/linux/net/core/dev_mcast.c	Wed Jun  9 14:45:36 1999
+++ linux/net/core/dev_mcast.c	Wed Aug 18 11:38:48 1999
@@ -68,7 +68,7 @@
  *	Update the multicast list into the physical NIC controller.
  */
  
-void dev_mc_upload(struct device *dev)
+void dev_mc_upload(struct net_device *dev)
 {
 	/* Don't do anything till we up the interface
 	   [dev_open will call this function so the list will
@@ -97,7 +97,7 @@
  *	Delete a device level multicast
  */
  
-int dev_mc_delete(struct device *dev, void *addr, int alen, int glbl)
+int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl)
 {
 	int err = 0;
 	struct dev_mc_list *dmi, **dmip;
@@ -144,7 +144,7 @@
  *	Add a device level multicast
  */
  
-int dev_mc_add(struct device *dev, void *addr, int alen, int glbl)
+int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl)
 {
 	int err = 0;
 	struct dev_mc_list *dmi, *dmi1;
@@ -194,7 +194,7 @@
  *	Discard multicast list when a device is downed
  */
 
-void dev_mc_discard(struct device *dev)
+void dev_mc_discard(struct net_device *dev)
 {
 	write_lock_bh(&dev_mc_lock);
 	while (dev->mc_list!=NULL) {
@@ -215,7 +215,7 @@
 	off_t pos=0, begin=0;
 	struct dev_mc_list *m;
 	int len=0;
-	struct device *dev;
+	struct net_device *dev;
 
 	read_lock(&dev_base_lock);
 	for (dev = dev_base; dev; dev = dev->next) {
diff -u --recursive --new-file v2.3.13/linux/net/core/dst.c linux/net/core/dst.c
--- v2.3.13/linux/net/core/dst.c	Wed Jun  9 14:45:36 1999
+++ linux/net/core/dst.c	Wed Aug 18 11:38:48 1999
@@ -164,7 +164,7 @@
 
 static int dst_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
-	struct device *dev = ptr;
+	struct net_device *dev = ptr;
 	struct dst_entry *dst;
 
 	switch (event) {
diff -u --recursive --new-file v2.3.13/linux/net/core/firewall.c linux/net/core/firewall.c
--- v2.3.13/linux/net/core/firewall.c	Wed May 12 08:31:44 1999
+++ linux/net/core/firewall.c	Wed Aug 18 11:38:48 1999
@@ -99,7 +99,7 @@
 	return -ENOENT;
 }
 
-int call_fw_firewall(int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **skb)
+int call_fw_firewall(int pf, struct net_device *dev, void *phdr, void *arg, struct sk_buff **skb)
 {
 	struct firewall_ops *fw=firewall_chain[pf];
 
@@ -117,7 +117,7 @@
  *	Actual invocation of the chains
  */
 
-int call_in_firewall(int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **skb)
+int call_in_firewall(int pf, struct net_device *dev, void *phdr, void *arg, struct sk_buff **skb)
 {
 	struct firewall_ops *fw=firewall_chain[pf];
 
@@ -131,7 +131,7 @@
 	return firewall_policy[pf];
 }
 
-int call_out_firewall(int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **skb)
+int call_out_firewall(int pf, struct net_device *dev, void *phdr, void *arg, struct sk_buff **skb)
 {
 	struct firewall_ops *fw=firewall_chain[pf];
 
diff -u --recursive --new-file v2.3.13/linux/net/core/neighbour.c linux/net/core/neighbour.c
--- v2.3.13/linux/net/core/neighbour.c	Wed Jun  9 14:45:36 1999
+++ linux/net/core/neighbour.c	Wed Aug 18 11:38:48 1999
@@ -49,7 +49,7 @@
 #ifdef CONFIG_ARPD
 static void neigh_app_notify(struct neighbour *n);
 #endif
-static int pneigh_ifdown(struct neigh_table *tbl, struct device *dev);
+static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
 
 static int neigh_glbl_allocs;
 static struct neigh_table *neigh_tables;
@@ -156,7 +156,7 @@
 	return shrunk;
 }
 
-int neigh_ifdown(struct neigh_table *tbl, struct device *dev)
+int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
 {
 	int i;
 
@@ -244,7 +244,7 @@
 }
 
 struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
-			       struct device *dev)
+			       struct net_device *dev)
 {
 	struct neighbour *n;
 	u32 hash_val;
@@ -269,7 +269,7 @@
 }
 
 struct neighbour * neigh_create(struct neigh_table *tbl, const void *pkey,
-				struct device *dev)
+				struct net_device *dev)
 {
 	struct neighbour *n, *n1;
 	u32 hash_val;
@@ -324,7 +324,7 @@
 }
 
 struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, const void *pkey,
-				    struct device *dev, int creat)
+				    struct net_device *dev, int creat)
 {
 	struct pneigh_entry *n;
 	u32 hash_val;
@@ -362,7 +362,7 @@
 }
 
 
-int pneigh_delete(struct neigh_table *tbl, const void *pkey, struct device *dev)
+int pneigh_delete(struct neigh_table *tbl, const void *pkey, struct net_device *dev)
 {
 	struct pneigh_entry *n, **np;
 	u32 hash_val;
@@ -387,7 +387,7 @@
 	return -ENOENT;
 }
 
-static int pneigh_ifdown(struct neigh_table *tbl, struct device *dev)
+static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
 {
 	struct pneigh_entry *n, **np;
 	u32 h;
@@ -724,7 +724,7 @@
 static __inline__ void neigh_update_hhs(struct neighbour *neigh)
 {
 	struct hh_cache *hh;
-	void (*update)(struct hh_cache*, struct device*, unsigned char*) =
+	void (*update)(struct hh_cache*, struct net_device*, unsigned char*) =
 		neigh->dev->header_cache_update;
 
 	if (update) {
@@ -752,7 +752,7 @@
 	u8 old;
 	int err;
 	int notify = 0;
-	struct device *dev = neigh->dev;
+	struct net_device *dev = neigh->dev;
 
 	write_lock_bh(&neigh->lock);
 	old = neigh->nud_state;
@@ -858,7 +858,7 @@
 
 struct neighbour * neigh_event_ns(struct neigh_table *tbl,
 				  u8 *lladdr, void *saddr,
-				  struct device *dev)
+				  struct net_device *dev)
 {
 	struct neighbour *neigh;
 
@@ -871,7 +871,7 @@
 static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst, u16 protocol)
 {
 	struct hh_cache	*hh = NULL;
-	struct device *dev = dst->dev;
+	struct net_device *dev = dst->dev;
 
 	for (hh=n->hh; hh; hh = hh->hh_next)
 		if (hh->hh_type == protocol)
@@ -908,7 +908,7 @@
 
 int neigh_compat_output(struct sk_buff *skb)
 {
-	struct device *dev = skb->dev;
+	struct net_device *dev = skb->dev;
 
 	__skb_pull(skb, skb->nh.raw - skb->data);
 
@@ -934,7 +934,7 @@
 
 	if (neigh_event_send(neigh, skb) == 0) {
 		int err;
-		struct device *dev = neigh->dev;
+		struct net_device *dev = neigh->dev;
 		if (dev->hard_header_cache && dst->hh == NULL) {
 			write_lock_bh(&neigh->lock);
 			if (dst->hh == NULL)
@@ -966,7 +966,7 @@
 	int err;
 	struct dst_entry *dst = skb->dst;
 	struct neighbour *neigh = dst->neighbour;
-	struct device *dev = neigh->dev;
+	struct net_device *dev = neigh->dev;
 
 	__skb_pull(skb, skb->nh.raw - skb->data);
 
@@ -1032,7 +1032,7 @@
 }
 
 
-struct neigh_parms *neigh_parms_alloc(struct device *dev, struct neigh_table *tbl)
+struct neigh_parms *neigh_parms_alloc(struct net_device *dev, struct neigh_table *tbl)
 {
 	struct neigh_parms *p;
 	p = kmalloc(sizeof(*p), GFP_KERNEL);
@@ -1135,7 +1135,7 @@
 	struct ndmsg *ndm = NLMSG_DATA(nlh);
 	struct rtattr **nda = arg;
 	struct neigh_table *tbl;
-	struct device *dev = NULL;
+	struct net_device *dev = NULL;
 
 	if (ndm->ndm_ifindex) {
 		if ((dev = dev_get_by_index(ndm->ndm_ifindex)) == NULL)
@@ -1178,7 +1178,7 @@
 	struct ndmsg *ndm = NLMSG_DATA(nlh);
 	struct rtattr **nda = arg;
 	struct neigh_table *tbl;
-	struct device *dev = NULL;
+	struct net_device *dev = NULL;
 
 	if (ndm->ndm_ifindex) {
 		if ((dev = dev_get_by_index(ndm->ndm_ifindex)) == NULL)
@@ -1443,7 +1443,7 @@
 	{{CTL_NET, "net", NULL, 0, 0555, NULL},{0}}
 };
 
-int neigh_sysctl_register(struct device *dev, struct neigh_parms *p,
+int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
 			  int p_id, int pdev_id, char *p_name)
 {
 	struct neigh_sysctl_table *t;
diff -u --recursive --new-file v2.3.13/linux/net/core/profile.c linux/net/core/profile.c
--- v2.3.13/linux/net/core/profile.c	Fri Jul 10 14:01:13 1998
+++ linux/net/core/profile.c	Wed Aug 18 11:38:48 1999
@@ -144,7 +144,7 @@
 struct iphdr whitehole_iph;
 int whitehole_count;
 
-static int whitehole_xmit(struct sk_buff *skb, struct device *dev)
+static int whitehole_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct net_device_stats *stats;
 	dev_kfree_skb(skb);
@@ -156,15 +156,15 @@
 }
 
 static void whitehole_inject(unsigned long);
-int whitehole_init(struct device *dev);
+int whitehole_init(struct net_device *dev);
 
 static struct timer_list whitehole_timer =
 	{ NULL, NULL, 0, 0L, whitehole_inject };
 
-static struct device whitehole_dev = {
+static struct net_device whitehole_dev = {
 	"whitehole", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, whitehole_init, };
 
-static int whitehole_open(struct device *dev)
+static int whitehole_open(struct net_device *dev)
 {
 	whitehole_count = 100000;
 	whitehole_timer.expires = jiffies + 5*HZ;
@@ -172,7 +172,7 @@
 	return 0;
 }
 
-static int whitehole_close(struct device *dev)
+static int whitehole_close(struct net_device *dev)
 {
 	del_timer(&whitehole_timer);
 	return 0;
@@ -206,13 +206,13 @@
 	}
 }
 
-static struct net_device_stats *whitehole_get_stats(struct device *dev)
+static struct net_device_stats *whitehole_get_stats(struct net_device *dev)
 {
 	struct net_device_stats *stats = (struct net_device_stats *) dev->priv;
 	return stats;
 }
 
-__initfunc(int whitehole_init(struct device *dev))
+__initfunc(int whitehole_init(struct net_device *dev))
 {
 	dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
 	if (dev->priv == NULL)
diff -u --recursive --new-file v2.3.13/linux/net/core/rtnetlink.c linux/net/core/rtnetlink.c
--- v2.3.13/linux/net/core/rtnetlink.c	Wed Jun  9 14:45:36 1999
+++ linux/net/core/rtnetlink.c	Wed Aug 18 11:38:48 1999
@@ -136,7 +136,7 @@
 	return err;
 }
 
-static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct device *dev,
+static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
 				 int type, u32 pid, u32 seq)
 {
 	struct ifinfomsg *r;
@@ -185,7 +185,7 @@
 {
 	int idx;
 	int s_idx = cb->args[0];
-	struct device *dev;
+	struct net_device *dev;
 
 	read_lock(&dev_base_lock);
 	for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
@@ -224,7 +224,7 @@
 	return skb->len;
 }
 
-void rtmsg_ifinfo(int type, struct device *dev)
+void rtmsg_ifinfo(int type, struct net_device *dev)
 {
 	struct sk_buff *skb;
 	int size = NLMSG_GOODSIZE;
@@ -464,7 +464,7 @@
 
 static int rtnetlink_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
-	struct device *dev = ptr;
+	struct net_device *dev = ptr;
 	switch (event) {
 	case NETDEV_UNREGISTER:
 		rtmsg_ifinfo(RTM_DELLINK, dev);
diff -u --recursive --new-file v2.3.13/linux/net/core/sock.c linux/net/core/sock.c
--- v2.3.13/linux/net/core/sock.c	Wed May 26 18:14:37 1999
+++ linux/net/core/sock.c	Wed Aug 18 11:38:48 1999
@@ -318,7 +318,7 @@
 				if (devname[0] == '\0') {
 					sk->bound_dev_if = 0;
 				} else {
-					struct device *dev = dev_get(devname);
+					struct net_device *dev = dev_get(devname);
 					if (!dev)
 						return -EINVAL;
 					sk->bound_dev_if = dev->ifindex;
diff -u --recursive --new-file v2.3.13/linux/net/decnet/af_decnet.c linux/net/decnet/af_decnet.c
--- v2.3.13/linux/net/decnet/af_decnet.c	Sat May 29 11:09:54 1999
+++ linux/net/decnet/af_decnet.c	Wed Aug 18 11:38:49 1999
@@ -1954,7 +1954,7 @@
 static int dn_device_event(struct notifier_block *this, unsigned long event,
 			void *ptr)
 {
-	struct device *dev = (struct device *)ptr;
+	struct net_device *dev = (struct net_device *)ptr;
 
 	switch(event) {
 		case NETDEV_UP:
@@ -1975,7 +1975,7 @@
 	0
 };
 
-extern int dn_route_rcv(struct sk_buff *, struct device *, struct packet_type *);
+extern int dn_route_rcv(struct sk_buff *, struct net_device *, struct packet_type *);
 
 static struct packet_type dn_dix_packet_type = 
 {
diff -u --recursive --new-file v2.3.13/linux/net/decnet/dn_dev.c linux/net/decnet/dn_dev.c
--- v2.3.13/linux/net/decnet/dn_dev.c	Tue Jun  1 10:07:39 1999
+++ linux/net/decnet/dn_dev.c	Wed Aug 18 11:38:49 1999
@@ -49,17 +49,17 @@
 
 extern struct neigh_table dn_neigh_table;
 
-struct device *decnet_default_device = NULL;
+struct net_device *decnet_default_device = NULL;
 
-static struct dn_dev *dn_dev_create(struct device *dev, int *err);
-static void dn_dev_delete(struct device *dev);
+static struct dn_dev *dn_dev_create(struct net_device *dev, int *err);
+static void dn_dev_delete(struct net_device *dev);
 #ifdef CONFIG_RTNETLINK
 static void rtmsg_ifa(int event, struct dn_ifaddr *ifa);
 #endif
 
-static int dn_eth_up(struct device *);
-static void dn_send_brd_hello(struct device *dev);
-static void dn_send_ptp_hello(struct device *dev);
+static int dn_eth_up(struct net_device *);
+static void dn_send_brd_hello(struct net_device *dev);
+static void dn_send_ptp_hello(struct net_device *dev);
 static int dn_dev_eth_setsrc(struct sk_buff *skb);
 static int dn_dev_lo_setsrc(struct sk_buff *skb);
 static int dn_dev_ptp_setsrc(struct sk_buff *skb);
@@ -257,7 +257,7 @@
 	{{CTL_NET, "net", NULL, 0, 0555, dn_dev_sysctl.dn_dev_proto_dir}, {0}}
 };
 
-static void dn_dev_sysctl_register(struct device *dev, struct dn_dev_parms *parms)
+static void dn_dev_sysctl_register(struct net_device *dev, struct dn_dev_parms *parms)
 {
 	struct dn_dev_sysctl_table *t;
 	int i;
@@ -361,7 +361,7 @@
 	return 0;
 }
 
-static int dn_dev_set_ifa(struct device *dev, struct dn_ifaddr *ifa)
+static int dn_dev_set_ifa(struct net_device *dev, struct dn_ifaddr *ifa)
 {
 	struct dn_dev *dn_db = dev->dn_ptr;
 
@@ -382,7 +382,7 @@
 
 static struct dn_dev *dn_dev_by_index(int ifindex)
 {
-	struct device *dev;
+	struct net_device *dev;
 	dev = dev_get_by_index(ifindex);
 	if (dev)
 		return dev->dn_ptr;
@@ -397,7 +397,7 @@
 	struct ifreq *ifr = (struct ifreq *)buffer;
 	struct sockaddr_dn *sdn = (struct sockaddr_dn *)&ifr->ifr_addr;
 	struct dn_dev *dn_db;
-	struct device *dev;
+	struct net_device *dev;
 	struct dn_ifaddr *ifa = NULL, **ifap = NULL;
 	int exclusive = 0;
 	int ret = 0;
@@ -503,7 +503,7 @@
 static int dn_dev_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 {
 	struct rtattr **rta = arg;
-	struct device *dev;
+	struct net_device *dev;
 	struct dn_dev *dn_db;
 	struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
 	struct dn_ifaddr *ifa;
@@ -581,7 +581,7 @@
 	netlink_broadcast(rtnl, skb, 0, RTMGRP_DECnet_IFADDR, GFP_KERNEL);
 }
 
-static int dn_dev_fill_ifinfo(struct sk_buff *skb, struct device *dev,
+static int dn_dev_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
 				int type, u32 pid, u32 seq)
 {
 	struct ifinfomsg *r;
@@ -618,7 +618,7 @@
 {
 	int idx, dn_idx;
 	int s_idx, s_dn_idx;
-	struct device *dev;
+	struct net_device *dev;
 	struct dn_dev *dn_db;
 	struct dn_ifaddr *ifa;
 
@@ -651,7 +651,7 @@
 {
 	int idx;
 	int s_idx = cb->args[0];
-	struct device *dev;
+	struct net_device *dev;
 
 	for(dev=dev_base, idx=0; dev; dev = dev->next) {
 		if (!dev->dn_ptr)
@@ -667,7 +667,7 @@
 	return skb->len;
 }
 
-static void dn_dev_ifinfo(int type, struct device *dev)
+static void dn_dev_ifinfo(int type, struct net_device *dev)
 {
 	struct sk_buff *skb;
 	int size = NLMSG_GOODSIZE;
@@ -686,7 +686,7 @@
 }
 #endif /* CONFIG_RTNETLINK */
 
-static void dn_send_endnode_hello(struct device *dev)
+static void dn_send_endnode_hello(struct net_device *dev)
 {
         struct endnode_hello_message *msg;
         struct sk_buff *skb = NULL;
@@ -760,7 +760,7 @@
 	return 0;
 }
 
-static void dn_send_router_hello(struct device *dev)
+static void dn_send_router_hello(struct net_device *dev)
 {
 	int n;
 	struct dn_dev *dn_db = dev->dn_ptr;
@@ -838,7 +838,7 @@
 		kfree_skb(skb);
 }
 
-static void dn_send_brd_hello(struct device *dev)
+static void dn_send_brd_hello(struct net_device *dev)
 {
 	if (decnet_node_type == DN_RT_INFO_ENDN)
 		dn_send_endnode_hello(dev);
@@ -846,13 +846,13 @@
 		dn_send_router_hello(dev);
 }
 #else
-static void dn_send_brd_hello(struct device *dev)
+static void dn_send_brd_hello(struct net_device *dev)
 {
 	dn_send_endnode_hello(dev);
 }
 #endif
 
-static void dn_send_ptp_hello(struct device *dev)
+static void dn_send_ptp_hello(struct net_device *dev)
 {
 	int tdlen = 16;
 	int size = dev->hard_header_len + 2 + 4 + tdlen;
@@ -897,7 +897,7 @@
 	dn_send_skb(skb);
 }
 
-static int dn_eth_up(struct device *dev)
+static int dn_eth_up(struct net_device *dev)
 {
 	struct dn_dev *dn_db = dev->dn_ptr;
 
@@ -947,7 +947,7 @@
 
 static int dn_dev_ptp_setsrc(struct sk_buff *skb)
 {
-	struct device *dev = skb->dev;
+	struct net_device *dev = skb->dev;
 	struct dn_dev *dn_db = dev->dn_ptr;
 	struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
 
@@ -959,11 +959,11 @@
 	return 0;
 }
 
-static void dn_dev_set_timer(struct device *dev);
+static void dn_dev_set_timer(struct net_device *dev);
 
 static void dn_dev_timer_func(unsigned long arg)
 {
-	struct device *dev = (struct device *)arg;
+	struct net_device *dev = (struct net_device *)arg;
 	struct dn_dev *dn_db = dev->dn_ptr;
 
 #ifdef CONFIG_DECNET_ROUTER
@@ -989,7 +989,7 @@
 	dn_dev_set_timer(dev);
 }
 
-static void dn_dev_set_timer(struct device *dev)
+static void dn_dev_set_timer(struct net_device *dev)
 {
 	struct dn_dev *dn_db = dev->dn_ptr;
 
@@ -1008,7 +1008,7 @@
 	add_timer(&dn_db->timer);
 }
 
-struct dn_dev *dn_dev_create(struct device *dev, int *err)
+struct dn_dev *dn_dev_create(struct net_device *dev, int *err)
 {
 	int i;
 	struct dn_dev_parms *p = dn_dev_list;
@@ -1066,7 +1066,7 @@
  * MAC addreses automatically. Others must be started
  * specifically.
  */
-void dn_dev_up(struct device *dev)
+void dn_dev_up(struct net_device *dev)
 {
 	struct dn_ifaddr *ifa;
 
@@ -1088,7 +1088,7 @@
 	dn_dev_set_ifa(dev, ifa);
 }
 
-static void dn_dev_delete(struct device *dev)
+static void dn_dev_delete(struct net_device *dev)
 {
 	struct dn_dev *dn_db = dev->dn_ptr;
 	unsigned long cpuflags;
@@ -1127,7 +1127,7 @@
 	kfree(dn_db);
 }
 
-void dn_dev_down(struct device *dev)
+void dn_dev_down(struct net_device *dev)
 {
 	struct dn_dev *dn_db = dev->dn_ptr;
 	struct dn_ifaddr *ifa;
@@ -1160,7 +1160,7 @@
 
 void dn_dev_devices_off(void)
 {
-	struct device *dev;
+	struct net_device *dev;
 
 	for(dev = dev_base; dev; dev = dev->next)
 		dn_dev_down(dev);
@@ -1169,7 +1169,7 @@
 
 void dn_dev_devices_on(void)
 {
-	struct device *dev;
+	struct net_device *dev;
 
 	for(dev = dev_base; dev; dev = dev->next) {
 		if (dev->flags & IFF_UP)
@@ -1185,7 +1185,7 @@
  * it as a compile time option. Probably you should use the
  * rtnetlink interface instead.
  */
-int dnet_gifconf(struct device *dev, char *buf, int len)
+int dnet_gifconf(struct net_device *dev, char *buf, int len)
 {
 	struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
 	struct dn_ifaddr *ifa;
@@ -1242,7 +1242,7 @@
 static int decnet_dev_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
 {
         struct dn_dev *dn_db;
-	struct device *dev;
+	struct net_device *dev;
         int len = 0;
         off_t pos = 0;
         off_t begin = 0;
diff -u --recursive --new-file v2.3.13/linux/net/decnet/dn_fib.c linux/net/decnet/dn_fib.c
--- v2.3.13/linux/net/decnet/dn_fib.c	Thu Jul  8 15:42:21 1999
+++ linux/net/decnet/dn_fib.c	Wed Aug 18 11:38:49 1999
@@ -489,7 +489,7 @@
 	dn_address dst, gw, mask = 0xffff;
 	int ifindex;
 	struct neighbour *neigh;
-	struct device *dev;
+	struct net_device *dev;
 	unsigned char addr[ETH_ALEN];
 
 	if (r->rtm_family != AF_DECnet)
diff -u --recursive --new-file v2.3.13/linux/net/decnet/dn_neigh.c linux/net/decnet/dn_neigh.c
--- v2.3.13/linux/net/decnet/dn_neigh.c	Wed Jun  9 14:45:36 1999
+++ linux/net/decnet/dn_neigh.c	Wed Aug 18 11:38:49 1999
@@ -127,7 +127,7 @@
 
 static int dn_neigh_construct(struct neighbour *neigh)
 {
-	struct device *dev = neigh->dev;
+	struct net_device *dev = neigh->dev;
 	struct dn_neigh *dn = (struct dn_neigh *)neigh;
 	struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
 
@@ -222,7 +222,7 @@
 {
 	struct dst_entry *dst = skb->dst;
 	struct neighbour *neigh = dst->neighbour;
-	struct device *dev = neigh->dev;
+	struct net_device *dev = neigh->dev;
 	struct dn_dev *dn_db = dev->dn_ptr;
 	int headroom = dev->hard_header_len + sizeof(struct dn_long_packet) + 3;
 	unsigned char *data;
@@ -277,7 +277,7 @@
 {
 	struct dst_entry *dst = skb->dst;
 	struct neighbour *neigh = dst->neighbour;
-	struct device *dev = neigh->dev;
+	struct net_device *dev = neigh->dev;
 	int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2;
 	struct dn_short_packet *sp;
 	unsigned char *data;
@@ -325,7 +325,7 @@
 {
 	struct dst_entry *dst = skb->dst;
 	struct neighbour *neigh = dst->neighbour;
-	struct device *dev = neigh->dev;
+	struct net_device *dev = neigh->dev;
 	int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2;
 	struct dn_short_packet *sp;
 	unsigned char *data;
@@ -507,7 +507,7 @@
 	return (*min < priority) ? (min - 6) : NULL;
 }
 
-int dn_neigh_elist(struct device *dev, unsigned char *ptr, int n)
+int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n)
 {
 	int t = 0;
 	int i;
diff -u --recursive --new-file v2.3.13/linux/net/decnet/dn_route.c linux/net/decnet/dn_route.c
--- v2.3.13/linux/net/decnet/dn_route.c	Wed May 26 09:36:36 1999
+++ linux/net/decnet/dn_route.c	Wed Aug 18 11:38:49 1999
@@ -310,7 +310,7 @@
         return 0;
 }
 
-int dn_route_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
+int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
 {
 	struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
 	unsigned char flags = 0;
@@ -459,7 +459,7 @@
 {
 	struct dst_entry *dst = skb->dst;
 	struct dn_route *rt = (struct dn_route *)dst;
-	struct device *dev = dst->dev;
+	struct net_device *dev = dst->dev;
 	struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
 	int err = -EINVAL;
 
@@ -629,7 +629,7 @@
 	struct dn_scp *scp = &sk->protinfo.dn;
 	dn_address dest = dn_saddr2dn(&scp->peer);
 	struct dn_route *rt = NULL;
-	struct device *dev  = decnet_default_device;
+	struct net_device *dev  = decnet_default_device;
 	struct neighbour *neigh = NULL;
 	struct dn_dev *dn_db;
 	unsigned char addr[6];
@@ -729,7 +729,7 @@
 {
 	struct dn_route *rt = NULL;
 	struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
-	struct device *dev = skb->dev;
+	struct net_device *dev = skb->dev;
 	struct neighbour *neigh = NULL;
 	unsigned char addr[6];
 
@@ -907,7 +907,7 @@
 		memcpy(&iif, RTA_DATA(rta[RTA_IIF-1]), sizeof(int));
 
 	if (iif) {
-		struct device *dev;
+		struct net_device *dev;
 		if ((dev = dev_get_by_index(iif)) == NULL)
 			return -ENODEV;
 		if (!dev->dn_ptr)
diff -u --recursive --new-file v2.3.13/linux/net/decnet/sysctl_net_decnet.c linux/net/decnet/sysctl_net_decnet.c
--- v2.3.13/linux/net/decnet/sysctl_net_decnet.c	Wed May 26 09:36:36 1999
+++ linux/net/decnet/sysctl_net_decnet.c	Wed Aug 18 11:38:49 1999
@@ -312,7 +312,7 @@
 				void **context)
 {
 	size_t len;
-	struct device *dev = decnet_default_device;
+	struct net_device *dev = decnet_default_device;
 	char devname[17];
 	size_t namel;
 
@@ -363,7 +363,7 @@
 				void *buffer, size_t *lenp)
 {
 	int len;
-	struct device *dev = decnet_default_device;
+	struct net_device *dev = decnet_default_device;
 	char devname[17];
 
 	if (!*lenp || (filp->f_pos && !write)) {
diff -u --recursive --new-file v2.3.13/linux/net/econet/econet.c linux/net/econet/econet.c
--- v2.3.13/linux/net/econet/econet.c	Thu Jul  8 15:42:21 1999
+++ linux/net/econet/econet.c	Wed Aug 18 11:38:49 1999
@@ -89,7 +89,7 @@
 
 struct ec_device
 {
-	struct device *dev;		/* Real device structure */
+	struct net_device *dev;		/* Real device structure */
 	unsigned char station, net;	/* Econet protocol address */
 	struct ec_device *prev, *next;	/* Linked list */
 };
@@ -102,7 +102,7 @@
  *	Faster version of edev_get - call with IRQs off
  */
 
-static __inline__ struct ec_device *__edev_get(struct device *dev)
+static __inline__ struct ec_device *__edev_get(struct net_device *dev)
 {
 	struct ec_device *edev;
 	for (edev = edevlist; edev; edev = edev->next)
@@ -117,7 +117,7 @@
  *	Find an Econet device given its `dev' pointer.  This is IRQ safe.
  */
 
-static struct ec_device *edev_get(struct device *dev)
+static struct ec_device *edev_get(struct net_device *dev)
 {
 	struct ec_device *edev;
 	unsigned long flags;
@@ -270,7 +270,7 @@
 {
 	struct sock *sk = sock->sk;
 	struct sockaddr_ec *saddr=(struct sockaddr_ec *)msg->msg_name;
-	struct device *dev;
+	struct net_device *dev;
 	struct ec_addr addr;
 	struct ec_device *edev;
 	int err;
@@ -591,7 +591,7 @@
 {
 	struct ifreq ifr;
 	struct ec_device *edev;
-	struct device *dev;
+	struct net_device *dev;
 	unsigned long flags;
 	struct sockaddr_ec *sec;
 
@@ -1030,7 +1030,7 @@
 
 static int econet_notifier(struct notifier_block *this, unsigned long msg, void *data)
 {
-	struct device *dev = (struct device *)data;
+	struct net_device *dev = (struct net_device *)data;
 	struct ec_device *edev;
 	unsigned long flags;
 
diff -u --recursive --new-file v2.3.13/linux/net/ethernet/eth.c linux/net/ethernet/eth.c
--- v2.3.13/linux/net/ethernet/eth.c	Mon Aug  9 14:59:23 1999
+++ linux/net/ethernet/eth.c	Wed Aug 18 11:38:48 1999
@@ -63,7 +63,7 @@
 static int __init eth_setup(char *str)
 {
 	int ints[5];
-	struct device *d;
+	struct net_device *d;
 
 	str = get_options(str, ARRAY_SIZE(ints), ints);
 
@@ -99,7 +99,7 @@
  *	daddr=NULL	means leave destination address (eg unresolved arp)
  */
 
-int eth_header(struct sk_buff *skb, struct device *dev, unsigned short type,
+int eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
 	   void *daddr, void *saddr, unsigned len)
 {
 	struct ethhdr *eth = (struct ethhdr *)skb_push(skb,ETH_HLEN);
@@ -155,7 +155,7 @@
 int eth_rebuild_header(struct sk_buff *skb)
 {
 	struct ethhdr *eth = (struct ethhdr *)skb->data;
-	struct device *dev = skb->dev;
+	struct net_device *dev = skb->dev;
 
 	switch (eth->h_proto)
 	{
@@ -182,7 +182,7 @@
  *	This is normal practice and works for any 'now in use' protocol.
  */
  
-unsigned short eth_type_trans(struct sk_buff *skb, struct device *dev)
+unsigned short eth_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ethhdr *eth;
 	unsigned char *rawp;
@@ -244,7 +244,7 @@
 {
 	unsigned short type = hh->hh_type;
 	struct ethhdr *eth = (struct ethhdr*)(((u8*)hh->hh_data) + 2);
-	struct device *dev = neigh->dev;
+	struct net_device *dev = neigh->dev;
 
 	if (type == __constant_htons(ETH_P_802_3))
 		return -1;
@@ -260,7 +260,7 @@
  * Called by Address Resolution module to notify changes in address.
  */
 
-void eth_header_cache_update(struct hh_cache *hh, struct device *dev, unsigned char * haddr)
+void eth_header_cache_update(struct hh_cache *hh, struct net_device *dev, unsigned char * haddr)
 {
 	memcpy(((u8*)hh->hh_data) + 2, haddr, dev->addr_len);
 }
diff -u --recursive --new-file v2.3.13/linux/net/ethernet/pe2.c linux/net/ethernet/pe2.c
--- v2.3.13/linux/net/ethernet/pe2.c	Sat May  2 14:22:29 1998
+++ linux/net/ethernet/pe2.c	Wed Aug 18 11:38:48 1999
@@ -8,7 +8,7 @@
 pEII_datalink_header(struct datalink_proto *dl, 
 		struct sk_buff *skb, unsigned char *dest_node)
 {
-	struct device	*dev = skb->dev;
+	struct net_device	*dev = skb->dev;
 
 	skb->protocol = htons (ETH_P_IPX);
 	if(dev->hard_header)
diff -u --recursive --new-file v2.3.13/linux/net/ipv4/arp.c linux/net/ipv4/arp.c
--- v2.3.13/linux/net/ipv4/arp.c	Wed Jun  9 14:45:36 1999
+++ linux/net/ipv4/arp.c	Wed Aug 18 11:38:48 1999
@@ -195,7 +195,7 @@
 	30*HZ, 128, 512, 1024,
 };
 
-int arp_mc_map(u32 addr, u8 *haddr, struct device *dev, int dir)
+int arp_mc_map(u32 addr, u8 *haddr, struct net_device *dev, int dir)
 {
 	switch (dev->type) {
 	case ARPHRD_ETHER:
@@ -217,7 +217,7 @@
 static int arp_constructor(struct neighbour *neigh)
 {
 	u32 addr = *(u32*)neigh->primary_key;
-	struct device *dev = neigh->dev;
+	struct net_device *dev = neigh->dev;
 	struct in_device *in_dev = dev->ip_ptr;
 
 	if (in_dev == NULL)
@@ -307,7 +307,7 @@
 {
 	u32 saddr;
 	u8  *dst_ha = NULL;
-	struct device *dev = neigh->dev;
+	struct net_device *dev = neigh->dev;
 	u32 target = *(u32*)neigh->primary_key;
 	int probes = atomic_read(&neigh->probes);
 
@@ -345,7 +345,7 @@
  *	is allowed to use this function, it is scheduled to be removed. --ANK
  */
 
-static int arp_set_predefined(int addr_hint, unsigned char * haddr, u32 paddr, struct device * dev)
+static int arp_set_predefined(int addr_hint, unsigned char * haddr, u32 paddr, struct net_device * dev)
 {
 	switch (addr_hint) {
 	case RTN_LOCAL:
@@ -365,7 +365,7 @@
 
 int arp_find(unsigned char *haddr, struct sk_buff *skb)
 {
-	struct device *dev = skb->dev;
+	struct net_device *dev = skb->dev;
 	u32 paddr;
 	struct neighbour *n;
 
@@ -401,7 +401,7 @@
 
 int arp_bind_neighbour(struct dst_entry *dst)
 {
-	struct device *dev = dst->dev;
+	struct net_device *dev = dst->dev;
 
 	if (dev == NULL)
 		return 0;
@@ -424,7 +424,7 @@
  */
 
 void arp_send(int type, int ptype, u32 dest_ip, 
-	      struct device *dev, u32 src_ip, 
+	      struct net_device *dev, u32 src_ip, 
 	      unsigned char *dest_hw, unsigned char *src_hw,
 	      unsigned char *target_hw)
 {
@@ -531,7 +531,7 @@
  *	Receive an arp request by the device layer.
  */
 
-int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
+int arp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
 {
 	struct arphdr *arp = skb->nh.arph;
 	unsigned char *arp_ptr= (unsigned char *)(arp+1);
@@ -744,7 +744,7 @@
  *	Set (create) an ARP cache entry.
  */
 
-int arp_req_set(struct arpreq *r, struct device * dev)
+int arp_req_set(struct arpreq *r, struct net_device * dev)
 {
 	u32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr;
 	struct neighbour *neigh;
@@ -816,7 +816,7 @@
  *	Get an ARP cache entry.
  */
 
-static int arp_req_get(struct arpreq *r, struct device *dev)
+static int arp_req_get(struct arpreq *r, struct net_device *dev)
 {
 	u32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr;
 	struct neighbour *neigh;
@@ -836,7 +836,7 @@
 	return err;
 }
 
-int arp_req_delete(struct arpreq *r, struct device * dev)
+int arp_req_delete(struct arpreq *r, struct net_device * dev)
 {
 	int err;
 	u32 ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;
@@ -887,7 +887,7 @@
 {
 	int err;
 	struct arpreq r;
-	struct device * dev = NULL;
+	struct net_device * dev = NULL;
 
 	switch(cmd) {
 		case SIOCDARP:
@@ -973,7 +973,7 @@
 		struct neighbour *n;
 		read_lock_bh(&arp_tbl.lock);
 		for (n=arp_tbl.hash_buckets[i]; n; n=n->next) {
-			struct device *dev = n->dev;
+			struct net_device *dev = n->dev;
 			int hatype = dev->type;
 
 			/* Do not confuse users "arp -a" with magic entries */
@@ -1028,7 +1028,7 @@
 	for (i=0; i<=PNEIGH_HASHMASK; i++) {
 		struct pneigh_entry *n;
 		for (n=arp_tbl.phash_buckets[i]; n; n=n->next) {
-			struct device *dev = n->dev;
+			struct net_device *dev = n->dev;
 			int hatype = dev ? dev->type : 0;
 
 			size = sprintf(buffer+len,
@@ -1067,7 +1067,7 @@
    It is necessary, that this routine was called after route cache will be
    flushed.
  */
-void arp_ifdown(struct device *dev)
+void arp_ifdown(struct net_device *dev)
 {
 	neigh_ifdown(&arp_tbl, dev);
 }
diff -u --recursive --new-file v2.3.13/linux/net/ipv4/devinet.c linux/net/ipv4/devinet.c
--- v2.3.13/linux/net/ipv4/devinet.c	Wed Jun  9 14:45:36 1999
+++ linux/net/ipv4/devinet.c	Wed Aug 18 11:38:48 1999
@@ -96,7 +96,7 @@
 	inet_ifa_count--;
 }
 
-struct in_device *inetdev_init(struct device *dev)
+struct in_device *inetdev_init(struct net_device *dev)
 {
 	struct in_device *in_dev;
 
@@ -254,7 +254,7 @@
 }
 
 static int
-inet_set_ifa(struct device *dev, struct in_ifaddr *ifa)
+inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa)
 {
 	struct in_device *in_dev = dev->ip_ptr;
 
@@ -273,7 +273,7 @@
 
 struct in_device *inetdev_by_index(int ifindex)
 {
-	struct device *dev;
+	struct net_device *dev;
 	dev = dev_get_by_index(ifindex);
 	if (dev)
 		return dev->ip_ptr;
@@ -324,7 +324,7 @@
 inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 {
 	struct rtattr **rta = arg;
-	struct device *dev;
+	struct net_device *dev;
 	struct in_device *in_dev;
 	struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
 	struct in_ifaddr *ifa;
@@ -399,7 +399,7 @@
 	struct in_device *in_dev;
 	struct in_ifaddr **ifap = NULL;
 	struct in_ifaddr *ifa = NULL;
-	struct device *dev;
+	struct net_device *dev;
 #ifdef CONFIG_IP_ALIAS
 	char *colon;
 #endif
@@ -603,7 +603,7 @@
 }
 
 static int
-inet_gifconf(struct device *dev, char *buf, int len)
+inet_gifconf(struct net_device *dev, char *buf, int len)
 {
 	struct in_device *in_dev = dev->ip_ptr;
 	struct in_ifaddr *ifa;
@@ -636,7 +636,7 @@
 	return done;
 }
 
-u32 inet_select_addr(const struct device *dev, u32 dst, int scope)
+u32 inet_select_addr(const struct net_device *dev, u32 dst, int scope)
 {
 	u32 addr = 0;
 	const struct in_device *in_dev = dev->ip_ptr;
@@ -692,7 +692,7 @@
  
 static int inetdev_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
-	struct device *dev = ptr;
+	struct net_device *dev = ptr;
 	struct in_device *in_dev = dev->ip_ptr;
 
 	if (in_dev == NULL)
@@ -786,7 +786,7 @@
 {
 	int idx, ip_idx;
 	int s_idx, s_ip_idx;
-	struct device *dev;
+	struct net_device *dev;
 	struct in_device *in_dev;
 	struct in_ifaddr *ifa;
 
@@ -879,7 +879,7 @@
 
 void inet_forward_change()
 {
-	struct device *dev;
+	struct net_device *dev;
 	int on = ipv4_devconf.forwarding;
 
 	ipv4_devconf.accept_redirects = !on;
@@ -972,7 +972,7 @@
 static void devinet_sysctl_register(struct in_device *in_dev, struct ipv4_devconf *p)
 {
 	int i;
-	struct device *dev = in_dev ? in_dev->dev : NULL;
+	struct net_device *dev = in_dev ? in_dev->dev : NULL;
 	struct devinet_sysctl_table *t;
 
 	t = kmalloc(sizeof(*t), GFP_KERNEL);
diff -u --recursive --new-file v2.3.13/linux/net/ipv4/fib_frontend.c linux/net/ipv4/fib_frontend.c
--- v2.3.13/linux/net/ipv4/fib_frontend.c	Wed Jun  9 14:45:36 1999
+++ linux/net/ipv4/fib_frontend.c	Wed Aug 18 11:38:49 1999
@@ -142,7 +142,7 @@
  *	Find the first device with a given source address.
  */
 
-struct device * ip_dev_find(u32 addr)
+struct net_device * ip_dev_find(u32 addr)
 {
 	struct rt_key key;
 	struct fib_result res;
@@ -187,7 +187,7 @@
  */
 
 int fib_validate_source(u32 src, u32 dst, u8 tos, int oif,
-			struct device *dev, u32 *spec_dst, u32 *itag)
+			struct net_device *dev, u32 *spec_dst, u32 *itag)
 {
 	struct in_device *in_dev = dev->ip_ptr;
 	struct rt_key key;
@@ -421,7 +421,7 @@
 static void fib_add_ifaddr(struct in_ifaddr *ifa)
 {
 	struct in_device *in_dev = ifa->ifa_dev;
-	struct device *dev = in_dev->dev;
+	struct net_device *dev = in_dev->dev;
 	struct in_ifaddr *prim = ifa;
 	u32 mask = ifa->ifa_mask;
 	u32 addr = ifa->ifa_local;
@@ -460,7 +460,7 @@
 static void fib_del_ifaddr(struct in_ifaddr *ifa)
 {
 	struct in_device *in_dev = ifa->ifa_dev;
-	struct device *dev = in_dev->dev;
+	struct net_device *dev = in_dev->dev;
 	struct in_ifaddr *ifa1;
 	struct in_ifaddr *prim = ifa;
 	u32 brd = ifa->ifa_address|~ifa->ifa_mask;
@@ -526,7 +526,7 @@
 #undef BRD1_OK
 }
 
-static void fib_disable_ip(struct device *dev, int force)
+static void fib_disable_ip(struct net_device *dev, int force)
 {
 	if (fib_sync_down(0, dev, force))
 		fib_flush();
@@ -560,7 +560,7 @@
 
 static int fib_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
-	struct device *dev = ptr;
+	struct net_device *dev = ptr;
 	struct in_device *in_dev = dev->ip_ptr;
 
 	if (!in_dev)
diff -u --recursive --new-file v2.3.13/linux/net/ipv4/fib_rules.c linux/net/ipv4/fib_rules.c
--- v2.3.13/linux/net/ipv4/fib_rules.c	Wed Jun  9 14:45:36 1999
+++ linux/net/ipv4/fib_rules.c	Wed Aug 18 11:38:49 1999
@@ -179,7 +179,7 @@
 		memcpy(&new_r->r_preference, RTA_DATA(rta[RTA_PRIORITY-1]), 4);
 	new_r->r_table = table_id;
 	if (rta[RTA_IIF-1]) {
-		struct device *dev;
+		struct net_device *dev;
 		memcpy(new_r->r_ifname, RTA_DATA(rta[RTA_IIF-1]), IFNAMSIZ);
 		new_r->r_ifname[IFNAMSIZ-1] = 0;
 		new_r->r_ifindex = -1;
@@ -251,7 +251,7 @@
 #endif
 
 
-static void fib_rules_detach(struct device *dev)
+static void fib_rules_detach(struct net_device *dev)
 {
 	struct fib_rule *r;
 
@@ -264,7 +264,7 @@
 	}
 }
 
-static void fib_rules_attach(struct device *dev)
+static void fib_rules_attach(struct net_device *dev)
 {
 	struct fib_rule *r;
 
@@ -349,7 +349,7 @@
 
 static int fib_rules_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
-	struct device *dev = ptr;
+	struct net_device *dev = ptr;
 
 	if (event == NETDEV_UNREGISTER)
 		fib_rules_detach(dev);
diff -u --recursive --new-file v2.3.13/linux/net/ipv4/fib_semantics.c linux/net/ipv4/fib_semantics.c
--- v2.3.13/linux/net/ipv4/fib_semantics.c	Sun Mar 21 07:22:00 1999
+++ linux/net/ipv4/fib_semantics.c	Wed Aug 18 11:38:49 1999
@@ -156,7 +156,7 @@
    Used only by redirect accept routine.
  */
 
-int ip_fib_check_default(u32 gw, struct device *dev)
+int ip_fib_check_default(u32 gw, struct net_device *dev)
 {
 	for_fib_info() {
 		if (fi->fib_flags & RTNH_F_DEAD)
@@ -331,7 +331,7 @@
 			return 0;
 #endif
 		if (nh->nh_flags&RTNH_F_ONLINK) {
-			struct device *dev;
+			struct net_device *dev;
 
 			if (r->rtm_scope >= RT_SCOPE_LINK)
 				return -EINVAL;
@@ -731,7 +731,7 @@
 #ifdef CONFIG_IP_ALIAS
 		char *colon;
 #endif
-		struct device *dev;
+		struct net_device *dev;
 		char   devname[IFNAMSIZ];
 
 		if (copy_from_user(devname, r->rt_dev, IFNAMSIZ-1))
@@ -821,7 +821,7 @@
    - device went down -> we must shutdown all nexthops going via it.
  */
 
-int fib_sync_down(u32 local, struct device *dev, int force)
+int fib_sync_down(u32 local, struct net_device *dev, int force)
 {
 	int ret = 0;
 	int scope = RT_SCOPE_NOWHERE;
@@ -865,7 +865,7 @@
    It takes sense only on multipath routes.
  */
 
-int fib_sync_up(struct device *dev)
+int fib_sync_up(struct net_device *dev)
 {
 	int ret = 0;
 
diff -u --recursive --new-file v2.3.13/linux/net/ipv4/icmp.c linux/net/ipv4/icmp.c
--- v2.3.13/linux/net/ipv4/icmp.c	Thu Jul  8 15:42:21 1999
+++ linux/net/ipv4/icmp.c	Wed Aug 18 11:38:48 1999
@@ -935,7 +935,7 @@
 static void icmp_address_reply(struct icmphdr *icmph, struct sk_buff *skb, int len)
 {
 	struct rtable *rt = (struct rtable*)skb->dst;
-	struct device *dev = skb->dev;
+	struct net_device *dev = skb->dev;
 	struct in_device *in_dev = dev->ip_ptr;
 	struct in_ifaddr *ifa;
 	u32 mask;
diff -u --recursive --new-file v2.3.13/linux/net/ipv4/igmp.c linux/net/ipv4/igmp.c
--- v2.3.13/linux/net/ipv4/igmp.c	Wed Jun  9 14:45:37 1999
+++ linux/net/ipv4/igmp.c	Wed Aug 18 11:38:48 1999
@@ -158,7 +158,7 @@
 
 #define IGMP_SIZE (sizeof(struct igmphdr)+sizeof(struct iphdr)+4)
 
-static int igmp_send_report(struct device *dev, u32 group, int type)
+static int igmp_send_report(struct net_device *dev, u32 group, int type)
 {
 	struct sk_buff *skb;
 	struct iphdr *iph;
@@ -359,7 +359,7 @@
 static void ip_mc_filter_add(struct in_device *in_dev, u32 addr)
 {
 	char buf[MAX_ADDR_LEN];
-	struct device *dev = in_dev->dev;
+	struct net_device *dev = in_dev->dev;
 
 	/* Checking for IFF_MULTICAST here is WRONG-WRONG-WRONG.
 	   We will get multicast token leakage, when IFF_MULTICAST
@@ -379,7 +379,7 @@
 static void ip_mc_filter_del(struct in_device *in_dev, u32 addr)
 {
 	char buf[MAX_ADDR_LEN];
-	struct device *dev = in_dev->dev;
+	struct net_device *dev = in_dev->dev;
 
 	if (arp_mc_map(addr, buf, dev, 0) == 0)
 		dev_mc_delete(dev,buf,dev->addr_len,0);
@@ -547,7 +547,7 @@
 static struct in_device * ip_mc_find_dev(struct ip_mreqn *imr)
 {
 	struct rtable *rt;
-	struct device *dev = NULL;
+	struct net_device *dev = NULL;
 
 	if (imr->imr_address.s_addr) {
 		dev = ip_dev_find(imr->imr_address.s_addr);
@@ -684,7 +684,7 @@
 	up(&ip_sk_mc_sem);
 }
 
-int ip_check_mc(struct device *dev, u32 mc_addr)
+int ip_check_mc(struct net_device *dev, u32 mc_addr)
 {
 	struct in_device *in_dev = dev->ip_ptr;
 	struct ip_mc_list *im;
@@ -710,7 +710,7 @@
 	off_t pos=0, begin=0;
 	struct ip_mc_list *im;
 	int len=0;
-	struct device *dev;
+	struct net_device *dev;
 
 	len=sprintf(buffer,"Idx\tDevice    : Count Querier\tGroup    Users Timer\tReporter\n");  
 
diff -u --recursive --new-file v2.3.13/linux/net/ipv4/ip_forward.c linux/net/ipv4/ip_forward.c
--- v2.3.13/linux/net/ipv4/ip_forward.c	Sun Mar 21 07:22:00 1999
+++ linux/net/ipv4/ip_forward.c	Wed Aug 18 11:38:48 1999
@@ -70,7 +70,7 @@
 
 int ip_forward(struct sk_buff *skb)
 {
-	struct device *dev2;	/* Output device */
+	struct net_device *dev2;	/* Output device */
 	struct iphdr *iph;	/* Our header */
 	struct rtable *rt;	/* Route we use */
 	struct ip_options * opt	= &(IPCB(skb)->opt);
diff -u --recursive --new-file v2.3.13/linux/net/ipv4/ip_fragment.c linux/net/ipv4/ip_fragment.c
--- v2.3.13/linux/net/ipv4/ip_fragment.c	Wed Jun 16 19:26:27 1999
+++ linux/net/ipv4/ip_fragment.c	Wed Aug 18 11:38:48 1999
@@ -66,7 +66,7 @@
 	short		ihlen;		/* length of the IP header		*/	
 	struct timer_list timer;	/* when will this queue expire?		*/
 	struct ipq	**pprev;
-	struct device	*dev;		/* Device - for icmp replies */
+	struct net_device	*dev;		/* Device - for icmp replies */
 };
 
 #define IPQ_HASHSZ	64
diff -u --recursive --new-file v2.3.13/linux/net/ipv4/ip_fw.c linux/net/ipv4/ip_fw.c
--- v2.3.13/linux/net/ipv4/ip_fw.c	Tue Jun  8 20:32:32 1999
+++ linux/net/ipv4/ip_fw.c	Wed Aug 18 11:38:48 1999
@@ -1652,14 +1652,14 @@
 /*
  *	Interface to the generic firewall chains.
  */
-int ipfw_input_check(struct firewall_ops *this, int pf, struct device *dev, 
+int ipfw_input_check(struct firewall_ops *this, int pf, struct net_device *dev, 
 		     void *phdr, void *arg, struct sk_buff **pskb)
 {
 	return ip_fw_check(phdr, dev->name,
 			   arg, IP_FW_INPUT_CHAIN, *pskb, SLOT_NUMBER(), 0);
 }
 
-int ipfw_output_check(struct firewall_ops *this, int pf, struct device *dev, 
+int ipfw_output_check(struct firewall_ops *this, int pf, struct net_device *dev, 
 		      void *phdr, void *arg, struct sk_buff **pskb)
 {
 	/* Locally generated bogus packets by root. <SIGH>. */
@@ -1670,7 +1670,7 @@
 			   arg, IP_FW_OUTPUT_CHAIN, *pskb, SLOT_NUMBER(), 0);
 }
 
-int ipfw_forward_check(struct firewall_ops *this, int pf, struct device *dev, 
+int ipfw_forward_check(struct firewall_ops *this, int pf, struct net_device *dev, 
 		       void *phdr, void *arg, struct sk_buff **pskb)
 {
 	return ip_fw_check(phdr, dev->name,
diff -u --recursive --new-file v2.3.13/linux/net/ipv4/ip_gre.c linux/net/ipv4/ip_gre.c
--- v2.3.13/linux/net/ipv4/ip_gre.c	Thu Mar 25 09:23:34 1999
+++ linux/net/ipv4/ip_gre.c	Wed Aug 18 11:38:49 1999
@@ -111,13 +111,13 @@
    Alexey Kuznetsov.
  */
 
-static int ipgre_tunnel_init(struct device *dev);
+static int ipgre_tunnel_init(struct net_device *dev);
 
 /* Fallback tunnel: no source, no destination, no key, no options */
 
-static int ipgre_fb_tunnel_init(struct device *dev);
+static int ipgre_fb_tunnel_init(struct net_device *dev);
 
-static struct device ipgre_fb_tunnel_dev = {
+static struct net_device ipgre_fb_tunnel_dev = {
 	NULL, 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, ipgre_fb_tunnel_init,
 };
 
@@ -235,7 +235,7 @@
 	u32 local = parms->iph.saddr;
 	u32 key = parms->i_key;
 	struct ip_tunnel *t, **tp, *nt;
-	struct device *dev;
+	struct net_device *dev;
 	unsigned h = HASH(key);
 	int prio = 0;
 
@@ -291,7 +291,7 @@
 	return NULL;
 }
 
-static void ipgre_tunnel_destroy(struct device *dev)
+static void ipgre_tunnel_destroy(struct net_device *dev)
 {
 	ipgre_tunnel_unlink((struct ip_tunnel*)dev->priv);
 
@@ -596,7 +596,7 @@
 	return(0);
 }
 
-static int ipgre_tunnel_xmit(struct sk_buff *skb, struct device *dev)
+static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv;
 	struct net_device_stats *stats = &tunnel->stat;
@@ -605,7 +605,7 @@
 	u8     tos;
 	u16    df;
 	struct rtable *rt;     			/* Route to the other host */
-	struct device *tdev;			/* Device to other host */
+	struct net_device *tdev;			/* Device to other host */
 	struct iphdr  *iph;			/* Our new IP header */
 	int    max_headroom;			/* The extra header space needed */
 	int    gre_hlen;
@@ -819,7 +819,7 @@
 }
 
 static int
-ipgre_tunnel_ioctl (struct device *dev, struct ifreq *ifr, int cmd)
+ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	int err = 0;
 	struct ip_tunnel_parm p;
@@ -945,12 +945,12 @@
 	return err;
 }
 
-static struct net_device_stats *ipgre_tunnel_get_stats(struct device *dev)
+static struct net_device_stats *ipgre_tunnel_get_stats(struct net_device *dev)
 {
 	return &(((struct ip_tunnel*)dev->priv)->stat);
 }
 
-static int ipgre_tunnel_change_mtu(struct device *dev, int new_mtu)
+static int ipgre_tunnel_change_mtu(struct net_device *dev, int new_mtu)
 {
 	struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv;
 	if (new_mtu < 68 || new_mtu > 0xFFF8 - tunnel->hlen)
@@ -989,7 +989,7 @@
 
  */
 
-static int ipgre_header(struct sk_buff *skb, struct device *dev, unsigned short type,
+static int ipgre_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
 			void *daddr, void *saddr, unsigned len)
 {
 	struct ip_tunnel *t = (struct ip_tunnel*)dev->priv;
@@ -1017,7 +1017,7 @@
 	return -t->hlen;
 }
 
-static int ipgre_open(struct device *dev)
+static int ipgre_open(struct net_device *dev)
 {
 	struct ip_tunnel *t = (struct ip_tunnel*)dev->priv;
 
@@ -1042,7 +1042,7 @@
 	return 0;
 }
 
-static int ipgre_close(struct device *dev)
+static int ipgre_close(struct net_device *dev)
 {
 	struct ip_tunnel *t = (struct ip_tunnel*)dev->priv;
 	if (MULTICAST(t->parms.iph.daddr) && t->mlink) {
@@ -1056,7 +1056,7 @@
 
 #endif
 
-static void ipgre_tunnel_init_gen(struct device *dev)
+static void ipgre_tunnel_init_gen(struct net_device *dev)
 {
 	struct ip_tunnel *t = (struct ip_tunnel*)dev->priv;
 
@@ -1078,9 +1078,9 @@
 	memcpy(dev->broadcast, &t->parms.iph.daddr, 4);
 }
 
-static int ipgre_tunnel_init(struct device *dev)
+static int ipgre_tunnel_init(struct net_device *dev)
 {
-	struct device *tdev = NULL;
+	struct net_device *tdev = NULL;
 	struct ip_tunnel *tunnel;
 	struct iphdr *iph;
 	int hlen = LL_MAX_HEADER;
@@ -1140,20 +1140,20 @@
 }
 
 #ifdef MODULE
-static int ipgre_fb_tunnel_open(struct device *dev)
+static int ipgre_fb_tunnel_open(struct net_device *dev)
 {
 	MOD_INC_USE_COUNT;
 	return 0;
 }
 
-static int ipgre_fb_tunnel_close(struct device *dev)
+static int ipgre_fb_tunnel_close(struct net_device *dev)
 {
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
 #endif
 
-__initfunc(int ipgre_fb_tunnel_init(struct device *dev))
+__initfunc(int ipgre_fb_tunnel_init(struct net_device *dev))
 {
 	struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv;
 	struct iphdr *iph;
diff -u --recursive --new-file v2.3.13/linux/net/ipv4/ip_input.c linux/net/ipv4/ip_input.c
--- v2.3.13/linux/net/ipv4/ip_input.c	Wed Jun  9 14:45:37 1999
+++ linux/net/ipv4/ip_input.c	Wed Aug 18 11:38:48 1999
@@ -317,7 +317,7 @@
 /*
  * 	Main IP Receive routine.
  */ 
-int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
+int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
 {
 	struct iphdr *iph = skb->nh.iph;
 #ifdef	CONFIG_FIREWALL
diff -u --recursive --new-file v2.3.13/linux/net/ipv4/ip_masq.c linux/net/ipv4/ip_masq.c
--- v2.3.13/linux/net/ipv4/ip_masq.c	Wed Jun 30 13:38:20 1999
+++ linux/net/ipv4/ip_masq.c	Wed Aug 18 11:38:49 1999
@@ -2388,7 +2388,7 @@
 /*
  *	Wrapper over inet_select_addr()
  */
-u32 ip_masq_select_addr(struct device *dev, u32 dst, int scope)
+u32 ip_masq_select_addr(struct net_device *dev, u32 dst, int scope)
 {
 	return inet_select_addr(dev, dst, scope);
 }
diff -u --recursive --new-file v2.3.13/linux/net/ipv4/ip_masq_user.c linux/net/ipv4/ip_masq_user.c
--- v2.3.13/linux/net/ipv4/ip_masq_user.c	Sun Oct  4 10:21:45 1998
+++ linux/net/ipv4/ip_masq_user.c	Wed Aug 18 11:38:49 1999
@@ -58,7 +58,7 @@
 
 static int ip_masq_user_maddr(struct ip_masq_user *ums)
 {
-	struct device *dev;
+	struct net_device *dev;
 	struct rtable *rt;
 	int ret = -EINVAL;
 	u32 rt_daddr, rt_saddr;
diff -u --recursive --new-file v2.3.13/linux/net/ipv4/ip_output.c linux/net/ipv4/ip_output.c
--- v2.3.13/linux/net/ipv4/ip_output.c	Thu Mar 25 09:23:34 1999
+++ linux/net/ipv4/ip_output.c	Wed Aug 18 11:38:48 1999
@@ -101,7 +101,7 @@
 {
 	struct rtable *rt = (struct rtable *)skb->dst;
 	struct iphdr *iph;
-	struct device *dev;
+	struct net_device *dev;
 	
 	/* Build the IP header. */
 	if (opt)
@@ -159,7 +159,7 @@
 {
 	struct sock *sk = skb->sk;
 	struct rtable *rt = (struct rtable*)skb->dst;
-	struct device *dev = rt->u.dst.dev;
+	struct net_device *dev = rt->u.dst.dev;
 
 	/*
 	 *	If the indicated interface is up and running, send the packet.
@@ -236,7 +236,7 @@
 	struct sock *sk = skb->sk;
 	struct ip_options *opt = sk->opt;
 	struct rtable *rt;
-	struct device *dev;
+	struct net_device *dev;
 	struct iphdr *iph;
 	unsigned int tot_len;
 
@@ -728,7 +728,7 @@
 	struct iphdr *iph;
 	unsigned char *raw;
 	unsigned char *ptr;
-	struct device *dev;
+	struct net_device *dev;
 	struct sk_buff *skb2;
 	unsigned int mtu, hlen, left, len; 
 	int offset;
diff -u --recursive --new-file v2.3.13/linux/net/ipv4/ip_sockglue.c linux/net/ipv4/ip_sockglue.c
--- v2.3.13/linux/net/ipv4/ip_sockglue.c	Thu Apr 22 19:45:19 1999
+++ linux/net/ipv4/ip_sockglue.c	Wed Aug 18 11:38:48 1999
@@ -515,7 +515,7 @@
 		case IP_MULTICAST_IF: 
 		{
 			struct ip_mreqn mreq;
-			struct device *dev = NULL;
+			struct net_device *dev = NULL;
 			
 			/*
 			 *	Check the arguments are allowable
diff -u --recursive --new-file v2.3.13/linux/net/ipv4/ipconfig.c linux/net/ipv4/ipconfig.c
--- v2.3.13/linux/net/ipv4/ipconfig.c	Wed Jun 30 13:38:20 1999
+++ linux/net/ipv4/ipconfig.c	Wed Aug 18 11:38:49 1999
@@ -12,6 +12,10 @@
  *  BOOTP rewritten to construct and analyse packets itself instead
  *  of misusing the IP layer. num_bugs_causing_wrong_arp_replies--;
  *					     -- MJ, December 1998
+ *  
+ *  Fixed ip_auto_config_setup calling at startup in the new "Linker Magic"
+ *  initialization scheme.
+ *	- Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 08/11/1999
  */
 
 #include <linux/config.h>
@@ -97,18 +101,18 @@
 
 struct ic_device {
 	struct ic_device *next;
-	struct device *dev;
+	struct net_device *dev;
 	unsigned short flags;
 	int able;
 };
 
 static struct ic_device *ic_first_dev __initdata = NULL;/* List of open device */
-static struct device *ic_dev __initdata = NULL;		/* Selected device */
+static struct net_device *ic_dev __initdata = NULL;		/* Selected device */
 
 static int __init ic_open_devs(void)
 {
 	struct ic_device *d, **last;
-	struct device *dev;
+	struct net_device *dev;
 	unsigned short oflags;
 
 	last = &ic_first_dev;
@@ -161,7 +165,7 @@
 static void __init ic_close_devs(void)
 {
 	struct ic_device *d, *next;
-	struct device *dev;
+	struct net_device *dev;
 
 	next = ic_first_dev;
 	while ((d = next)) {
@@ -305,7 +309,7 @@
 
 #ifdef CONFIG_IP_PNP_RARP
 
-static int ic_rarp_recv(struct sk_buff *skb, struct device *dev, struct packet_type *pt);
+static int ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt);
 
 static struct packet_type rarp_packet_type __initdata = {
 	__constant_htons(ETH_P_RARP),
@@ -329,7 +333,7 @@
  *  Process received RARP packet.
  */
 static int __init
-ic_rarp_recv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
+ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
 {
 	struct arphdr *rarp = (struct arphdr *)skb->h.raw;
 	unsigned char *rarp_ptr = (unsigned char *) (rarp + 1);
@@ -394,7 +398,7 @@
 
 	for (d=ic_first_dev; d; d=d->next)
 		if (d->able & IC_RARP) {
-			struct device *dev = d->dev;
+			struct net_device *dev = d->dev;
 			arp_send(ARPOP_RREQUEST, ETH_P_RARP, 0, dev, 0, NULL,
 				 dev->dev_addr, dev->dev_addr);
 		}
@@ -433,7 +437,7 @@
 
 static u32 ic_bootp_xid;
 
-static int ic_bootp_recv(struct sk_buff *skb, struct device *dev, struct packet_type *pt);
+static int ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt);
 
 static struct packet_type bootp_packet_type __initdata = {
 	__constant_htons(ETH_P_IP),
@@ -497,7 +501,7 @@
  */
 static void __init ic_bootp_send_if(struct ic_device *d, u32 jiffies)
 {
-	struct device *dev = d->dev;
+	struct net_device *dev = d->dev;
 	struct sk_buff *skb;
 	struct bootp_pkt *b;
 	int hh_len = (dev->hard_header_len + 15) & ~15;
@@ -616,7 +620,7 @@
 /*
  *  Receive BOOTP reply.
  */
-static int __init ic_bootp_recv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
+static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
 {
 	struct bootp_pkt *b = (struct bootp_pkt *) skb->nh.iph;
 	struct iphdr *h = &b->iph;
@@ -912,7 +916,7 @@
 	return 0;
 }
 
-void __init ip_auto_config_setup(char *addrs, int *ints)
+static int __init ip_auto_config_setup(char *addrs)
 {
 	char *cp, *ip, *dp;
 	int num = 0;
@@ -920,10 +924,10 @@
 	ic_set_manually = 1;
 	if (!strcmp(addrs, "off")) {
 		ic_enable = 0;
-		return;
+		return 1;
 	}
 	if (ic_proto_name(addrs))
-		return;
+		return 1;
 
 	/* Parse the whole string */
 	ip = addrs;
@@ -971,4 +975,14 @@
 		ip = cp;
 		num++;
 	}
+
+	return 0;
 }
+
+static int __init nfsaddrs_config_setup(char *addrs)
+{
+	return ip_auto_config_setup(addrs);
+}
+
+__setup("ip=", ip_auto_config_setup);
+__setup("nfsaddrs=", nfsaddrs_config_setup);
diff -u --recursive --new-file v2.3.13/linux/net/ipv4/ipip.c linux/net/ipv4/ipip.c
--- v2.3.13/linux/net/ipv4/ipip.c	Thu Mar 25 09:23:34 1999
+++ linux/net/ipv4/ipip.c	Wed Aug 18 11:38:48 1999
@@ -116,10 +116,10 @@
 #define HASH_SIZE  16
 #define HASH(addr) ((addr^(addr>>4))&0xF)
 
-static int ipip_fb_tunnel_init(struct device *dev);
-static int ipip_tunnel_init(struct device *dev);
+static int ipip_fb_tunnel_init(struct net_device *dev);
+static int ipip_tunnel_init(struct net_device *dev);
 
-static struct device ipip_fb_tunnel_dev = {
+static struct net_device ipip_fb_tunnel_dev = {
 	NULL, 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, ipip_fb_tunnel_init,
 };
 
@@ -203,7 +203,7 @@
 	u32 remote = parms->iph.daddr;
 	u32 local = parms->iph.saddr;
 	struct ip_tunnel *t, **tp, *nt;
-	struct device *dev;
+	struct net_device *dev;
 	unsigned h = 0;
 	int prio = 0;
 
@@ -260,7 +260,7 @@
 }
 
 
-static void ipip_tunnel_destroy(struct device *dev)
+static void ipip_tunnel_destroy(struct net_device *dev)
 {
 	if (dev == &ipip_fb_tunnel_dev) {
 		tunnels_wc[0] = NULL;
@@ -480,7 +480,7 @@
  *	and that skb is filled properly by that function.
  */
 
-static int ipip_tunnel_xmit(struct sk_buff *skb, struct device *dev)
+static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv;
 	struct net_device_stats *stats = &tunnel->stat;
@@ -488,7 +488,7 @@
 	u8     tos = tunnel->parms.iph.tos;
 	u16    df = tiph->frag_off;
 	struct rtable *rt;     			/* Route to the other host */
-	struct device *tdev;			/* Device to other host */
+	struct net_device *tdev;			/* Device to other host */
 	struct iphdr  *old_iph = skb->nh.iph;
 	struct iphdr  *iph;			/* Our new IP header */
 	int    max_headroom;			/* The extra header space needed */
@@ -616,7 +616,7 @@
 }
 
 static int
-ipip_tunnel_ioctl (struct device *dev, struct ifreq *ifr, int cmd)
+ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	int err = 0;
 	struct ip_tunnel_parm p;
@@ -727,12 +727,12 @@
 	return err;
 }
 
-static struct net_device_stats *ipip_tunnel_get_stats(struct device *dev)
+static struct net_device_stats *ipip_tunnel_get_stats(struct net_device *dev)
 {
 	return &(((struct ip_tunnel*)dev->priv)->stat);
 }
 
-static int ipip_tunnel_change_mtu(struct device *dev, int new_mtu)
+static int ipip_tunnel_change_mtu(struct net_device *dev, int new_mtu)
 {
 	if (new_mtu < 68 || new_mtu > 0xFFF8 - sizeof(struct iphdr))
 		return -EINVAL;
@@ -740,7 +740,7 @@
 	return 0;
 }
 
-static void ipip_tunnel_init_gen(struct device *dev)
+static void ipip_tunnel_init_gen(struct net_device *dev)
 {
 	struct ip_tunnel *t = (struct ip_tunnel*)dev->priv;
 
@@ -762,9 +762,9 @@
 	memcpy(dev->broadcast, &t->parms.iph.daddr, 4);
 }
 
-static int ipip_tunnel_init(struct device *dev)
+static int ipip_tunnel_init(struct net_device *dev)
 {
-	struct device *tdev = NULL;
+	struct net_device *tdev = NULL;
 	struct ip_tunnel *tunnel;
 	struct iphdr *iph;
 
@@ -795,20 +795,20 @@
 }
 
 #ifdef MODULE
-static int ipip_fb_tunnel_open(struct device *dev)
+static int ipip_fb_tunnel_open(struct net_device *dev)
 {
 	MOD_INC_USE_COUNT;
 	return 0;
 }
 
-static int ipip_fb_tunnel_close(struct device *dev)
+static int ipip_fb_tunnel_close(struct net_device *dev)
 {
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
 #endif
 
-__initfunc(int ipip_fb_tunnel_init(struct device *dev))
+__initfunc(int ipip_fb_tunnel_init(struct net_device *dev))
 {
 	struct iphdr *iph;
 
diff -u --recursive --new-file v2.3.13/linux/net/ipv4/ipmr.c linux/net/ipv4/ipmr.c
--- v2.3.13/linux/net/ipv4/ipmr.c	Wed Jun  9 14:45:37 1999
+++ linux/net/ipv4/ipmr.c	Wed Aug 18 11:38:48 1999
@@ -85,9 +85,9 @@
 extern struct inet_protocol pim_protocol;
 
 static
-struct device *ipmr_new_tunnel(struct vifctl *v)
+struct net_device *ipmr_new_tunnel(struct vifctl *v)
 {
-	struct device  *dev = NULL;
+	struct net_device  *dev = NULL;
 
 	rtnl_lock();
 	dev = dev_get("tunl0");
@@ -136,9 +136,9 @@
 #ifdef CONFIG_IP_PIMSM
 
 static int reg_vif_num = -1;
-static struct device * reg_dev;
+static struct net_device * reg_dev;
 
-static int reg_vif_xmit(struct sk_buff *skb, struct device *dev)
+static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	((struct net_device_stats*)dev->priv)->tx_bytes += skb->len;
 	((struct net_device_stats*)dev->priv)->tx_packets++;
@@ -147,15 +147,15 @@
 	return 0;
 }
 
-static struct net_device_stats *reg_vif_get_stats(struct device *dev)
+static struct net_device_stats *reg_vif_get_stats(struct net_device *dev)
 {
 	return (struct net_device_stats*)dev->priv;
 }
 
 static
-struct device *ipmr_reg_vif(struct vifctl *v)
+struct net_device *ipmr_reg_vif(struct vifctl *v)
 {
-	struct device  *dev;
+	struct net_device  *dev;
 	struct in_device *in_dev;
 	int size;
 
@@ -213,7 +213,7 @@
 static int vif_delete(int vifi)
 {
 	struct vif_device *v;
-	struct device *dev;
+	struct net_device *dev;
 	struct in_device *in_dev;
 	
 	if (vifi < 0 || vifi >= maxvif || !(vifc_map&(1<<vifi)))
@@ -724,7 +724,7 @@
 			if(optname==MRT_ADD_VIF)
 			{
 				struct vif_device *v=&vif_table[vif.vifc_vifi];
-				struct device *dev;
+				struct net_device *dev;
 				struct in_device *in_dev;
 
 				/* Is vif busy ? */
@@ -1028,7 +1028,7 @@
 {
 	struct iphdr *iph = skb->nh.iph;
 	struct vif_device *vif = &vif_table[vifi];
-	struct device *dev;
+	struct net_device *dev;
 	struct rtable *rt;
 	int    encap = 0;
 	struct sk_buff *skb2;
@@ -1135,7 +1135,7 @@
 		ip_fragment(skb2, skb2->dst->output);
 }
 
-int ipmr_find_vif(struct device *dev)
+int ipmr_find_vif(struct net_device *dev)
 {
 	int ct;
 	for (ct=0; ct<maxvif; ct++) {
@@ -1383,7 +1383,7 @@
 {
 	int ct;
 	struct rtnexthop *nhp;
-	struct device *dev = vif_table[c->mfc_parent].dev;
+	struct net_device *dev = vif_table[c->mfc_parent].dev;
 	u8 *b = skb->tail;
 	struct rtattr *mp_head;
 
@@ -1421,7 +1421,7 @@
 	start_bh_atomic();
 	cache = ipmr_cache_find(rt->rt_src, rt->rt_dst);
 	if (cache==NULL || (cache->mfc_flags&MFC_QUEUED)) {
-		struct device *dev;
+		struct net_device *dev;
 		int vif;
 		int err;
 
diff -u --recursive --new-file v2.3.13/linux/net/ipv4/rarp.c linux/net/ipv4/rarp.c
--- v2.3.13/linux/net/ipv4/rarp.c	Sun Jul 26 23:35:57 1998
+++ linux/net/ipv4/rarp.c	Wed Aug 18 11:38:48 1999
@@ -83,12 +83,12 @@
 	unsigned char      ha[MAX_ADDR_LEN];  /* Hardware address            */
 	unsigned char      hlen;              /* Length of hardware address  */
 	unsigned char      htype;             /* Type of hardware in use     */
-	struct device      *dev;              /* Device the entry is tied to */
+	struct net_device      *dev;              /* Device the entry is tied to */
 };
 
 struct rarp_table *rarp_tables = NULL;
 
-static int rarp_rcv(struct sk_buff *, struct device *, struct packet_type *);
+static int rarp_rcv(struct sk_buff *, struct net_device *, struct packet_type *);
 
 static struct packet_type rarp_packet_type =
 {
@@ -142,7 +142,7 @@
  *	Flush a device.
  */
 
-static void rarp_destroy_dev(struct device *dev)
+static void rarp_destroy_dev(struct net_device *dev)
 {
 	struct rarp_table *entry;
 	struct rarp_table **pentry;
@@ -166,7 +166,7 @@
 {
 	if(event!=NETDEV_DOWN)
 		return NOTIFY_DONE;
-	rarp_destroy_dev((struct device *)ptr);
+	rarp_destroy_dev((struct net_device *)ptr);
 	return NOTIFY_DONE;
 }
 
@@ -210,7 +210,7 @@
  *	"overhead" time isn't that high...
  */
 
-static int rarp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
+static int rarp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
 {
 /*
  *	We shouldn't use this type conversion. Check later.
@@ -305,7 +305,7 @@
 	int htype, hlen;
 	unsigned long ip;
 	struct rtable *rt;
-	struct device * dev;
+	struct net_device * dev;
 	int err; 
   
 	err = copy_from_user(&r, req, sizeof(r));
diff -u --recursive --new-file v2.3.13/linux/net/ipv4/route.c linux/net/ipv4/route.c
--- v2.3.13/linux/net/ipv4/route.c	Wed Jun  9 14:45:37 1999
+++ linux/net/ipv4/route.c	Wed Aug 18 11:38:48 1999
@@ -619,7 +619,7 @@
 }
 
 void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw,
-		    u32 saddr, u8 tos, struct device *dev)
+		    u32 saddr, u8 tos, struct net_device *dev)
 {
 	int i, k;
 	struct in_device *in_dev = dev->ip_ptr;
@@ -1035,7 +1035,7 @@
 
 static int
 ip_route_input_mc(struct sk_buff *skb, u32 daddr, u32 saddr,
-		  u8 tos, struct device *dev, int our)
+		  u8 tos, struct net_device *dev, int our)
 {
 	unsigned hash;
 	struct rtable *rth;
@@ -1111,7 +1111,7 @@
  */
 
 int ip_route_input_slow(struct sk_buff *skb, u32 daddr, u32 saddr,
-			u8 tos, struct device *dev)
+			u8 tos, struct net_device *dev)
 {
 	struct rt_key	key;
 	struct fib_result res;
@@ -1277,7 +1277,7 @@
 
 #ifdef CONFIG_NET_FASTROUTE
 	if (netdev_fastroute && !(flags&(RTCF_NAT|RTCF_MASQ|RTCF_DOREDIRECT))) {
-		struct device *odev = rth->u.dst.dev;
+		struct net_device *odev = rth->u.dst.dev;
 		if (odev != dev &&
 		    dev->accept_fastpath &&
 		    odev->mtu >= dev->mtu &&
@@ -1380,7 +1380,7 @@
 }
 
 int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr,
-		   u8 tos, struct device *dev)
+		   u8 tos, struct net_device *dev)
 {
 	struct rtable * rth;
 	unsigned	hash;
@@ -1443,7 +1443,7 @@
 	struct fib_result res;
 	unsigned flags = 0;
 	struct rtable *rth;
-	struct device *dev_out = NULL;
+	struct net_device *dev_out = NULL;
 	unsigned hash;
 #ifdef CONFIG_IP_TRANSPARENT_PROXY
 	u32 nochecksrc = (tos & RTO_TPROXY);
@@ -1845,7 +1845,7 @@
 		memcpy(&iif, RTA_DATA(rta[RTA_IIF-1]), sizeof(int));
 
 	if (iif) {
-		struct device *dev;
+		struct net_device *dev;
 		dev = dev_get_by_index(iif);
 		if (!dev)
 			return -ENODEV;
diff -u --recursive --new-file v2.3.13/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c
--- v2.3.13/linux/net/ipv4/tcp_ipv4.c	Wed Jul 28 14:47:42 1999
+++ linux/net/ipv4/tcp_ipv4.c	Wed Aug 18 11:38:49 1999
@@ -362,7 +362,7 @@
  * connection.  So always assume those are both wildcarded
  * during the search since they can never be otherwise.
  */
-static struct sock *tcp_v4_lookup_listener(u32 daddr, unsigned short hnum, int dif)
+struct sock *tcp_v4_lookup_listener(u32 daddr, unsigned short hnum, int dif)
 {
 	struct sock *sk;
 	struct sock *result = NULL;
@@ -452,7 +452,7 @@
  */
 static struct sock *tcp_v4_proxy_lookup(unsigned short num, unsigned long raddr,
 					unsigned short rnum, unsigned long laddr,
-					struct device *dev, unsigned short pnum,
+					struct net_device *dev, unsigned short pnum,
 					int dif)
 {
 	struct sock *s, *result = NULL;
diff -u --recursive --new-file v2.3.13/linux/net/ipv4/udp.c linux/net/ipv4/udp.c
--- v2.3.13/linux/net/ipv4/udp.c	Thu Jul  8 15:42:21 1999
+++ linux/net/ipv4/udp.c	Wed Aug 18 11:38:48 1999
@@ -293,7 +293,7 @@
 
 static struct sock *udp_v4_proxy_lookup(unsigned short num, unsigned long raddr,
 					unsigned short rnum, unsigned long laddr,
-					struct device *dev, unsigned short pnum,
+					struct net_device *dev, unsigned short pnum,
 					int dif)
 {
 	struct sock *s, *result = NULL;
diff -u --recursive --new-file v2.3.13/linux/net/ipv6/addrconf.c linux/net/ipv6/addrconf.c
--- v2.3.13/linux/net/ipv6/addrconf.c	Wed Jun  9 14:45:37 1999
+++ linux/net/ipv6/addrconf.c	Wed Aug 18 11:38:49 1999
@@ -114,7 +114,7 @@
 	atomic_dec(&addr_list_lock);
 }
 
-static int addrconf_ifdown(struct device *dev, int how);
+static int addrconf_ifdown(struct net_device *dev, int how);
 
 static void addrconf_dad_start(struct inet6_ifaddr *ifp);
 static void addrconf_dad_timer(unsigned long data);
@@ -206,7 +206,7 @@
 	return IPV6_ADDR_RESERVED;
 }
 
-static struct inet6_dev * ipv6_add_dev(struct device *dev)
+static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
 {
 	struct inet6_dev *ndev, **bptr, *iter;
 	int hash;
@@ -245,7 +245,7 @@
 	return ndev;
 }
 
-static struct inet6_dev * ipv6_find_idev(struct device *dev)
+static struct inet6_dev * ipv6_find_idev(struct net_device *dev)
 {
 	struct inet6_dev *idev;
 
@@ -272,7 +272,7 @@
 	}
 }
 
-struct inet6_dev * ipv6_get_idev(struct device *dev)
+struct inet6_dev * ipv6_get_idev(struct net_device *dev)
 {
 	struct inet6_dev *idev;
 	int hash;
@@ -380,7 +380,7 @@
 	int scope;
 	struct inet6_ifaddr *ifp = NULL;
 	struct inet6_ifaddr *match = NULL;
-	struct device *dev = NULL;
+	struct net_device *dev = NULL;
 	struct rt6_info *rt;
 	int err;
 	int i;
@@ -461,7 +461,7 @@
 	return err;
 }
 
-int ipv6_get_lladdr(struct device *dev, struct in6_addr *addr)
+int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr)
 {
 	struct inet6_ifaddr *ifp = NULL;
 	struct inet6_dev *idev;
@@ -486,7 +486,7 @@
  *	to the host.
  */
 
-struct inet6_ifaddr * ipv6_chk_addr(struct in6_addr *addr, struct device *dev, int nd)
+struct inet6_ifaddr * ipv6_chk_addr(struct in6_addr *addr, struct net_device *dev, int nd)
 {
 	struct inet6_ifaddr * ifp;
 	u8 hash;
@@ -520,7 +520,7 @@
 
 /* Join to solicited addr multicast group. */
 
-static void addrconf_join_solict(struct device *dev, struct in6_addr *addr)
+static void addrconf_join_solict(struct net_device *dev, struct in6_addr *addr)
 {
 	struct in6_addr maddr;
 
@@ -537,7 +537,7 @@
 #endif
 }
 
-static void addrconf_leave_solict(struct device *dev, struct in6_addr *addr)
+static void addrconf_leave_solict(struct net_device *dev, struct in6_addr *addr)
 {
 	struct in6_addr maddr;
 
@@ -556,7 +556,7 @@
 
 
 #ifdef CONFIG_IPV6_EUI64
-static int ipv6_generate_eui64(u8 *eui, struct device *dev)
+static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
 {
 	switch (dev->type) {
 	case ARPHRD_ETHER:
@@ -578,7 +578,7 @@
  */
 
 static void
-addrconf_prefix_route(struct in6_addr *pfx, int plen, struct device *dev,
+addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev,
 		      unsigned long expires, unsigned flags)
 {
 	struct in6_rtmsg rtmsg;
@@ -604,7 +604,7 @@
 
 /* Create "default" multicast route to the interface */
 
-static void addrconf_add_mroute(struct device *dev)
+static void addrconf_add_mroute(struct net_device *dev)
 {
 	struct in6_rtmsg rtmsg;
 
@@ -619,7 +619,7 @@
 	ip6_route_add(&rtmsg);
 }
 
-static void sit_route_add(struct device *dev)
+static void sit_route_add(struct net_device *dev)
 {
 	struct in6_rtmsg rtmsg;
 
@@ -636,7 +636,7 @@
 	ip6_route_add(&rtmsg);
 }
 
-static void addrconf_add_lroute(struct device *dev)
+static void addrconf_add_lroute(struct net_device *dev)
 {
 	struct in6_addr addr;
 
@@ -644,7 +644,7 @@
 	addrconf_prefix_route(&addr, 10, dev, 0, RTF_ADDRCONF);
 }
 
-static struct inet6_dev *addrconf_add_dev(struct device *dev)
+static struct inet6_dev *addrconf_add_dev(struct net_device *dev)
 {
 	struct inet6_dev *idev;
 
@@ -659,7 +659,7 @@
 	return idev;
 }
 
-void addrconf_prefix_rcv(struct device *dev, u8 *opt, int len)
+void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
 {
 	struct prefix_info *pinfo;
 	struct rt6_info *rt;
@@ -801,7 +801,7 @@
 int addrconf_set_dstaddr(void *arg)
 {
 	struct in6_ifreq ireq;
-	struct device *dev;
+	struct net_device *dev;
 	int err = -EINVAL;
 
 	rtnl_lock();
@@ -858,7 +858,7 @@
 {
 	struct inet6_ifaddr *ifp;
 	struct inet6_dev *idev;
-	struct device *dev;
+	struct net_device *dev;
 	int scope;
 	
 	if ((dev = dev_get_by_index(ifindex)) == NULL)
@@ -889,7 +889,7 @@
 {
 	struct inet6_ifaddr *ifp;
 	struct inet6_dev *idev;
-	struct device *dev;
+	struct net_device *dev;
 	int scope;
 	
 	if ((dev = dev_get_by_index(ifindex)) == NULL)
@@ -958,7 +958,7 @@
 {
 	struct inet6_ifaddr * ifp;
 	struct in6_addr addr;
-	struct device *dev;
+	struct net_device *dev;
 	int scope;
 
 	memset(&addr, 0, sizeof(struct in6_addr));
@@ -1019,7 +1019,7 @@
 	read_unlock(&dev_base_lock);
 }
 
-static void init_loopback(struct device *dev)
+static void init_loopback(struct net_device *dev)
 {
 	struct in6_addr addr;
 	struct inet6_dev  *idev;
@@ -1060,7 +1060,7 @@
 	addrconf_unlock();
 }
 
-static void addrconf_dev_config(struct device *dev)
+static void addrconf_dev_config(struct net_device *dev)
 {
 	struct in6_addr addr;
 	struct inet6_dev    * idev;
@@ -1096,7 +1096,7 @@
 #endif
 }
 
-static void addrconf_sit_config(struct device *dev)
+static void addrconf_sit_config(struct net_device *dev)
 {
 	struct inet6_dev *idev;
 
@@ -1124,9 +1124,9 @@
 int addrconf_notify(struct notifier_block *this, unsigned long event, 
 		    void * data)
 {
-	struct device *dev;
+	struct net_device *dev;
 
-	dev = (struct device *) data;
+	dev = (struct net_device *) data;
 
 	switch(event) {
 	case NETDEV_UP:
@@ -1181,7 +1181,7 @@
 	return NOTIFY_OK;
 }
 
-static int addrconf_ifdown(struct device *dev, int how)
+static int addrconf_ifdown(struct net_device *dev, int how)
 {
 	struct inet6_dev *idev, **bidev;
 	struct inet6_ifaddr *ifa, **bifa;
@@ -1299,7 +1299,7 @@
  */
 static void addrconf_dad_start(struct inet6_ifaddr *ifp)
 {
-	struct device *dev;
+	struct net_device *dev;
 	unsigned long rand_num;
 
 	dev = ifp->idev->dev;
@@ -1367,7 +1367,7 @@
 
 static void addrconf_dad_completed(struct inet6_ifaddr *ifp)
 {
-	struct device *	dev = ifp->idev->dev;
+	struct net_device *	dev = ifp->idev->dev;
 
 	/*
 	 *	Configure the address for reception. Now it is valid.
@@ -1707,7 +1707,7 @@
 		struct inet6_dev *idev = NULL;
 
 		if (valp != &ipv6_devconf.forwarding) {
-			struct device *dev = dev_get_by_index(ctl->ctl_name);
+			struct net_device *dev = dev_get_by_index(ctl->ctl_name);
 			if (dev)
 				idev = ipv6_get_idev(dev);
 			if (idev == NULL)
@@ -1788,7 +1788,7 @@
 static void addrconf_sysctl_register(struct inet6_dev *idev, struct ipv6_devconf *p)
 {
 	int i;
-	struct device *dev = idev ? idev->dev : NULL;
+	struct net_device *dev = idev ? idev->dev : NULL;
 	struct addrconf_sysctl_table *t;
 
 	t = kmalloc(sizeof(*t), GFP_KERNEL);
@@ -1842,7 +1842,7 @@
 __initfunc(void addrconf_init(void))
 {
 #ifdef MODULE
-	struct device *dev;
+	struct net_device *dev;
 
 	/* This takes sense only during module load. */
 	read_lock(&dev_base_lock);
diff -u --recursive --new-file v2.3.13/linux/net/ipv6/icmp.c linux/net/ipv6/icmp.c
--- v2.3.13/linux/net/ipv6/icmp.c	Wed May 26 18:14:38 1999
+++ linux/net/ipv6/icmp.c	Wed Aug 18 11:38:49 1999
@@ -237,7 +237,7 @@
  */
 
 void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, 
-		 struct device *dev)
+		 struct net_device *dev)
 {
 	struct ipv6hdr *hdr = skb->nh.ipv6h;
 	struct sock *sk = icmpv6_socket->sk;
@@ -458,7 +458,7 @@
 
 int icmpv6_rcv(struct sk_buff *skb, unsigned long len)
 {
-	struct device *dev = skb->dev;
+	struct net_device *dev = skb->dev;
 	struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
 	struct in6_addr *daddr = &skb->nh.ipv6h->daddr;
 	struct ipv6hdr *orig_hdr;
diff -u --recursive --new-file v2.3.13/linux/net/ipv6/ip6_input.c linux/net/ipv6/ip6_input.c
--- v2.3.13/linux/net/ipv6/ip6_input.c	Thu Aug 27 19:33:09 1998
+++ linux/net/ipv6/ip6_input.c	Wed Aug 18 11:38:49 1999
@@ -38,7 +38,7 @@
 #include <net/addrconf.h>
 
 
-int ipv6_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
+int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
 {
 	struct ipv6hdr *hdr;
 	u32 		pkt_len;
diff -u --recursive --new-file v2.3.13/linux/net/ipv6/ip6_output.c linux/net/ipv6/ip6_output.c
--- v2.3.13/linux/net/ipv6/ip6_output.c	Wed Jun  9 14:45:37 1999
+++ linux/net/ipv6/ip6_output.c	Wed Aug 18 11:38:49 1999
@@ -50,7 +50,7 @@
 int ip6_output(struct sk_buff *skb)
 {
 	struct dst_entry *dst = skb->dst;
-	struct device *dev = dst->dev;
+	struct net_device *dev = dst->dev;
 	struct hh_cache *hh = dst->hh;
 
 	skb->protocol = __constant_htons(ETH_P_IPV6);
@@ -168,7 +168,7 @@
  *	is for us performace critical)
  */
 
-int ip6_nd_hdr(struct sock *sk, struct sk_buff *skb, struct device *dev,
+int ip6_nd_hdr(struct sock *sk, struct sk_buff *skb, struct net_device *dev,
 	       struct in6_addr *saddr, struct in6_addr *daddr,
 	       int proto, int len)
 {
@@ -528,7 +528,7 @@
 	if (pktlength <= mtu) {
 		struct sk_buff *skb;
 		struct ipv6hdr *hdr;
-		struct device *dev = dst->dev;
+		struct net_device *dev = dst->dev;
 
 		skb = sock_alloc_send_skb(sk, pktlength + 15 +
 					  dev->hard_header_len, 0,
diff -u --recursive --new-file v2.3.13/linux/net/ipv6/mcast.c linux/net/ipv6/mcast.c
--- v2.3.13/linux/net/ipv6/mcast.c	Wed Jun  9 14:45:37 1999
+++ linux/net/ipv6/mcast.c	Wed Aug 18 11:38:49 1999
@@ -77,7 +77,7 @@
 
 int ipv6_sock_mc_join(struct sock *sk, int ifindex, struct in6_addr *addr)
 {
-	struct device *dev = NULL;
+	struct net_device *dev = NULL;
 	struct ipv6_mc_socklist *mc_lst;
 	struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6;
 	int err;
@@ -140,7 +140,7 @@
 	for (lnk = &np->ipv6_mc_list; (mc_lst = *lnk) !=NULL ; lnk = &mc_lst->next) {
 		if (mc_lst->ifindex == ifindex &&
 		    ipv6_addr_cmp(&mc_lst->addr, addr) == 0) {
-			struct device *dev;
+			struct net_device *dev;
 
 			*lnk = mc_lst->next;
 			write_unlock_bh(&ipv6_sk_mc_lock);
@@ -163,7 +163,7 @@
 
 	write_lock_bh(&ipv6_sk_mc_lock);
 	while ((mc_lst = np->ipv6_mc_list) != NULL) {
-		struct device *dev;
+		struct net_device *dev;
 
 		np->ipv6_mc_list = mc_lst->next;
 		write_unlock_bh(&ipv6_sk_mc_lock);
@@ -229,7 +229,7 @@
 /*
  *	device multicast group inc (add if not found)
  */
-int ipv6_dev_mc_inc(struct device *dev, struct in6_addr *addr)
+int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr)
 {
 	struct ifmcaddr6 *mc;
 	struct inet6_dev    *idev;
@@ -283,7 +283,7 @@
 	return 0;
 }
 
-static void ipv6_mca_remove(struct device *dev, struct ifmcaddr6 *ma)
+static void ipv6_mca_remove(struct net_device *dev, struct ifmcaddr6 *ma)
 {
 	struct inet6_dev *idev;
 
@@ -304,7 +304,7 @@
 /*
  *	device multicast group del
  */
-int ipv6_dev_mc_dec(struct device *dev, struct in6_addr *addr)
+int ipv6_dev_mc_dec(struct net_device *dev, struct in6_addr *addr)
 {
 	struct ifmcaddr6 *ma, **lnk;
 	int hash;
@@ -334,7 +334,7 @@
 /*
  *	check if the interface/address pair is valid
  */
-int ipv6_chk_mcast_addr(struct device *dev, struct in6_addr *addr)
+int ipv6_chk_mcast_addr(struct net_device *dev, struct in6_addr *addr)
 {
 	struct ifmcaddr6 *mc;
 	int hash;
@@ -433,7 +433,7 @@
 {
 	struct ifmcaddr6 *ma;
 	struct in6_addr *addrp;
-	struct device *dev;
+	struct net_device *dev;
 	int hash;
 
 	/* Our own report looped back. Ignore it. */
@@ -474,7 +474,7 @@
 	return 0;
 }
 
-void igmp6_send(struct in6_addr *addr, struct device *dev, int type)
+void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
 {
 	struct sock *sk = igmp6_socket->sk;
         struct sk_buff *skb;
@@ -664,7 +664,7 @@
 	off_t pos=0, begin=0;
 	struct ifmcaddr6 *im;
 	int len=0;
-	struct device *dev;
+	struct net_device *dev;
 	
 	read_lock(&dev_base_lock);
 	for (dev = dev_base; dev; dev = dev->next) {
diff -u --recursive --new-file v2.3.13/linux/net/ipv6/ndisc.c linux/net/ipv6/ndisc.c
--- v2.3.13/linux/net/ipv6/ndisc.c	Wed Jun  9 14:45:37 1999
+++ linux/net/ipv6/ndisc.c	Wed Aug 18 11:38:49 1999
@@ -150,7 +150,7 @@
 	return opt + space;
 }
 
-int ndisc_mc_map(struct in6_addr *addr, char *buf, struct device *dev, int dir)
+int ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int dir)
 {
 	switch (dev->type) {
 	case ARPHRD_ETHER:
@@ -170,7 +170,7 @@
 static int ndisc_constructor(struct neighbour *neigh)
 {
 	struct in6_addr *addr = (struct in6_addr*)&neigh->primary_key;
-	struct device *dev = neigh->dev;
+	struct net_device *dev = neigh->dev;
 	struct inet6_dev *in6_dev = ipv6_get_idev(dev);
 	int addr_type;
 
@@ -219,7 +219,7 @@
 {
 	struct in6_addr *addr = (struct in6_addr*)&n->key;
 	struct in6_addr maddr;
-	struct device *dev = n->dev;
+	struct net_device *dev = n->dev;
 
 	if (dev == NULL || ipv6_get_idev(dev) == NULL)
 		return -EINVAL;
@@ -238,7 +238,7 @@
 {
 	struct in6_addr *addr = (struct in6_addr*)&n->key;
 	struct in6_addr maddr;
-	struct device *dev = n->dev;
+	struct net_device *dev = n->dev;
 
 	if (dev == NULL || ipv6_get_idev(dev) == NULL)
 		return;
@@ -255,7 +255,7 @@
 
 
 static int
-ndisc_build_ll_hdr(struct sk_buff *skb, struct device *dev,
+ndisc_build_ll_hdr(struct sk_buff *skb, struct net_device *dev,
 		   struct in6_addr *daddr, struct neighbour *neigh, int len)
 {
 	unsigned char ha[MAX_ADDR_LEN];
@@ -299,7 +299,7 @@
  *	Send a Neighbour Advertisement
  */
 
-void ndisc_send_na(struct device *dev, struct neighbour *neigh,
+void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
 		   struct in6_addr *daddr, struct in6_addr *solicited_addr,
 		   int router, int solicited, int override, int inc_opt) 
 {
@@ -362,7 +362,7 @@
 	icmpv6_statistics.Icmp6OutMsgs++;
 }        
 
-void ndisc_send_ns(struct device *dev, struct neighbour *neigh,
+void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
 		   struct in6_addr *solicit,
 		   struct in6_addr *daddr, struct in6_addr *saddr) 
 {
@@ -421,7 +421,7 @@
 	icmpv6_statistics.Icmp6OutMsgs++;
 }
 
-void ndisc_send_rs(struct device *dev, struct in6_addr *saddr,
+void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
 		   struct in6_addr *daddr)
 {
 	struct sock *sk = ndisc_socket->sk;
@@ -510,7 +510,7 @@
 {
 	struct in6_addr *saddr = NULL;
 	struct in6_addr mcaddr;
-	struct device *dev = neigh->dev;
+	struct net_device *dev = neigh->dev;
 	struct in6_addr *target = (struct in6_addr *)&neigh->primary_key;
 	int probes = atomic_read(&neigh->probes);
 
@@ -782,7 +782,7 @@
 	struct icmp6hdr *icmph;
 	struct in6_addr saddr_buf;
 	struct in6_addr *addrp;
-	struct device *dev;
+	struct net_device *dev;
 	struct rt6_info *rt;
 	u8 *opt;
 	int rd_len;
@@ -922,7 +922,7 @@
 
 int ndisc_rcv(struct sk_buff *skb, unsigned long len)
 {
-	struct device *dev = skb->dev;
+	struct net_device *dev = skb->dev;
 	struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
 	struct in6_addr *daddr = &skb->nh.ipv6h->daddr;
 	struct nd_msg *msg = (struct nd_msg *) skb->h.raw;
diff -u --recursive --new-file v2.3.13/linux/net/ipv6/reassembly.c linux/net/ipv6/reassembly.c
--- v2.3.13/linux/net/ipv6/reassembly.c	Wed Jun  9 14:45:37 1999
+++ linux/net/ipv6/reassembly.c	Wed Aug 18 11:38:49 1999
@@ -74,7 +74,7 @@
 	struct in6_addr		daddr;
 	struct timer_list	timer;		/* expire timer		*/
 	struct ipv6_frag	*fragments;
-	struct device		*dev;
+	struct net_device		*dev;
 	int			iif;
 	__u8			last_in;	/* has first/last segment arrived? */
 #define FIRST_IN		2
@@ -228,7 +228,7 @@
 	   (fixed --ANK (980728))
 	 */
 	if (fq->last_in&FIRST_IN) {
-		struct device *dev = dev_get_by_index(fq->iif);
+		struct net_device *dev = dev_get_by_index(fq->iif);
 
 		/*
 		   But use as source device on which LAST ARRIVED
diff -u --recursive --new-file v2.3.13/linux/net/ipv6/route.c linux/net/ipv6/route.c
--- v2.3.13/linux/net/ipv6/route.c	Thu Jul  8 15:42:21 1999
+++ linux/net/ipv6/route.c	Wed Aug 18 11:38:49 1999
@@ -145,7 +145,7 @@
 
 	if (oif) {
 		for (sprt = rt; sprt; sprt = sprt->u.next) {
-			struct device *dev = sprt->rt6i_dev;
+			struct net_device *dev = sprt->rt6i_dev;
 			if (dev->ifindex == oif)
 				return sprt;
 			if (dev->flags&IFF_LOOPBACK)
@@ -580,7 +580,7 @@
 		pfx->s6_addr[plen>>3] &= (0xFF<<(8-b));
 }
 
-static int ipv6_get_mtu(struct device *dev)
+static int ipv6_get_mtu(struct net_device *dev)
 {
 	struct inet6_dev *idev;
 
@@ -591,7 +591,7 @@
 		return IPV6_MIN_MTU;
 }
 
-static int ipv6_get_hoplimit(struct device *dev)
+static int ipv6_get_hoplimit(struct net_device *dev)
 {
 	struct inet6_dev *idev;
 
@@ -610,7 +610,7 @@
 {
 	int err;
 	struct rt6_info *rt;
-	struct device *dev = NULL;
+	struct net_device *dev = NULL;
 	int addr_type;
 
 	if (rtmsg->rtmsg_dst_len > 128 || rtmsg->rtmsg_src_len > 128)
@@ -842,7 +842,7 @@
 }
 
 void rt6_sndmsg(int type, struct in6_addr *dst, struct in6_addr *src,
-		struct in6_addr *gw, struct device *dev, 
+		struct in6_addr *gw, struct net_device *dev, 
 		int dstlen, int srclen,	int metric, __u32 flags)
 {
 	struct sk_buff *skb;
@@ -996,7 +996,7 @@
  */
 
 void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
-			struct device *dev, u32 pmtu)
+			struct net_device *dev, u32 pmtu)
 {
 	struct rt6_info *rt, *nrt;
 
@@ -1098,7 +1098,7 @@
 	return rt;
 }
 
-struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct device *dev)
+struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *dev)
 {	
 	struct rt6_info *rt;
 	struct fib6_node *fn;
@@ -1118,7 +1118,7 @@
 }
 
 struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr,
-				     struct device *dev)
+				     struct net_device *dev)
 {
 	struct in6_rtmsg rtmsg;
 
@@ -1210,7 +1210,7 @@
  *	Add address
  */
 
-int ip6_rt_addr_add(struct in6_addr *addr, struct device *dev)
+int ip6_rt_addr_add(struct in6_addr *addr, struct net_device *dev)
 {
 	struct rt6_info *rt;
 
@@ -1244,7 +1244,7 @@
    disappeared before calling this function.
  */
 
-int ip6_rt_addr_del(struct in6_addr *addr, struct device *dev)
+int ip6_rt_addr_del(struct in6_addr *addr, struct net_device *dev)
 {
 	struct rt6_info *rt;
 	int err = -ENOENT;
@@ -1384,14 +1384,14 @@
 	return 0;
 }
 
-void rt6_ifdown(struct device *dev)
+void rt6_ifdown(struct net_device *dev)
 {
 	fib6_clean_tree(&ip6_routing_table, fib6_ifdown, 0, dev);
 }
 
 struct rt6_mtu_change_arg
 {
-	struct device *dev;
+	struct net_device *dev;
 	unsigned mtu;
 };
 
@@ -1410,7 +1410,7 @@
 	return 0;
 }
 
-void rt6_mtu_change(struct device *dev, unsigned mtu)
+void rt6_mtu_change(struct net_device *dev, unsigned mtu)
 {
 	struct rt6_mtu_change_arg arg;
 
@@ -1716,7 +1716,7 @@
 		memcpy(&iif, RTA_DATA(rta[RTA_IIF-1]), sizeof(int));
 
 	if (iif) {
-		struct device *dev;
+		struct net_device *dev;
 		dev = dev_get_by_index(iif);
 		if (!dev)
 			return -ENODEV;
diff -u --recursive --new-file v2.3.13/linux/net/ipv6/sit.c linux/net/ipv6/sit.c
--- v2.3.13/linux/net/ipv6/sit.c	Thu Mar 25 09:23:34 1999
+++ linux/net/ipv6/sit.c	Wed Aug 18 11:38:49 1999
@@ -53,10 +53,10 @@
 #define HASH_SIZE  16
 #define HASH(addr) ((addr^(addr>>4))&0xF)
 
-static int ipip6_fb_tunnel_init(struct device *dev);
-static int ipip6_tunnel_init(struct device *dev);
+static int ipip6_fb_tunnel_init(struct net_device *dev);
+static int ipip6_tunnel_init(struct net_device *dev);
 
-static struct device ipip6_fb_tunnel_dev = {
+static struct net_device ipip6_fb_tunnel_dev = {
 	NULL, 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, ipip6_fb_tunnel_init,
 };
 
@@ -139,7 +139,7 @@
 	u32 remote = parms->iph.daddr;
 	u32 local = parms->iph.saddr;
 	struct ip_tunnel *t, **tp, *nt;
-	struct device *dev;
+	struct net_device *dev;
 	unsigned h = 0;
 	int prio = 0;
 
@@ -195,7 +195,7 @@
 	return NULL;
 }
 
-static void ipip6_tunnel_destroy(struct device *dev)
+static void ipip6_tunnel_destroy(struct net_device *dev)
 {
 	if (dev == &ipip6_fb_tunnel_dev) {
 		tunnels_wc[0] = NULL;
@@ -384,7 +384,7 @@
  *	and that skb is filled properly by that function.
  */
 
-static int ipip6_tunnel_xmit(struct sk_buff *skb, struct device *dev)
+static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv;
 	struct net_device_stats *stats = &tunnel->stat;
@@ -392,7 +392,7 @@
 	struct ipv6hdr *iph6 = skb->nh.ipv6h;
 	u8     tos = tunnel->parms.iph.tos;
 	struct rtable *rt;     			/* Route to the other host */
-	struct device *tdev;			/* Device to other host */
+	struct net_device *tdev;			/* Device to other host */
 	struct iphdr  *iph;			/* Our new IP header */
 	int    max_headroom;			/* The extra header space needed */
 	u32    dst = tiph->daddr;
@@ -544,7 +544,7 @@
 }
 
 static int
-ipip6_tunnel_ioctl (struct device *dev, struct ifreq *ifr, int cmd)
+ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	int err = 0;
 	struct ip_tunnel_parm p;
@@ -654,12 +654,12 @@
 	return err;
 }
 
-static struct net_device_stats *ipip6_tunnel_get_stats(struct device *dev)
+static struct net_device_stats *ipip6_tunnel_get_stats(struct net_device *dev)
 {
 	return &(((struct ip_tunnel*)dev->priv)->stat);
 }
 
-static int ipip6_tunnel_change_mtu(struct device *dev, int new_mtu)
+static int ipip6_tunnel_change_mtu(struct net_device *dev, int new_mtu)
 {
 	if (new_mtu < IPV6_MIN_MTU || new_mtu > 0xFFF8 - sizeof(struct iphdr))
 		return -EINVAL;
@@ -667,7 +667,7 @@
 	return 0;
 }
 
-static void ipip6_tunnel_init_gen(struct device *dev)
+static void ipip6_tunnel_init_gen(struct net_device *dev)
 {
 	struct ip_tunnel *t = (struct ip_tunnel*)dev->priv;
 
@@ -689,9 +689,9 @@
 	memcpy(dev->broadcast, &t->parms.iph.daddr, 4);
 }
 
-static int ipip6_tunnel_init(struct device *dev)
+static int ipip6_tunnel_init(struct net_device *dev)
 {
-	struct device *tdev = NULL;
+	struct net_device *tdev = NULL;
 	struct ip_tunnel *tunnel;
 	struct iphdr *iph;
 
@@ -724,20 +724,20 @@
 }
 
 #ifdef MODULE
-static int ipip6_fb_tunnel_open(struct device *dev)
+static int ipip6_fb_tunnel_open(struct net_device *dev)
 {
 	MOD_INC_USE_COUNT;
 	return 0;
 }
 
-static int ipip6_fb_tunnel_close(struct device *dev)
+static int ipip6_fb_tunnel_close(struct net_device *dev)
 {
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
 #endif
 
-__initfunc(int ipip6_fb_tunnel_init(struct device *dev))
+__initfunc(int ipip6_fb_tunnel_init(struct net_device *dev))
 {
 	struct iphdr *iph;
 
diff -u --recursive --new-file v2.3.13/linux/net/ipv6/udp.c linux/net/ipv6/udp.c
--- v2.3.13/linux/net/ipv6/udp.c	Thu Jul  8 15:42:21 1999
+++ linux/net/ipv6/udp.c	Wed Aug 18 11:38:49 1999
@@ -448,7 +448,7 @@
 	       struct inet6_skb_parm *opt,
 	       int type, int code, unsigned char *buff, __u32 info)
 {
-	struct device *dev = skb->dev;
+	struct net_device *dev = skb->dev;
 	struct in6_addr *saddr = &hdr->saddr;
 	struct in6_addr *daddr = &hdr->daddr;
 	struct sock *sk;
@@ -579,7 +579,7 @@
 {
 	struct sock *sk;
   	struct udphdr *uh;
-	struct device *dev = skb->dev;
+	struct net_device *dev = skb->dev;
 	struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
 	struct in6_addr *daddr = &skb->nh.ipv6h->daddr;
 	u32 ulen;
diff -u --recursive --new-file v2.3.13/linux/net/ipx/af_ipx.c linux/net/ipx/af_ipx.c
--- v2.3.13/linux/net/ipx/af_ipx.c	Thu Jul  8 15:42:21 1999
+++ linux/net/ipx/af_ipx.c	Wed Aug 18 11:38:49 1999
@@ -239,7 +239,7 @@
 		ipx_primary_net = NULL;
 }
 
-static ipx_interface *ipxitf_find_using_phys(struct device *dev, unsigned short datalink)
+static ipx_interface *ipxitf_find_using_phys(struct net_device *dev, unsigned short datalink)
 {
 	ipx_interface	*i;
 
@@ -365,7 +365,7 @@
 
 static int ipxitf_device_event(struct notifier_block *notifier, unsigned long event, void *ptr)
 {
-	struct device *dev = ptr;
+	struct net_device *dev = ptr;
 	ipx_interface *i, *tmp;
 
 	if(event != NETDEV_DOWN)
@@ -608,7 +608,7 @@
 static int ipxitf_send(ipx_interface *intrfc, struct sk_buff *skb, char *node)
 {
 	struct ipxhdr *ipx = skb->nh.ipxh;
-	struct device *dev = intrfc->if_dev;
+	struct net_device *dev = intrfc->if_dev;
 	struct datalink_proto *dl = intrfc->if_dlink;
 	char dest_node[IPX_NODE_LEN];
 	int send_to_wire = 1;
@@ -922,7 +922,7 @@
 
 static int ipxitf_create(ipx_interface_definition *idef)
 {
-	struct device *dev;
+	struct net_device *dev;
 	unsigned short dlink_type = 0;
 	struct datalink_proto *datalink = NULL;
 	ipx_interface *intrfc;
@@ -1025,7 +1025,7 @@
 
 static int ipxitf_delete(ipx_interface_definition *idef)
 {
-	struct device *dev = NULL;
+	struct net_device *dev = NULL;
 	unsigned short dlink_type = 0;
 	ipx_interface *intrfc;
 
@@ -1057,7 +1057,7 @@
 	return (-EINVAL);
 }
 
-static ipx_interface *ipxitf_auto_create(struct device *dev, 
+static ipx_interface *ipxitf_auto_create(struct net_device *dev, 
 	unsigned short dlink_type)
 {
 	struct datalink_proto *datalink = NULL;
@@ -1148,7 +1148,7 @@
 		{
 			struct sockaddr_ipx *sipx;
 			ipx_interface *ipxif;
-			struct device *dev;
+			struct net_device *dev;
 
 			if(copy_from_user(&ifr, arg, sizeof(ifr)))
 				return (-EFAULT);
@@ -2068,7 +2068,7 @@
 	return (0);
 }
 
-int ipx_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
+int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
 {
 	/* NULL here for pt means the packet was looped back */
 	ipx_interface *intrfc;
diff -u --recursive --new-file v2.3.13/linux/net/irda/af_irda.c linux/net/irda/af_irda.c
--- v2.3.13/linux/net/irda/af_irda.c	Mon Jun  7 16:18:58 1999
+++ linux/net/irda/af_irda.c	Wed Aug 18 11:38:49 1999
@@ -44,7 +44,7 @@
 
 extern int  irda_init(void);
 extern void irda_cleanup(void);
-extern int  irlap_driver_rcv(struct sk_buff *, struct device *, 
+extern int  irlap_driver_rcv(struct sk_buff *, struct net_device *, 
 			     struct packet_type *);
 
 static struct proto_ops irda_stream_ops;
@@ -1383,7 +1383,7 @@
 static int irda_device_event(struct notifier_block *this, unsigned long event,
 			     void *ptr)
 {
-	struct device *dev = (struct device *) ptr;
+	struct net_device *dev = (struct net_device *) ptr;
 	
 	DEBUG(3, __FUNCTION__ "()\n");
 	
diff -u --recursive --new-file v2.3.13/linux/net/irda/irda_device.c linux/net/irda/irda_device.c
--- v2.3.13/linux/net/irda/irda_device.c	Mon Jun  7 16:18:58 1999
+++ linux/net/irda/irda_device.c	Wed Aug 18 11:38:49 1999
@@ -64,12 +64,12 @@
 /* Netdevice functions */
 static int irda_device_net_rebuild_header(struct sk_buff *skb);
 static int irda_device_net_hard_header(struct sk_buff *skb, 
-				       struct device *dev,
+				       struct net_device *dev,
 				       unsigned short type, void *daddr, 
 				       void *saddr, unsigned len);
-static int irda_device_net_set_config(struct device *dev, struct ifmap *map);
-static int irda_device_net_change_mtu(struct device *dev, int new_mtu);
-static int irda_device_net_ioctl(struct device *dev, struct ifreq *rq,int cmd);
+static int irda_device_net_set_config(struct net_device *dev, struct ifmap *map);
+static int irda_device_net_change_mtu(struct net_device *dev, int new_mtu);
+static int irda_device_net_ioctl(struct net_device *dev, struct ifreq *rq,int cmd);
 #ifdef CONFIG_PROC_FS
 int irda_device_proc_read( char *buf, char **start, off_t offset, int len, 
 			   int unused);
@@ -404,7 +404,7 @@
 	return &self->qos;
 }
 
-static struct enet_statistics *irda_device_get_stats( struct device *dev)
+static struct enet_statistics *irda_device_get_stats( struct net_device *dev)
 {
 	struct irda_device *priv = (struct irda_device *) dev->priv;
 
@@ -417,7 +417,7 @@
  *    This function should be used by low level device drivers in a similar way
  *    as ether_setup() is used by normal network device drivers
  */
-int irda_device_setup(struct device *dev) 
+int irda_device_setup(struct net_device *dev) 
 {
 	struct irda_device *self;
 
@@ -465,7 +465,7 @@
 	return 0;
 }
 
-static int irda_device_net_hard_header(struct sk_buff *skb, struct device *dev,
+static int irda_device_net_hard_header(struct sk_buff *skb, struct net_device *dev,
 				       unsigned short type, void *daddr, 
 				       void *saddr, unsigned len)
 {
@@ -478,14 +478,14 @@
 	return 0;
 }
 
-static int irda_device_net_set_config( struct device *dev, struct ifmap *map)
+static int irda_device_net_set_config( struct net_device *dev, struct ifmap *map)
 {
 	DEBUG( 0, __FUNCTION__ "()\n");
 
 	return 0;
 }
 
-static int irda_device_net_change_mtu( struct device *dev, int new_mtu)
+static int irda_device_net_change_mtu( struct net_device *dev, int new_mtu)
 {
      DEBUG( 0, __FUNCTION__ "()\n");
      
@@ -494,7 +494,7 @@
 
 
 #define SIOCSDONGLE     SIOCDEVPRIVATE
-static int irda_device_net_ioctl(struct device *dev, /* ioctl device */
+static int irda_device_net_ioctl(struct net_device *dev, /* ioctl device */
 				 struct ifreq *rq,   /* Data passed */
 				 int	cmd)	     /* Ioctl number */
 {
diff -u --recursive --new-file v2.3.13/linux/net/irda/irlan/irlan_eth.c linux/net/irda/irlan/irlan_eth.c
--- v2.3.13/linux/net/irda/irlan/irlan_eth.c	Mon Jun  7 16:18:58 1999
+++ linux/net/irda/irlan/irlan_eth.c	Wed Aug 18 11:38:49 1999
@@ -45,7 +45,7 @@
  *    The network device initialization function.
  *
  */
-int irlan_eth_init(struct device *dev)
+int irlan_eth_init(struct net_device *dev)
 {
 	struct irmanager_event mgr_event;
 	struct irlan_cb *self;
@@ -111,7 +111,7 @@
  *    Network device has been opened by user
  *
  */
-int irlan_eth_open(struct device *dev)
+int irlan_eth_open(struct net_device *dev)
 {
 	struct irlan_cb *self;
 	
@@ -146,7 +146,7 @@
  *    close timer, so that the instance will be removed if we are unable
  *    to discover the remote device after the disconnect.
  */
-int irlan_eth_close(struct device *dev)
+int irlan_eth_close(struct net_device *dev)
 {
 	struct irlan_cb *self = (struct irlan_cb *) dev->priv;
 
@@ -182,7 +182,7 @@
  *    Transmits ethernet frames over IrDA link.
  *
  */
-int irlan_eth_xmit(struct sk_buff *skb, struct device *dev)
+int irlan_eth_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct irlan_cb *self;
 	int ret;
@@ -287,7 +287,7 @@
 void irlan_eth_flow_indication(void *instance, void *sap, LOCAL_FLOW flow)
 {
 	struct irlan_cb *self;
-	struct device *dev;
+	struct net_device *dev;
 
 	self = (struct irlan_cb *) instance;
 
@@ -319,7 +319,7 @@
  *    If we don't want to use ARP. Currently not used!!
  *
  */
-void irlan_eth_rebuild_header(void *buff, struct device *dev, 
+void irlan_eth_rebuild_header(void *buff, struct net_device *dev, 
 			      unsigned long dest, struct sk_buff *skb)
 {
 	struct ethhdr *eth = (struct ethhdr *) buff;
@@ -336,7 +336,7 @@
  *    Send gratuitous ARP to announce that we have changed
  *    hardware address, so that all peers updates their ARP tables
  */
-void irlan_eth_send_gratuitous_arp(struct device *dev)
+void irlan_eth_send_gratuitous_arp(struct net_device *dev)
 {
 	struct in_device *in_dev;
 
@@ -361,7 +361,7 @@
  *
  */
 #define HW_MAX_ADDRS 4 /* Must query to get it! */
-void irlan_eth_set_multicast_list(struct device *dev) 
+void irlan_eth_set_multicast_list(struct net_device *dev) 
 {
  	struct irlan_cb *self;
 
@@ -413,7 +413,7 @@
  *    Get the current statistics for this device
  *
  */
-struct enet_statistics *irlan_eth_get_stats(struct device *dev) 
+struct enet_statistics *irlan_eth_get_stats(struct net_device *dev) 
 {
 	struct irlan_cb *self = (struct irlan_cb *) dev->priv;
 
diff -u --recursive --new-file v2.3.13/linux/net/irda/irlap_frame.c linux/net/irda/irlap_frame.c
--- v2.3.13/linux/net/irda/irlap_frame.c	Mon Jun  7 16:18:58 1999
+++ linux/net/irda/irlap_frame.c	Wed Aug 18 11:38:49 1999
@@ -1185,7 +1185,7 @@
  *    for processing of the frame.
  *
  */
-int irlap_driver_rcv(struct sk_buff *skb, struct device *dev, 
+int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev, 
 		     struct packet_type *ptype)
 {
 	struct irlap_info info;
diff -u --recursive --new-file v2.3.13/linux/net/khttpd/Config.in linux/net/khttpd/Config.in
--- v2.3.13/linux/net/khttpd/Config.in	Wed Dec 31 16:00:00 1969
+++ linux/net/khttpd/Config.in	Wed Aug 18 09:45:10 1999
@@ -0,0 +1,4 @@
+#
+# kHTTPd
+#
+tristate 'Kernel httpd acceleration (experimental)' CONFIG_KHTTPD
diff -u --recursive --new-file v2.3.13/linux/net/khttpd/Makefile linux/net/khttpd/Makefile
--- v2.3.13/linux/net/khttpd/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/net/khttpd/Makefile	Wed Aug 18 09:45:10 1999
@@ -0,0 +1,28 @@
+#
+# Makefile for kHTTPd
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definition is now in the main makefile...
+
+O_TARGET := khttpd.o
+MOD_LIST_NAME := NET_MODULES
+
+M_OBJS := $(O_TARGET)
+O_OBJS := 	main.o accept.o datasending.o logging.o misc.o rfc.o rfc_time.o security.o \
+		sockets.o sysctl.o userspace.o waitheaders.o
+
+
+
+include $(TOPDIR)/Rules.make
+
+rfc_time.o: times.h
+
+
+make_times_h: make_times_h.c
+	$(HOSTCC) $(HOSTCFLAGS) -o make_times_h make_times_h.c
+
+times.h: make_times_h
+	./make_times_h
diff -u --recursive --new-file v2.3.13/linux/net/khttpd/README linux/net/khttpd/README
--- v2.3.13/linux/net/khttpd/README	Wed Dec 31 16:00:00 1969
+++ linux/net/khttpd/README	Wed Aug 18 09:45:10 1999
@@ -0,0 +1,235 @@
+=====
+
+kHTTPd  -  Kernel httpd accelerator
+
+(C) 1999 by Arjan van de Ven
+Licensed under the terms of the GNU General Public License
+
+=====
+
+
+1. Introduction
+---------------
+   kHTTPd is a http-daemon (webserver) for Linux. kHTTPd is different from 
+   other webservers in that it runs from within the Linux-kernel as a module 
+   (device-driver).
+
+   kHTTPd handles only static (file based) web-pages, and passes all requests
+   for non-static information to a regular userspace-webserver such as Apache or 
+   Zeus. The userspace-daemon doesn't have to be altered in any way.
+
+   Static web-pages are not a very complex thing to serve, but these are very
+   important nevertheless, since virtually all images are static, and a large
+   portion of the html-pages are static also. A "regular" webserver has little
+   added value for static pages, it is simply a "copy file to network"-operation.
+   This can be done very efficiently from within the Linux-kernel, for example 
+   the nfs (network file system) daemon performs a similar task and also runs 
+   in the kernel.
+
+   By "accelerating" the simple case within the kernel, userspace daemons can
+   do what they are very good at: Generating user-specific, dynamic content.
+
+   Note: This document sometimes uses "Apache" instead of "any webserver you
+   ever might want to use", just for reasons of readability.
+   
+
+2. Quick Start  
+--------------
+
+   1) compile and load the module
+   2) configure the module in /proc/sys/net/khttpd if needed
+   3) echo 1 > /proc/sys/net/khttpd/start
+
+   unloading:
+ 
+   echo 1 > /proc/sys/net/khttpd/stop
+   echo 1 > /proc/sys/net/khttpd/unload 
+   rmmod khttpd
+   
+
+
+3. Configuration 
+----------------
+
+   Modes of operation
+   ==================
+
+
+   There are two recommended modes of operation:
+
+   1) "Apache" is main webserver, kHTTPd is assistant
+	clientport   -> 80
+  	serverport   -> 8080 (or whatever)
+
+   2) kHTTPd is main webserver, "Apache" is assistant
+	clientport   -> 8080 (or whatever)
+ 	serverport   -> 80
+
+   
+   Configuring kHTTPd
+   ==================
+
+   Before you can start using kHTTPd, you have to configure it. This
+   is done through the /proc filesystem, and can thus be done from inside
+   a script. Most parameters can only be set when kHTTPd is not active.
+
+   The following things need configuration:
+
+   1) The port where kHTTPd should listen for requests
+   2) The port (on "localhost") where "Apache" is listening
+   3) The location of the documents (documentroot)
+   4) The strings that indicate dynamic content (optional)
+      [  "cgi-bin" is added by default ]
+
+   It is very important that the documentroot for kHTTPd matches the
+   documentroot for the userspace-daemon, as kHTTPd might "redirect"
+   any request to this userspace-daemon.
+
+   A typical script (for the first mode of operation) to do this would 
+   look like:
+
+#!/bin/sh
+modprobe khttpd
+echo 80 > /proc/sys/net/khttpd/clientport
+echo 8080 > /proc/sys/net/khttpd/serverport
+echo /var/www > /proc/sys/net/khttpd/documentroot
+echo php3 > /proc/sys/net/khttpd/dynamic
+echo shtml > /proc/sys/net/khttpd/dynamic
+echo 1 > /proc/sys/net/khttpd/start
+
+   For the second mode of operation, this would be:
+
+#!/bin/sh
+modprobe khttpd
+echo 8080 > /proc/sys/net/khttpd/clientport
+echo 80 > /proc/sys/net/khttpd/serverport
+echo /var/www > /proc/sys/net/khttpd/documentroot
+echo php3 > /proc/sys/net/khttpd/dynamic
+echo shtml > /proc/sys/net/khttpd/dynamic
+echo 1 > /proc/sys/net/khttpd/start
+
+   In this case, you also have to change the configuration of the 
+   userspace-daemon. For Apache, you do this by changing
+
+   Port 80
+
+   to 
+
+   Port 8080
+
+   in /etc/apache/httpd.conf. For security-reasons, you can also change 
+   
+   BindAddress *
+
+   to
+
+   BindAddress 127.0.0.1
+
+   (in the same file) to prevent outside users from accessing Apache 
+   directly. 
+
+
+   
+   Stopping kHTTPd
+   ===============
+   In order to change the configuration, you should stop kHTTPd by typing
+   echo 1 > /proc/sys/net/khttpd/stop
+   on a command-prompt.
+
+   If you want to unload the module, you should type
+   echo 1 > /proc/sys/net/khttpd/unload
+   after stopping kHTTPd first.
+
+   If this doesn't work fast enough for you (the commands above can wait for 
+   a remote connection to close down), you can send the daemons a "HUP"
+   signal after you told them to stop. This will cause the daemon-threads to
+   stop immediately. 
+
+   Note that the daemons will restart immediately if they are not told to
+   stop.
+
+   
+
+4. Permissions
+--------------
+   The security model of kHTTPd is very strict. It can be, since there is a 
+   userspace daemon that can handle the complex exceptions. 
+
+   kHTTPd only serves a file if
+
+	1)  There is no "?" in the URL
+	2)  The URL starts with a "/"
+	3)  The file indicated by the URL exists
+	4)  The file is world-readable (*)
+	5)  The file is not a directory, executable or has the Sticky-bit
+	    set (*)
+	6)  The URL doesn't contain any "forbidden" substrings such as ".."
+	    and "cgi-bin" (*)
+	7)  The mime-type is known (*)
+
+   The items marked with a (*) are configurable through the
+   sysctl-parameters in /proc/sys/net/khttpd.
+
+
+   In all cases where any of the above conditions isn't met, the
+   userspace-daemon is handed the request.
+
+
+
+5. Parameters
+-------------
+   The following parameters are settable through /proc/sys/net/khttpd:
+ 
+	Name		Default		Description
+
+	serverport	8080		The port where kHTTPd listens on
+
+	clientport	80		The port of the userspace
+					http-daemon
+
+	threads		2		The number of server-threads. Should
+					be 1 per CPU for small websites, 2
+					per CPU for big (the active files
+					do not fit in the RAM) websites.
+
+	documentroot	/var/www	the directory where the
+					document-files are
+
+	start		0		Set to 1 to start kHTTPd 
+					(this also resets "stop" to 0)
+
+	stop		0		Set to 1 to stop kHTTPd
+					(this also resets "start" to 0)
+
+	unload		0		Set to 1 to prepare kHTTPd for
+					unloading of the module
+
+	sloppymime	0		If set to 1, unknown mime-types are
+					set to text/html. If set to 0,
+					files with unknown mime-types are
+					handled by the userspace daemon
+
+	perm_required	S_IROTH		Minimum permissions required
+					(for values see "man 2 stat")
+	
+	perm_forbid	dir+sticky+	Permission-mask with "forbidden"
+			execute		permissions.
+					(for values see "man 2 stat")
+
+	dynamic		cgi-bin ..	Strings that, if they are a subset
+					of the URL, indicate "dynamic
+					content"
+
+	maxconnect	1000		Maximum number of concurrent
+					connections
+
+6. More information
+-------------------
+   More information about the architecture of kHTTPd, the mailinglist and
+   configuration-examples can be found at the kHTTPd homepage:
+
+	http://www.fenrus.demon.nl
+
+   Bugreports, patches, etc can be send to the mailinglist
+   (khttpd-users@zgp.org) or to khttpd@fenrus.demon.nl
+
diff -u --recursive --new-file v2.3.13/linux/net/khttpd/accept.c linux/net/khttpd/accept.c
--- v2.3.13/linux/net/khttpd/accept.c	Wed Dec 31 16:00:00 1969
+++ linux/net/khttpd/accept.c	Wed Aug 18 09:45:10 1999
@@ -0,0 +1,137 @@
+/*
+
+kHTTPd -- the next generation
+
+Accept connections
+
+*/
+/****************************************************************
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2, or (at your option)
+ *	any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program; if not, write to the Free Software
+ *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ****************************************************************/
+
+#include "structure.h"
+#include "prototypes.h"
+#include "sysctl.h"
+
+#include <linux/smp_lock.h>
+
+/*
+
+Purpose:
+
+AcceptConnections puts all "accepted" connections in the 
+"WaitForHeader" queue.
+
+Return value:
+	The number of accepted connections
+*/
+
+
+int AcceptConnections(const int CPUNR, struct socket *Socket)
+{
+	struct http_request *NewRequest;
+	struct socket *NewSock;
+	int count = 0;
+	int error;
+
+	EnterFunction("AcceptConnections");
+	
+	if (atomic_read(&ConnectCount)>sysctl_khttpd_maxconnect)
+	{
+		LeaveFunction("AcceptConnections - to many active connections");
+		return 0;
+	}
+	
+	if (Socket==NULL) return 0;
+	
+	/* 
+	   Quick test to see if there are connections on the queue.
+	   This is cheaper than accept() itself because this saves us
+	   the allocation of a new socket. (Which doesn't seem to be 
+	   used anyway)
+	*/
+	lock_sock(Socket->sk);
+   	if (Socket->sk->tp_pinfo.af_tcp.syn_wait_queue==NULL)
+	{
+	  	release_sock(Socket->sk);
+		return 0;
+	}
+	release_sock(Socket->sk);
+	
+	error = 0;	
+	while (error>=0)
+	{
+		NewSock = sock_alloc();
+		if (NewSock==NULL)
+			break;
+			
+		lock_kernel(); 	/* Required for the TCPIP-stack in 2.3.13 */
+				/* This is actually bogus, since accept() releases
+				   it immediatly again. This will be fixed
+				   eventually though. */
+			
+			
+		NewSock->type = Socket->type;
+		(void)Socket->ops->dup(NewSock,Socket);
+		
+		
+		error = Socket->ops->accept(Socket,NewSock,O_NONBLOCK);
+		
+		unlock_kernel();
+
+		if ((error<0)&&(NewSock!=NULL))
+		{
+			sock_release(NewSock);
+			break;
+		}
+		
+			
+		if (NewSock==NULL)
+			break;
+		
+		
+		
+		/* Allocate a request-entry for the connection */
+		NewRequest = kmalloc(sizeof(struct http_request),(int)GFP_KERNEL); 
+		
+		if (NewRequest == NULL)
+		{
+			Send50x(NewSock); 	/* Service not available. Try again later */
+			sock_release(NewSock);
+			error = -1;
+			break;
+		}
+		memset(NewRequest,0,sizeof(struct http_request));  
+		
+		NewRequest->sock = NewSock;
+		
+		NewRequest->Next = threadinfo[CPUNR].WaitForHeaderQueue;
+		
+		init_waitqueue_entry(&NewRequest->sleep,current);
+		
+		add_wait_queue(NewSock->sk->sleep,&(NewRequest->sleep));
+		
+		threadinfo[CPUNR].WaitForHeaderQueue = NewRequest;
+		
+		atomic_inc(&ConnectCount);
+
+	
+		count++;
+	}		
+	
+	LeaveFunction("AcceptConnections");
+	return count;
+}
diff -u --recursive --new-file v2.3.13/linux/net/khttpd/datasending.c linux/net/khttpd/datasending.c
--- v2.3.13/linux/net/khttpd/datasending.c	Wed Dec 31 16:00:00 1969
+++ linux/net/khttpd/datasending.c	Wed Aug 18 09:49:42 1999
@@ -0,0 +1,194 @@
+/*
+
+kHTTPd -- the next generation
+
+Send actual file-data to the connections
+
+*/
+/****************************************************************
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2, or (at your option)
+ *	any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program; if not, write to the Free Software
+ *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ****************************************************************/
+
+/*
+
+Purpose:
+
+DataSending does the actual sending of file-data to the socket.
+
+Note: Since asynchronous reads do not -yet- exists, this might block!
+
+Return value:
+	The number of requests that changed status (ie: made some progress)
+*/
+
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+
+#include <net/tcp.h>
+
+#include <asm/uaccess.h>
+#include <linux/smp_lock.h>
+
+#include "structure.h"
+#include "prototypes.h"
+
+static	char	*Block[CONFIG_KHTTPD_NUMCPU];
+
+
+int DataSending(const int CPUNR)
+{
+	struct http_request *CurrentRequest,**Prev;
+	int count = 0;
+	
+	EnterFunction("DataSending");
+	
+	Prev = &(threadinfo[CPUNR].DataSendingQueue);
+	CurrentRequest = threadinfo[CPUNR].DataSendingQueue;
+	while (CurrentRequest!=NULL)
+	{
+		int ReadSize,Space;
+		int retval;
+		mm_segment_t oldfs;
+
+
+		/* First, test if the socket has any buffer-space left.
+		   If not, no need to actually try to send something.  */
+		  
+		
+		Space=4096;
+		if (CurrentRequest->sock->sk!=NULL)
+		{
+			lock_sock(CurrentRequest->sock->sk);
+			Space = sock_wspace(CurrentRequest->sock->sk);
+			release_sock(CurrentRequest->sock->sk);
+		}
+		
+		ReadSize = min(4096,CurrentRequest->FileLength - CurrentRequest->BytesSent);
+		ReadSize = min(ReadSize , Space );
+		
+		if (ReadSize>0)
+		{
+			/* This part does a redundant data-copy. To bad for now. 
+			   In the future, we might want to nick the data right out
+			   of the page-cache
+			*/
+		
+			CurrentRequest->filp->f_pos = CurrentRequest->BytesSent;
+		
+			oldfs = get_fs(); set_fs(KERNEL_DS);
+			retval = CurrentRequest->filp->f_op->read(CurrentRequest->filp, Block[CPUNR], ReadSize, &CurrentRequest->filp->f_pos);
+			set_fs(oldfs);
+		
+			if (retval>0)
+			{
+				retval = SendBuffer_async(CurrentRequest->sock,Block[CPUNR],(size_t)retval);
+				if (retval>0)
+				{
+					CurrentRequest->BytesSent += retval;
+					count++;
+				
+				}
+			}
+		
+		}
+		lock_sock(CurrentRequest->sock->sk);
+		
+		/* 
+		   If end-of-file or closed connection: Finish this request 
+		   by moving it to the "logging" queue. 
+		*/
+		if ((CurrentRequest->BytesSent>=CurrentRequest->FileLength)||
+		   (CurrentRequest->sock->sk->state !=TCP_ESTABLISHED))
+		{
+			struct http_request *Next;
+			Next = CurrentRequest->Next;
+						
+			if  (CurrentRequest->sock->sk->state ==TCP_ESTABLISHED)
+			{
+			
+				CurrentRequest->sock->sk->nonagle = 0;
+				CurrentRequest->sock->sk->linger = 0;
+				tcp_push_pending_frames(CurrentRequest->sock->sk,&(CurrentRequest->sock->sk->tp_pinfo.af_tcp));
+			}
+			
+			release_sock(CurrentRequest->sock->sk);
+
+
+
+			(*Prev) = CurrentRequest->Next;
+			
+			CurrentRequest->Next = threadinfo[CPUNR].LoggingQueue;
+			threadinfo[CPUNR].LoggingQueue = CurrentRequest;	
+				
+			CurrentRequest = Next;
+			continue;
+		
+		}
+		release_sock(CurrentRequest->sock->sk);
+		
+
+		Prev = &(CurrentRequest->Next);	
+		CurrentRequest = CurrentRequest->Next;
+	}
+	
+	LeaveFunction("DataSending");
+	return count;
+}
+
+int InitDataSending(int ThreadCount)
+{
+	int I,I2;
+	
+	EnterFunction("InitDataSending");
+	I=0;
+	while (I<ThreadCount)
+	{
+		Block[I] = (char*)get_free_page((int)GFP_KERNEL);
+		if (Block[I] == NULL) 
+		{
+			I2=0;
+			while (I2<I-1)
+			{
+				free_page((unsigned long)Block[I2++]);
+			}
+			LeaveFunction("InitDataSending - abort");
+			return -1;
+		}
+		I++;
+	}
+	LeaveFunction("InitDataSending");
+	return 0;		
+}
+
+void StopDataSending(const int CPUNR)
+{
+	struct http_request *CurrentRequest,*Next;
+	
+	EnterFunction("StopDataSending");
+	CurrentRequest = threadinfo[CPUNR].DataSendingQueue;
+
+	while (CurrentRequest!=NULL)
+	{	
+		Next = CurrentRequest->Next;
+		CleanUpRequest(CurrentRequest);
+		CurrentRequest=Next;		
+	}
+	
+	threadinfo[CPUNR].DataSendingQueue = NULL;
+
+	free_page( (unsigned long)Block[CPUNR]);
+	LeaveFunction("StopDataSending");
+}
diff -u --recursive --new-file v2.3.13/linux/net/khttpd/logging.c linux/net/khttpd/logging.c
--- v2.3.13/linux/net/khttpd/logging.c	Wed Dec 31 16:00:00 1969
+++ linux/net/khttpd/logging.c	Wed Aug 18 09:45:10 1999
@@ -0,0 +1,95 @@
+/*
+
+kHTTPd -- the next generation
+
+logging.c takes care of shutting down a connection.
+
+*/
+/****************************************************************
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2, or (at your option)
+ *	any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program; if not, write to the Free Software
+ *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ****************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/smp_lock.h>
+#include <net/tcp.h>
+#include <asm/uaccess.h>
+#include "structure.h"
+#include "prototypes.h"
+
+/*
+
+Purpose:
+
+Logging() terminates "finished" connections and will eventually log them to a 
+userspace daemon.
+
+Return value:
+	The number of requests that changed status, thus the number of connections
+	that shut down.
+*/
+
+
+int Logging(const int CPUNR)
+{
+	struct http_request *CurrentRequest,*Req;
+	int count = 0;
+	
+	EnterFunction("Logging");
+	
+	CurrentRequest = threadinfo[CPUNR].LoggingQueue;
+	
+	/* For now, all requests are removed immediatly, but this changes
+	   when userspace-logging is added. */
+	   
+	while (CurrentRequest!=NULL)
+	{
+
+		Req = CurrentRequest->Next;
+
+		CleanUpRequest(CurrentRequest);
+		
+		threadinfo[CPUNR].LoggingQueue = Req;
+			
+		CurrentRequest = Req;
+	
+		count++;
+		
+	}
+	
+	LeaveFunction("Logging");
+	return count;
+}
+
+
+
+void StopLogging(const int CPUNR)
+{
+	struct http_request *CurrentRequest,*Next;
+	
+	EnterFunction("StopLogging");
+	CurrentRequest = threadinfo[CPUNR].LoggingQueue;
+	
+	while (CurrentRequest!=NULL)
+	{
+		Next=CurrentRequest->Next;
+		CleanUpRequest(CurrentRequest);
+		CurrentRequest=Next;		
+	}
+	
+	threadinfo[CPUNR].LoggingQueue = NULL;
+	LeaveFunction("StopLogging");
+}
diff -u --recursive --new-file v2.3.13/linux/net/khttpd/main.c linux/net/khttpd/main.c
--- v2.3.13/linux/net/khttpd/main.c	Wed Dec 31 16:00:00 1969
+++ linux/net/khttpd/main.c	Wed Aug 18 09:50:01 1999
@@ -0,0 +1,394 @@
+/*
+
+kHTTPd -- the next generation
+
+Main program
+
+
+kHTTPd TNG consists of 1 thread, this main-thread handles ALL connections
+simultanious. It does this by keeping queues with the requests in different
+stages.
+
+The stages are
+
+<not accepted> 		-	TCP/IP connection is not accepted yet
+WaitForHeaders		-	Connection is accepted, waiting for headers
+DataSending		-	Headers decoded, sending file-data
+Userspace		-	Requires userspace daemon 
+Logging			-	The request is finished, cleanup and logging
+
+A typical flow for a request would be:
+
+<not accepted>
+WaitForHeaders
+DataSending
+Logging
+
+or
+
+<not accepted>
+WaitForHeaders
+Userspace
+
+
+
+*/
+/****************************************************************
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2, or (at your option)
+ *	any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program; if not, write to the Free Software
+ *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ****************************************************************/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/init.h>
+#include <linux/wait.h>
+#include <linux/smp_lock.h>
+#include <asm/unistd.h>
+
+#include "structure.h"
+#include "prototypes.h"
+#include "sysctl.h"
+
+struct khttpd_threadinfo threadinfo[CONFIG_KHTTPD_NUMCPU];  /* The actual work-queues */
+
+
+atomic_t	ConnectCount;
+atomic_t	DaemonCount;
+
+static int	ActualThreads; /* The number of actual, active threads */
+
+
+static int ConnectionsPending(int CPUNR)
+{
+	if (threadinfo[CPUNR].DataSendingQueue!=NULL) return O_NONBLOCK;
+	if (threadinfo[CPUNR].WaitForHeaderQueue!=NULL) return O_NONBLOCK;
+	if (threadinfo[CPUNR].LoggingQueue!=NULL) return O_NONBLOCK;
+	if (threadinfo[CPUNR].UserspaceQueue!=NULL) return O_NONBLOCK;
+  return 0;
+}
+
+
+
+static wait_queue_head_t DummyWQ[CONFIG_KHTTPD_NUMCPU];
+static atomic_t Running[CONFIG_KHTTPD_NUMCPU]; 
+
+static int MainDaemon(void *cpu_pointer)
+{
+	int CPUNR;
+	sigset_t tmpsig;
+	
+	DECLARE_WAITQUEUE(main_wait,current);
+	
+	MOD_INC_USE_COUNT;
+
+	
+	current->state |= TASK_EXCLUSIVE;
+
+	CPUNR=0;
+	if (cpu_pointer!=NULL)
+	CPUNR=(int)*(int*)cpu_pointer;
+
+	sprintf(current->comm,"khttpd - %i",CPUNR);
+	lock_kernel();   /* This seems to be required for exit_mm */
+	exit_mm(current);
+	
+	init_waitqueue_head(&(DummyWQ[CPUNR]));
+	
+
+	/* Block all signals except SIGKILL, SIGSTOP and SIGHUP */
+	spin_lock_irq(&current->sigmask_lock);
+	tmpsig = current->blocked;
+	siginitsetinv(&current->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP)| sigmask(SIGHUP));
+	recalc_sigpending(current);
+	spin_unlock_irq(&current->sigmask_lock);
+	
+	
+	if (MainSocket->sk==NULL)
+	 	return 0;
+	add_wait_queue_exclusive(MainSocket->sk->sleep,&(main_wait));
+	atomic_inc(&DaemonCount);
+	atomic_set(&Running[CPUNR],1);
+	
+	while (sysctl_khttpd_stop==0)
+	{
+		int changes = 0;
+				
+
+		
+		changes +=AcceptConnections(CPUNR,MainSocket);
+		if (ConnectionsPending(CPUNR))
+		{
+			changes +=WaitForHeaders(CPUNR);
+			changes +=DataSending(CPUNR);
+			changes +=Userspace(CPUNR);
+			changes +=Logging(CPUNR);
+			/* Test for incomming connections _again_, because it is possible
+			   one came in during the other steps, and the wakeup doesn't happen
+			   then.
+			*/
+			changes +=AcceptConnections(CPUNR,MainSocket);
+		}
+		
+		current->state = TASK_INTERRUPTIBLE|TASK_EXCLUSIVE;	
+		if (changes==0) 
+		{
+			(void)interruptible_sleep_on_timeout(&(DummyWQ[CPUNR]),1);	
+			if (CPUNR==0) 
+				UpdateCurrentDate();
+		}
+			
+		if (signal_pending(current)!=0)
+		{
+			(void)printk(KERN_NOTICE "kHTTPd: Ring Ring - signal received\n");
+			break;		  
+		}
+	
+	}
+	
+	remove_wait_queue(MainSocket->sk->sleep,&(main_wait));
+	
+	StopWaitingForHeaders(CPUNR);
+	StopDataSending(CPUNR);
+	StopUserspace(CPUNR);
+	StopLogging(CPUNR);
+	
+	atomic_set(&Running[CPUNR],0);
+	atomic_dec(&DaemonCount);
+	(void)printk(KERN_NOTICE "kHTTPd: Daemon %i has ended\n",CPUNR);
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static int CountBuf[CONFIG_KHTTPD_NUMCPU];
+
+static int errno;
+inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options);
+
+
+
+/*
+
+The ManagementDaemon has a very simple task: Start the real daemons when the user wants us
+to, and cleanup when the users wants to unload the module.
+
+Initially, kHTTPd didn't have this thread, but it is the only way to have "delayed activation",
+a feature required to prevent accidental activations resulting in unexpected backdoors.
+
+*/
+static int ManagementDaemon(void *unused)
+{
+	sigset_t tmpsig;
+	int waitpid_result;
+	
+	DECLARE_WAIT_QUEUE_HEAD(WQ);
+	
+	MOD_INC_USE_COUNT;
+	
+	sprintf(current->comm,"khttpd manager");
+	lock_kernel();   /* This seems to be required for exit_mm */
+	exit_mm(current);
+	
+
+	/* Block all signals except SIGKILL and SIGSTOP */
+	spin_lock_irq(&current->sigmask_lock);
+	tmpsig = current->blocked;
+	siginitsetinv(&current->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP) );
+	recalc_sigpending(current);
+	spin_unlock_irq(&current->sigmask_lock);
+
+
+	/* main loop */
+	while (sysctl_khttpd_unload==0)
+	{
+		int I;
+		
+		
+		/* First : wait for activation */
+		
+		sysctl_khttpd_start = 0;
+		
+		while ( (sysctl_khttpd_start==0) && (!signal_pending(current)) && (sysctl_khttpd_unload==0) )
+		{
+			current->state = TASK_INTERRUPTIBLE;
+			interruptible_sleep_on_timeout(&WQ,HZ); 
+		}
+		
+		if ( (signal_pending(current)) || (sysctl_khttpd_unload!=0) )
+		 	break;
+		 	
+		/* Then start listening and spawn the daemons */
+		 	
+		if (StartListening(sysctl_khttpd_serverport)==0)
+		{
+			continue;
+		}
+		
+		ActualThreads = sysctl_khttpd_threads;
+		if (ActualThreads<1) 
+			ActualThreads = 1;
+			
+		if (ActualThreads>CONFIG_KHTTPD_NUMCPU) 
+			ActualThreads = CONFIG_KHTTPD_NUMCPU;
+		
+		/* Write back the actual value */
+		
+		sysctl_khttpd_threads = ActualThreads;
+		
+		InitUserspace(ActualThreads);
+		
+		if (InitDataSending(ActualThreads)!=0)
+		{
+			StopListening();
+			continue;
+		}
+		if (InitWaitHeaders(ActualThreads)!=0)
+		{
+			I=0;
+			while (I<ActualThreads)
+			{
+				StopDataSending(I);
+				I++;
+			}
+			StopListening();
+			continue;
+		}
+	
+		/* Clean all queues */
+		memset(threadinfo, 0, sizeof(struct khttpd_threadinfo));
+
+
+		 	
+		I=0;
+		while (I<ActualThreads)
+		{
+			atomic_set(&Running[I],1);
+			(void)kernel_thread(MainDaemon,&(CountBuf[I]),0);
+			I++;
+		}
+		
+		/* Then wait for deactivation */
+		sysctl_khttpd_stop = 0;
+
+		while ( (sysctl_khttpd_stop==0) && (!signal_pending(current)) && (sysctl_khttpd_unload==0) )
+		{
+			if (atomic_read(&DaemonCount)<ActualThreads)
+			{
+				I=0;
+				while (I<ActualThreads)
+				{
+					if (atomic_read(&Running[I])==0)
+					{
+						atomic_set(&Running[I],1);
+						(void)kernel_thread(MainDaemon,&(CountBuf[I]),0);
+						(void)printk(KERN_CRIT "kHTTPd: Restarting daemon %i \n",I);
+					}
+					I++;
+				}
+			}
+			interruptible_sleep_on_timeout(&WQ,HZ);
+			
+			/* reap the daemons */
+			waitpid_result = waitpid(-1,NULL,__WCLONE|WNOHANG);
+			
+		}
+		
+		
+		/* The user wants us to stop. So stop listening on the socket. */
+		if (sysctl_khttpd_stop!=0)	
+		{
+			/* Wait for the daemons to stop, one second per iteration */
+			while (atomic_read(&DaemonCount)>0)
+		 		interruptible_sleep_on_timeout(&WQ,HZ);
+			StopListening();
+		}
+
+		
+	
+	}
+	
+	sysctl_khttpd_stop = 1;
+
+	/* Wait for the daemons to stop, one second per iteration */
+	while (atomic_read(&DaemonCount)>0)
+ 		interruptible_sleep_on_timeout(&WQ,HZ);
+		
+		
+	waitpid_result = 1;
+	/* reap the zombie-daemons */
+	while (waitpid_result>0)
+		waitpid_result = waitpid(-1,NULL,__WCLONE|WNOHANG);
+		
+	StopListening();
+	
+	
+	(void)printk(KERN_NOTICE "kHTTPd: Management daemon stopped. \n        You can unload the module now.\n");
+
+	MOD_DEC_USE_COUNT;
+
+	return 0;
+}
+
+int __init khttpd_init(void)
+{
+	int I;
+	
+	I=0;
+	while (I<CONFIG_KHTTPD_NUMCPU)
+	{
+		CountBuf[I]=I;
+		
+		I++;
+	}
+	
+	atomic_set(&ConnectCount,0);
+	atomic_set(&DaemonCount,0);
+	
+
+	/* Maybe the mime-types will be set-able through sysctl in the future */	   
+		
+ 	AddMimeType(".htm","text/html");
+ 	AddMimeType("html","text/html");
+ 	AddMimeType(".gif","image/gif");
+ 	AddMimeType(".jpg","image/jpeg");
+ 	AddMimeType(".png","image/png");
+ 	AddMimeType("tiff","image/tiff");
+ 	AddMimeType(".zip","application/zip");
+	AddMimeType(".pdf","application/pdf");
+ 	AddMimeType("r.gz","application/x-gtar");
+ 	AddMimeType(".tgz","application/x-gtar");
+	AddMimeType(".deb","application/x-debian-package");
+	AddMimeType("lass","application/x-java");
+	AddMimeType(".mp3","audio/mpeg");
+	AddMimeType(".txt","text/plain");
+	
+	AddDynamicString("..");
+	AddDynamicString("cgi-bin");
+
+	StartSysctl();
+	
+	(void)kernel_thread(ManagementDaemon,NULL,0);
+	
+	return 0;
+}
+
+void khttpd_cleanup(void)
+{
+	EndSysctl();
+}
+
+	module_init(khttpd_init)
+	module_exit(khttpd_cleanup)
diff -u --recursive --new-file v2.3.13/linux/net/khttpd/make_times_h.c linux/net/khttpd/make_times_h.c
--- v2.3.13/linux/net/khttpd/make_times_h.c	Wed Dec 31 16:00:00 1969
+++ linux/net/khttpd/make_times_h.c	Wed Aug 18 09:45:10 1999
@@ -0,0 +1,122 @@
+/*
+
+This program generates the "times.h" file with the zulu-times of the first of
+every month of a decade.
+
+*/
+/****************************************************************
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2, or (at your option)
+ *	any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program; if not, write to the Free Software
+ *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ****************************************************************/
+
+#include <time.h>
+#include <stdio.h>
+
+static time_t GetDay(int D,int M,int Y)
+{
+	struct tm TM;
+	
+	TM.tm_sec    	= 0;
+	TM.tm_min	= 0;
+	TM.tm_hour	= 0;
+	TM.tm_mday	= D;
+	TM.tm_mon	= M;
+	TM.tm_wday	= 0;
+	TM.tm_yday	= 0;
+	TM.tm_year	= Y-1900;
+	TM.tm_isdst	= 0;
+	
+	return mktime(&TM);
+	
+}
+static int WeekGetDay(int D,int M,int Y)
+{
+	struct tm TM;
+	
+	TM.tm_sec    	= 0;
+	TM.tm_min	= 0;
+	TM.tm_hour	= 0;
+	TM.tm_mday	= D;
+	TM.tm_mon	= M;
+	TM.tm_year	= Y-1900;
+	TM.tm_isdst	= 0;
+	TM.tm_wday	= 0;
+	TM.tm_yday	= 0;
+	
+	(void)mktime(&TM);
+	
+	return TM.tm_wday;
+	
+}
+
+int main(void)
+{
+	int M,Y;
+	FILE *file;
+	
+	file=fopen("times.h","w");
+	
+	if (file==NULL) 
+		return 0; 
+	
+	fprintf(file,"static time_t TimeDays[10][13] = { \n");
+	
+	Y=1997;
+	while (Y<2007)
+	{
+		M=0;
+		fprintf(file," { ");
+		while (M<12)
+		{
+			fprintf(file,"%i",(int)GetDay(1,M,Y));
+     		  	fprintf(file,",\t");
+		
+			M++;
+		}
+		
+		fprintf(file,"%i } ",(int)GetDay(1,0,Y+1));
+		if (Y!=2006) fprintf(file,",");
+		fprintf(file,"\n");
+		Y++;
+	}
+	fprintf(file,"};\n");
+
+	fprintf(file,"static int WeekDays[10][13] = { \n");
+	
+	Y=1997;
+	while (Y<2007)
+	{
+		M=0;
+		fprintf(file," { ");
+		while (M<12)
+		{
+			fprintf(file,"%i",(int)WeekGetDay(1,M,Y));
+     		  	fprintf(file,",\t");
+		
+			M++;
+		}
+		
+		fprintf(file,"%i } ",(int)WeekGetDay(1,0,Y+1));
+		if (Y!=2006) fprintf(file,",");
+		fprintf(file,"\n");
+		Y++;
+	}
+	fprintf(file,"};\n");
+	fprintf(file,"#define KHTTPD_YEAROFFSET   1997\n");
+	fprintf(file,"#define KHTTPD_NUMYEARS     10\n");
+	(void)fclose(file);
+	
+	return 0;
+}
diff -u --recursive --new-file v2.3.13/linux/net/khttpd/misc.c linux/net/khttpd/misc.c
--- v2.3.13/linux/net/khttpd/misc.c	Wed Dec 31 16:00:00 1969
+++ linux/net/khttpd/misc.c	Wed Aug 18 09:45:10 1999
@@ -0,0 +1,253 @@
+/*
+
+kHTTPd -- the next generation
+
+General functions
+
+*/
+/****************************************************************
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2, or (at your option)
+ *	any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program; if not, write to the Free Software
+ *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ****************************************************************/
+
+#include <linux/kernel.h>
+
+#include <linux/ctype.h>
+#include <linux/errno.h>
+#include <linux/malloc.h>
+#include <linux/net.h>
+#include <linux/sched.h>
+#include <linux/skbuff.h>
+#include <linux/unistd.h>
+#include <linux/file.h>
+#include <linux/smp_lock.h>
+
+#include <net/ip.h>
+#include <net/sock.h>
+
+#include <asm/atomic.h>
+#include <asm/errno.h>
+#include <asm/semaphore.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+
+#include "structure.h"
+#include "prototypes.h"
+
+#ifndef ECONNRESET
+#define ECONNRESET 102
+#endif
+
+
+/*
+
+Readrest reads and discards all pending input on a socket. This is required
+before closing the socket.
+
+*/
+static void ReadRest(struct socket *sock)
+{
+	struct msghdr		msg;
+	struct iovec		iov;
+	int			len;
+
+	mm_segment_t		oldfs;
+	
+	
+	EnterFunction("ReadRest");
+	
+	
+	if (sock->sk==NULL)
+		return;
+	if (sock->sk->state!=TCP_ESTABLISHED)
+		return;
+
+	len = 1;
+		
+	while (len>0)
+	{
+		static char		Buffer[1024];   /* Never read, so doesn't need to
+							   be SMP safe */
+
+		msg.msg_name     = 0;
+		msg.msg_namelen  = 0;
+		msg.msg_iov	 = &iov;
+		msg.msg_iovlen   = 1;
+		msg.msg_control  = NULL;
+		msg.msg_controllen = 0;
+		msg.msg_flags    = MSG_DONTWAIT;
+	
+		msg.msg_iov->iov_base = &Buffer[0];
+		msg.msg_iov->iov_len  = (__kernel_size_t)1024;
+	
+		len = 0;
+		oldfs = get_fs(); set_fs(KERNEL_DS);
+		len = sock_recvmsg(sock,&msg,1024,MSG_DONTWAIT);
+		set_fs(oldfs);
+	}
+	LeaveFunction("ReadRest");
+}
+
+
+/*
+
+CleanUpRequest takes care of shutting down the connection, closing the file-pointer
+and releasing the memory of the request-structure. Do not try to access it afterwards!
+
+*/
+void CleanUpRequest(struct http_request *Req)
+{
+	EnterFunction("CleanUpRequest");	
+	
+	/* Close the socket ....*/
+	if ((Req->sock!=NULL)&&(Req->sock->sk!=NULL))
+	{
+		ReadRest(Req->sock);
+		lock_kernel();   /* 2.3.11 quirk - needed for 2.3.13 ?? */
+		lock_sock(Req->sock->sk);
+		remove_wait_queue(Req->sock->sk->sleep,&(Req->sleep));
+		release_sock(Req->sock->sk);
+	    	sock_release(Req->sock);
+	    	unlock_kernel();  /* 2.3.13 quirk */
+	}
+	
+	/* ... and the file-pointer ... */
+	if (Req->filp!=NULL)
+	{
+	    	fput(Req->filp);
+	    	Req->filp = NULL;
+	}
+	
+	
+	/* ... and release the memory for the structure. */
+	kfree(Req);
+	
+	atomic_dec(&ConnectCount);
+	LeaveFunction("CleanUpRequest");
+}
+
+
+/*
+
+SendBuffer and Sendbuffer_async send "Length" bytes from "Buffer" to the "sock"et.
+The _async-version is non-blocking.
+
+A positive return-value indicates the number of bytes sent, a negative value indicates
+an error-condition.
+
+*/
+int SendBuffer(struct socket *sock, const char *Buffer,const size_t Length)
+{
+	struct msghdr	msg;
+	mm_segment_t	oldfs;
+	struct iovec	iov;
+	int 		len;
+	
+	EnterFunction("SendBuffer");
+	
+	msg.msg_name     = 0;
+	msg.msg_namelen  = 0;
+	msg.msg_iov	 = &iov;
+	msg.msg_iovlen   = 1;
+	msg.msg_control  = NULL;
+	msg.msg_controllen = 0;
+	msg.msg_flags    = MSG_NOSIGNAL;    
+	msg.msg_iov->iov_len = (__kernel_size_t)Length;
+	msg.msg_iov->iov_base = (char*) Buffer;
+	
+	
+	len = 0;
+	
+	if (sock->sk->state==TCP_ESTABLISHED)
+	{
+		oldfs = get_fs(); set_fs(KERNEL_DS);
+		len = sock_sendmsg(sock,&msg,(size_t)(Length-len));
+		set_fs(oldfs);
+		LeaveFunction("SendBuffer");
+		return len;	
+	}
+	else
+		return -ECONNRESET;
+}
+
+int SendBuffer_async(struct socket *sock, const char *Buffer,const size_t Length)
+{
+	struct msghdr	msg;
+	mm_segment_t	oldfs;
+	struct iovec	iov;
+	int 		len;
+	
+	EnterFunction("SendBuffer_async");
+	msg.msg_name     = 0;
+	msg.msg_namelen  = 0;
+	msg.msg_iov	 = &iov;
+	msg.msg_iovlen   = 1;
+	msg.msg_control  = NULL;
+	msg.msg_controllen = 0;
+	msg.msg_flags    = MSG_DONTWAIT|MSG_NOSIGNAL;    
+	msg.msg_iov->iov_base = (char*) Buffer;
+	msg.msg_iov->iov_len  = (__kernel_size_t)Length;
+	
+
+	if (sock->sk)
+	{	
+		oldfs = get_fs(); set_fs(KERNEL_DS);
+		len = sock_sendmsg(sock,&msg,(size_t)(Length));
+		set_fs(oldfs);
+	} else
+	{
+		return -ECONNRESET;
+	}
+	
+	LeaveFunction("SendBuffer_async");
+	return len;	
+}
+
+
+
+
+/* 
+
+HTTP header shortcuts. Hardcoded since these might be called in a low-memory
+situation, and they don't change anyhow.
+
+*/
+
+static char NoPerm[] = "403 Permission denied\r\nServer: kHTTPd 0.1.6\r\n\r\n Permission denied";
+static char TryLater[] = "500 Try again later\r\nServer: kHTTPd 0.1.6\r\n\r\n Try again later";
+static char NotModified[] = "304 Not Modified\r\nServer: kHTTPd 0.1.6\r\n\r\n";
+
+
+void Send403(struct socket *sock)
+{
+	EnterFunction("Send403");
+	(void)SendBuffer(sock,NoPerm,strlen(NoPerm));
+	LeaveFunction("Send403");
+}
+
+void Send304(struct socket *sock)
+{
+	EnterFunction("Send304");
+	(void)SendBuffer(sock,NotModified,strlen(NoPerm));
+	LeaveFunction("Send304");
+}
+
+void Send50x(struct socket *sock)
+{
+	EnterFunction("Send50x");
+	(void)SendBuffer(sock,TryLater,strlen(TryLater));
+	LeaveFunction("Send50x");
+}
+
diff -u --recursive --new-file v2.3.13/linux/net/khttpd/prototypes.h linux/net/khttpd/prototypes.h
--- v2.3.13/linux/net/khttpd/prototypes.h	Wed Dec 31 16:00:00 1969
+++ linux/net/khttpd/prototypes.h	Wed Aug 18 09:45:10 1999
@@ -0,0 +1,131 @@
+#ifndef _INCLUDE_GUARD_PROTOTYPES_H
+#define _INCLUDE_GUARD_PROTOTYPES_H
+
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/net.h>
+#include <linux/time.h>
+#include <linux/types.h>
+#include <linux/wait.h>
+#include <net/sock.h>
+#include <asm/uaccess.h>
+
+#include "structure.h"
+
+
+/* General defines and stuff */
+
+
+#define CONFIG_KHTTPD_NUMCPU 16    /* Maximum number of threads */
+
+/* the TCP/IP stack defines a __BROKEN__ set of min/max functions !! */
+/* So we better define our own.                                      */
+
+/* Broken means: working on unsigned data only, which is not acceptable
+ 		 for kHTTPd and probably a lot of other functions. */
+
+#undef min
+#undef max
+#define min(a,b)  ( (a) < (b) ? (a) : (b) )
+#define max(a,b)  ( (a) > (b) ? (a) : (b) )
+
+#ifdef OOPSTRACE
+#define EnterFunction(x)   printk("Enter: %s, %s line %i\n",x,__FILE__,__LINE__)
+#define LeaveFunction(x)   printk("Leave: %s, %s line %i\n",x,__FILE__,__LINE__)
+#else
+#define EnterFunction(x)   do {} while (0)
+#define LeaveFunction(x)   do {} while (0)
+#endif
+
+
+
+/* sockets.c */
+int  StartListening(const int Port);
+void StopListening(void);
+
+extern struct socket *MainSocket;
+
+
+/* sysctl.c */
+void StartSysctl(void);
+void EndSysctl(void);
+
+extern int sysctl_khttpd_stop;
+
+
+/* main.c */
+
+
+extern struct khttpd_threadinfo threadinfo[CONFIG_KHTTPD_NUMCPU];
+extern char CurrentTime[];
+extern atomic_t ConnectCount;
+extern struct wait_queue main_wait[CONFIG_KHTTPD_NUMCPU];
+
+/* misc.c */
+
+void CleanUpRequest(struct http_request *Req);
+int SendBuffer(struct socket *sock, const char *Buffer,const size_t Length);
+int SendBuffer_async(struct socket *sock, const char *Buffer,const size_t Length);
+void Send403(struct socket *sock);
+void Send304(struct socket *sock);
+void Send50x(struct socket *sock);
+
+/* accept.c */
+
+int AcceptConnections(const int CPUNR,struct socket *Socket);
+
+/* waitheaders.c */
+
+int WaitForHeaders(const int CPUNR);
+void StopWaitingForHeaders(const int CPUNR);
+int InitWaitHeaders(int ThreadCount);
+
+/* datasending.c */
+
+int DataSending(const int CPUNR);
+void StopDataSending(const int CPUNR);
+int InitDataSending(int ThreadCount);
+
+
+/* userspace.c */
+
+int Userspace(const int CPUNR);
+void StopUserspace(const int CPUNR);
+void InitUserspace(const int CPUNR);
+
+
+/* rfc_time.c */
+
+void time_Unix2RFC(const time_t Zulu,char *Buffer);
+void UpdateCurrentDate(void);
+time_t mimeTime_to_UnixTime(char *Q);
+extern int CurrentTime_i;
+
+/* rfc.c */
+
+void ParseHeader(char *Buffer,const int length, struct http_request *Head);
+char *ResolveMimeType(const char *File,__kernel_size_t *Len);
+void AddMimeType(const char *Ident,const char *Type);
+void SendHTTPHeader(struct http_request *Request);
+
+
+
+/* security.c */
+
+struct file *OpenFileForSecurity(char *Filename);
+void AddDynamicString(const char *String);
+void GetSecureString(char *String);
+
+
+/* logging.c */
+
+int Logging(const int CPUNR);
+void StopLogging(const int CPUNR);
+
+
+/* Other prototypes */
+
+
+
+#endif
diff -u --recursive --new-file v2.3.13/linux/net/khttpd/rfc.c linux/net/khttpd/rfc.c
--- v2.3.13/linux/net/khttpd/rfc.c	Wed Dec 31 16:00:00 1969
+++ linux/net/khttpd/rfc.c	Wed Aug 18 09:50:16 1999
@@ -0,0 +1,375 @@
+/*
+
+kHTTPd -- the next generation
+
+RFC related functions (headers and stuff)
+
+*/
+
+/****************************************************************
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2, or (at your option)
+ *	any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program; if not, write to the Free Software
+ *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ****************************************************************/
+
+
+#include <linux/kernel.h>
+
+#include <linux/ctype.h>
+#include <linux/errno.h>
+#include <linux/malloc.h>
+#include <linux/net.h>
+#include <linux/sched.h>
+#include <linux/skbuff.h>
+#include <linux/unistd.h>
+#include <linux/file.h>
+#include <linux/smp_lock.h>
+
+#include <net/ip.h>
+#include <net/sock.h>
+
+#include <asm/atomic.h>
+#include <asm/semaphore.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/msr.h>
+
+
+#include "prototypes.h"
+#include "structure.h"
+#include "sysctl.h"
+
+
+#define KHTTPD_NUMMIMETYPES 	40
+
+static atomic_t	MimeCount;
+
+struct MimeType
+{
+	__u32 	identifier;
+	char	type[64-sizeof(__u32)-sizeof(__kernel_size_t)];  
+	__kernel_size_t	len;
+};
+
+static struct MimeType	MimeTypes[KHTTPD_NUMMIMETYPES];
+
+
+void AddMimeType(const char *Ident,const char *Type)
+{	
+	__u32	*I;
+	
+	EnterFunction("AddMimeType");
+	
+	if (strlen(Ident)!=4) 
+   	{	
+   		(void)printk(KERN_ERR "httpd: Only 4-byte mime-identifiers are accepted\n");
+   		return;
+   	}
+
+	if (strlen(Type)>(64-sizeof(__u32)-sizeof(__kernel_size_t) ) )  
+   	{	
+   		(void)printk(KERN_ERR "httpd: Mime-string too long.\n");
+   		return;
+   	}
+   	
+   	I=(__u32*)Ident;
+   	
+   	/* FIXME: Need to lock-down all access to the mime-structure here */
+   	/*        For now, just don't add mime-types after initialisation */
+   	
+   	
+   	MimeTypes[atomic_read(&MimeCount)].identifier=*I;
+   	strcpy(MimeTypes[atomic_read(&MimeCount)].type,Type);
+   	MimeTypes[atomic_read(&MimeCount)].len = strlen(Type);
+   	
+   	atomic_inc(&MimeCount);
+   	LeaveFunction("AddMimeType");
+}
+
+
+char *ResolveMimeType(const char *File,__kernel_size_t *Len)
+/*
+
+	The returned string is for READ ONLY, ownership of the memory is NOT
+	transfered.
+
+*/
+{	
+	__u32	*I;
+	int pos,lc,filelen;
+	
+	EnterFunction("ResolveMimeType");
+	
+	*Len = 0;
+	
+	if (File==NULL)
+		return NULL;
+	
+	filelen = (int)strlen(File);
+	
+	if (filelen<4) 
+   	{	
+   		return NULL;
+   	}
+   	
+   	/* The Merced-people are NOT going to like this! So this has to be fixed
+   	   in a later stage. */
+
+	pos = filelen-4;
+   	I=(__u32*)(File+pos);
+   	
+   	lc=0;
+   	
+   	while (lc<atomic_read(&MimeCount))
+ 	{
+   		if (MimeTypes[lc].identifier == *I)
+   		{
+   			*Len = MimeTypes[lc].len;
+   			LeaveFunction("ResolveMimeType - success");
+   	  		return MimeTypes[lc].type;
+   	  	}
+   	  	lc++;
+   	} 	
+   	
+	if (sysctl_khttpd_sloppymime)
+	{
+		*Len = MimeTypes[0].len;  
+		LeaveFunction("ResolveMimeType - unknown");
+	   	return MimeTypes[0].type;
+	}
+	else
+	{
+		LeaveFunction("ResolveMimeType - failure");
+	   	return NULL;
+	}
+}
+
+
+static char HeaderPart1[] = "HTTP/1.0 200 OK\r\nServer: kHTTPd/0.1.6\r\nDate: ";
+#ifdef BENCHMARK
+static char HeaderPart1b[] ="HTTP/1.0 200 OK";
+#endif
+static char HeaderPart3[] = "\r\nContent-type: ";
+static char HeaderPart5[] = "\r\nLast-modified: ";
+static char HeaderPart7[] = "\r\nContent-length: ";
+static char HeaderPart9[] = "\r\n\r\n";
+
+#ifdef BENCHMARK
+/* In BENCHMARK-mode, just send the bare essentials */
+void SendHTTPHeader(struct http_request *Request)
+{
+	struct msghdr	msg;
+	mm_segment_t	oldfs;
+	struct iovec	iov[9];
+	int 		len,len2;
+	
+	
+	EnterFunction("SendHTTPHeader");
+		
+	msg.msg_name     = 0;
+	msg.msg_namelen  = 0;
+	msg.msg_iov	 = &iov[0];
+	msg.msg_iovlen   = 6;
+	msg.msg_control  = NULL;
+	msg.msg_controllen = 0;
+	msg.msg_flags    = 0;  /* Synchronous for now */
+	
+	iov[0].iov_base = HeaderPart1b;
+	iov[0].iov_len  = 15;
+	iov[1].iov_base = HeaderPart3;
+	iov[1].iov_len  = 16;
+	iov[2].iov_base = Request->MimeType;
+	iov[2].iov_len  = Request->MimeLength;
+	
+	iov[3].iov_base = HeaderPart7;
+	iov[3].iov_len  = 18;
+	
+	
+	sprintf(Request->LengthS,"%i",Request->FileLength);
+	iov[4].iov_base = Request->LengthS;
+	iov[4].iov_len  = strlen(Request->LengthS);
+	iov[5].iov_base = HeaderPart9;
+	iov[5].iov_len  = 4;
+	
+	len2=15+16+18+iov[2].iov_len+iov[4].iov_len+4;
+	
+	
+	len = 0;
+	
+
+	oldfs = get_fs(); set_fs(KERNEL_DS);
+	len = sock_sendmsg(Request->sock,&msg,len2);
+	set_fs(oldfs);
+
+	
+	return;	
+}
+#else
+void SendHTTPHeader(struct http_request *Request)
+{
+	struct msghdr	msg;
+	mm_segment_t	oldfs;
+	struct iovec	iov[9];
+	int 		len,len2;
+	__kernel_size_t	slen;
+	
+	EnterFunction("SendHTTPHeader");
+	
+	msg.msg_name     = 0;
+	msg.msg_namelen  = 0;
+	msg.msg_iov	 = &(iov[0]);
+	msg.msg_iovlen   = 9;
+	msg.msg_control  = NULL;
+	msg.msg_controllen = 0;
+	msg.msg_flags    = 0;  /* Synchronous for now */
+	
+	iov[0].iov_base = HeaderPart1;
+	iov[0].iov_len  = 45;
+	iov[1].iov_base = CurrentTime;
+	iov[1].iov_len  = 29;
+	iov[2].iov_base = HeaderPart3;
+	iov[2].iov_len  = 16;
+	
+	iov[3].iov_base = Request->MimeType;
+	iov[3].iov_len  = Request->MimeLength;
+	
+	iov[4].iov_base = HeaderPart5;
+	iov[4].iov_len  = 17;
+	iov[5].iov_base = &(Request->TimeS[0]);
+	iov[5].iov_len  = 29;
+	iov[6].iov_base = HeaderPart7;
+	iov[6].iov_len  = 18;
+	iov[7].iov_base = &(Request->LengthS[0]);
+	slen = strlen(Request->LengthS); 
+	iov[7].iov_len  = slen;
+	iov[8].iov_base = HeaderPart9;
+	iov[8].iov_len  = 4;
+	
+	len2=45+2*29+16+17+18+slen+4+iov[3].iov_len;
+	
+	len = 0;
+
+	oldfs = get_fs(); set_fs(KERNEL_DS);
+	len = sock_sendmsg(Request->sock,&msg,len2);
+	set_fs(oldfs);
+	LeaveFunction("SendHTTPHeader");
+	
+
+	return;	
+}
+#endif
+
+
+
+/* 
+
+Parse a HTTP-header. Be careful for buffer-overflows here, this is the most important
+place for this, since the remote-user controls the data.
+
+*/
+void ParseHeader(char *Buffer,const int length, struct http_request *Head)
+{
+	char *Endval,*EOL,*tmp;
+	
+	EnterFunction("ParseHeader");
+	Endval = Buffer + length;
+	
+	/* We want to parse only the first header if multiple headers are present */
+	tmp = strstr(Buffer,"\r\n\r\n"); 
+	if (tmp!=NULL)
+	    Endval = tmp;
+	
+	
+	while (Buffer<Endval)
+	{
+		if (isspace(Buffer[0]))
+		{
+			Buffer++;
+			continue;
+		}
+			
+		
+		EOL=strchr(Buffer,'\n');
+		
+		if (EOL==NULL) EOL=Endval;
+		
+		if (EOL-Buffer<4) 
+		{
+			Buffer++;
+			continue;
+		}
+		
+		if (strncmp("GET ",Buffer,4)==0)
+		{
+			int PrefixLen;
+			Buffer+=4;
+			
+			tmp=strchr(Buffer,' ');
+			if (tmp==0) 
+			{
+				tmp=EOL-1;
+				Head->HTTPVER = 9;
+			} else
+				Head->HTTPVER = 10;
+			
+			if (tmp>Endval) continue;
+			
+			strcpy(Head->FileName,sysctl_khttpd_docroot);
+			PrefixLen = strlen(sysctl_khttpd_docroot);
+			Head->FileNameLength = min(255,tmp-Buffer+PrefixLen);		
+			
+			strncat(Head->FileName,Buffer,min(255-PrefixLen,tmp-Buffer));
+					
+			Buffer=EOL+1;	
+#ifdef BENCHMARK
+			break;
+#endif						
+			continue;
+		}
+#ifndef BENCHMARK		
+		if (strncmp("If-Modified-Since: ",Buffer,19)==0)
+		{
+			Buffer+=19;
+			
+			strncpy(Head->IMS,Buffer,min(127,EOL-Buffer-1));
+					
+			Buffer=EOL+1;	
+			continue;
+		}
+
+		if (strncmp("User-Agent: ",Buffer,12)==0)
+		{
+			Buffer+=12;
+			
+			strncpy(Head->Agent,Buffer,min(127,EOL-Buffer-1));
+					
+			Buffer=EOL+1;	
+			continue;
+		}
+		
+
+		if (strncmp("Host: ",Buffer,6)==0)
+		{
+			Buffer+=6;
+			
+			strncpy(Head->Host,Buffer,min(127,EOL-Buffer-1));
+					
+			Buffer=EOL+1;	
+			continue;
+		}
+#endif		
+		Buffer = EOL+1;  /* Skip line */
+	}
+	LeaveFunction("ParseHeader");
+}
diff -u --recursive --new-file v2.3.13/linux/net/khttpd/rfc_time.c linux/net/khttpd/rfc_time.c
--- v2.3.13/linux/net/khttpd/rfc_time.c	Wed Dec 31 16:00:00 1969
+++ linux/net/khttpd/rfc_time.c	Wed Aug 18 09:51:31 1999
@@ -0,0 +1,227 @@
+/*
+
+Functions related to time:
+
+1) rfc (string) time to unix-time
+2) unix-time to rfc (string) time
+3) current time to rfc (string) time for the "Date:" header
+
+*/
+
+/****************************************************************
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2, or (at your option)
+ *	any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program; if not, write to the Free Software
+ *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ****************************************************************/
+
+#include <linux/time.h>
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <linux/ctype.h>
+
+
+#include "times.h"
+#include "prototypes.h"
+static char *dayName[7] = {
+	"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+};
+
+static char *monthName[12] = {
+	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+
+
+char CurrentTime[64];
+int  CurrentTime_i;
+
+
+static char itoa_h[60]={'0','0','0','0','0','0','0','0','0','0',
+		 '1','1','1','1','1','1','1','1','1','1',
+		 '2','2','2','2','2','2','2','2','2','2',
+		 '3','3','3','3','3','3','3','3','3','3',
+		 '4','4','4','4','4','4','4','4','4','4',
+		 '5','5','5','5','5','5','5','5','5','5'};
+		
+static char itoa_l[60]={'0','1','2','3','4','5','6','7','8','9',
+		 '0','1','2','3','4','5','6','7','8','9',
+		 '0','1','2','3','4','5','6','7','8','9',
+		 '0','1','2','3','4','5','6','7','8','9',
+		 '0','1','2','3','4','5','6','7','8','9',
+		 '0','1','2','3','4','5','6','7','8','9'};
+void time_Unix2RFC(const time_t Zulu,char *Buffer)
+{
+	int Y=0,M=0,D=0;
+	int H=0,Min=0,S=0,WD=0;
+	int I,I2;
+	time_t rest;
+	
+	
+		
+	I=0;
+	while (I<KHTTPD_NUMYEARS)
+	{
+		if (TimeDays[I][0]>Zulu) 
+		   break;
+		I++;
+	}
+	
+	Y=--I;
+	if (I<0) 
+	{
+		Y=0;
+		goto BuildYear;
+	}
+	I2=0;
+	while (I2<=12)
+	{
+		if (TimeDays[I][I2]>Zulu) 
+		   break;
+		I2++;
+	}			   
+	
+	M=I2-1;
+	
+	rest=Zulu - TimeDays[Y][M];
+	WD=WeekDays[Y][M];
+	D=rest/86400;
+	rest=rest%86400;
+	WD+=D;
+	WD=WD%7;
+	H=rest/3600;
+	rest=rest%3600;
+	Min=rest/60;
+	rest=rest%60;
+	S=rest;
+	
+BuildYear:
+	Y+=KHTTPD_YEAROFFSET;
+	
+	
+	/* Format:  Day, 01 Mon 1999 01:01:01 GMT */
+	
+/*	
+	We want to do 
+	
+	sprintf( Buffer, "%s, %02i %s %04i %02i:%02i:%02i GMT",
+		dayName[ WD ], D+1, monthName[ M ], Y,
+		H, Min, S
+	);
+	
+	but this is very expensive. Since the string is fixed length,
+	it is filled manually.
+*/
+	Buffer[0]=dayName[WD][0];
+	Buffer[1]=dayName[WD][1];
+	Buffer[2]=dayName[WD][2];
+	Buffer[3]=',';
+	Buffer[4]=' ';
+	Buffer[5]=itoa_h[D+1];
+	Buffer[6]=itoa_l[D+1];
+	Buffer[7]=' ';
+	Buffer[8]=monthName[M][0];
+	Buffer[9]=monthName[M][1];
+	Buffer[10]=monthName[M][2];
+	Buffer[11]=' ';
+	Buffer[12]=itoa_l[Y/1000];
+	Buffer[13]=itoa_l[(Y/100)%10];
+	Buffer[14]=itoa_l[(Y/10)%10];
+	Buffer[15]=itoa_l[Y%10];
+	Buffer[16]=' ';
+	Buffer[17]=itoa_h[H];
+	Buffer[18]=itoa_l[H];
+	Buffer[19]=':';
+	Buffer[20]=itoa_h[Min];
+	Buffer[21]=itoa_l[Min];
+	Buffer[22]=':';
+	Buffer[23]=itoa_h[S];
+	Buffer[24]=itoa_l[S];
+	Buffer[25]=' ';
+	Buffer[26]='G';
+	Buffer[27]='M';
+	Buffer[28]='T';
+	Buffer[29]=0;
+	
+	
+		
+	
+}
+
+void UpdateCurrentDate(void)
+{
+   struct timeval tv;
+   
+   do_gettimeofday(&tv);
+   if (CurrentTime_i!=tv.tv_sec)
+	   time_Unix2RFC(tv.tv_sec,CurrentTime);
+   
+   CurrentTime_i = tv.tv_sec;
+}
+
+static int MonthHash[32] = {0,0,7,0,0,0,0,0,0,0,0,3,0,0,0,2,6,0,5,0,9,8,4,0,0,11,1,10,0,0,0,0};
+
+#define is_digit(c)	((c) >= '0' && (c) <= '9')
+
+__inline static int skip_atoi(char **s)
+{
+	int i=0;
+
+	while (is_digit(**s))
+		i = i*10 + *((*s)++) - '0';
+	return i;
+}
+
+time_t mimeTime_to_UnixTime(char *Q)
+{
+	int Y,M,D,H,Min,S;
+	unsigned int Hash;
+	time_t Temp;
+	char *s,**s2;
+	
+	s=Q;
+	s2=&s;
+	
+	if (strlen(s)<30) return 0;
+	if (s[3]!=',') return 0;
+	if (s[19]!=':') return 0;
+	
+	s+=5; /* Skip day of week */
+	D = skip_atoi(s2);  /*  Day of month */
+	s++;
+	Hash = (unsigned char)s[0]+(unsigned char)s[2];
+	Hash = (Hash<<1) + (unsigned char)s[1];
+	Hash = (Hash&63)>>1;
+	M = MonthHash[Hash];
+	s+=4;
+	Y = skip_atoi(s2); /* Year */
+	s++;
+	H = skip_atoi(s2); /* Hour */
+	s++;
+	Min = skip_atoi(s2); /* Minutes */
+	s++;
+	S = skip_atoi(s2); /* Seconds */
+	s++;
+	if ((s[0]!='G')||(s[1]!='M')||(s[2]!='T')) 
+	{	
+  		return 0; /* No GMT */
+  	}
+
+	if (Y<KHTTPD_YEAROFFSET) Y = KHTTPD_YEAROFFSET;
+	if (Y>KHTTPD_YEAROFFSET+9) Y = KHTTPD_YEAROFFSET+9;
+	
+	Temp = 	TimeDays[Y-KHTTPD_YEAROFFSET][M];
+	Temp += D*86400+H*3600+Min*60+S;
+	
+	return Temp;  
+}
diff -u --recursive --new-file v2.3.13/linux/net/khttpd/security.c linux/net/khttpd/security.c
--- v2.3.13/linux/net/khttpd/security.c	Wed Dec 31 16:00:00 1969
+++ linux/net/khttpd/security.c	Wed Aug 18 09:45:10 1999
@@ -0,0 +1,271 @@
+/*
+
+kHTTPd -- the next generation
+
+Permissions/Security functions
+
+*/
+
+/****************************************************************
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2, or (at your option)
+ *	any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program; if not, write to the Free Software
+ *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ****************************************************************/
+
+
+#include <linux/kernel.h>
+
+#include <linux/errno.h>
+#include <linux/malloc.h>
+#include <linux/net.h>
+#include <linux/sched.h>
+#include <linux/skbuff.h>
+#include <linux/smp_lock.h>
+#include <linux/un.h>
+#include <linux/unistd.h>
+
+#include <net/ip.h>
+#include <net/sock.h>
+#include <net/tcp.h>
+
+#include <asm/atomic.h>
+#include <asm/semaphore.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+
+#include <linux/file.h>
+
+#include "sysctl.h"
+#include "security.h"
+#include "prototypes.h"
+
+/*
+
+The basic security function answers "Userspace" when any one of the following 
+conditions is met:
+
+1) The filename contains a "?" (this is before % decoding, all others are 
+                                after % decoding)
+2) The filename doesn't start with a "/"                                
+3) The file does not exist
+4) The file does not have enough permissions 
+   (sysctl-configurable, default = worldreadble)
+5) The file has any of the "forbidden" permissions 
+   (sysctl-configurable, default = execute, directory and sticky)
+6) The filename contains a string as defined in the "Dynamic" list.
+
+*/	
+
+
+/* Prototypes */
+
+static void DecodeHexChars(char *URL);
+static struct DynamicString *DynamicList=NULL;
+
+	
+
+/*
+
+The function "OpenFileForSecurity" returns either the "struct file" pointer
+of the file, or NULL. NULL means "let userspace handle it". 
+
+*/
+struct file *OpenFileForSecurity(char *Filename)
+{
+	struct file *filp;
+	struct DynamicString *List;
+	umode_t permission;
+	
+	
+
+	EnterFunction("OpenFileForSecurity");
+	if (Filename==NULL)
+		return NULL;
+	
+	if (strlen(Filename)>=256 ) return NULL;  /* Sanity check */
+	
+	/* Rule no. 1  -- No "?" characters */
+#ifndef BENCHMARK	
+	if (strchr(Filename,'?')!=NULL)
+		return NULL;
+
+	/* Intermediate step: decode all %hex sequences */
+	
+	DecodeHexChars(Filename);
+
+	/* Rule no. 2  -- Must start with a "/" */
+	
+	
+	if (Filename[0]!='/')
+		return NULL;
+		
+#endif
+	/* Rule no. 3 -- Does the file exist ? */
+
+	
+		
+	filp = filp_open(Filename,00,O_RDONLY);
+	
+	
+	if ((IS_ERR(filp))||(filp==NULL)||(filp->f_dentry==NULL))
+	{
+		return NULL;
+	}
+
+#ifndef BENCHMARK		
+	permission = filp->f_dentry->d_inode->i_mode;
+	
+	/* Rule no. 4 : must have enough permissions */
+	
+	
+	if ((permission & sysctl_khttpd_permreq)==0)
+	{
+		if (filp!=NULL);
+			fput(filp);
+		filp=NULL;
+		return NULL;
+	}
+		
+	/* Rule no. 5 : cannot have "forbidden" permission */
+	
+	
+	if ((permission & sysctl_khttpd_permforbid)!=0)
+	{
+		if (filp!=NULL)
+			fput(filp);
+		filp=NULL;
+		return NULL;
+	}
+		
+	/* Rule no. 6 : No string in DynamicList can be a
+			substring of the filename */
+			
+	
+	List = DynamicList;
+	
+	while (List!=NULL)
+	{
+		if (strstr(List->value,Filename)!=NULL)
+		{
+			if (filp!=NULL)
+				fput(filp);
+			filp=NULL;
+			return NULL;
+		}
+		List = List->Next;
+	}
+	
+#endif	
+	LeaveFunction("OpenFileForSecurity - success");
+
+	return filp;
+}
+
+/* 
+
+DecodeHexChars does the actual %HEX decoding, in place. 
+In place is possible because strings only get shorter by this.
+
+*/
+static void DecodeHexChars(char *URL)
+{
+	char *Source,*Dest;
+	int val,val2;
+	
+	EnterFunction("DecodeHexChars");
+	
+	Source = strchr(URL,'%');
+	
+	if (Source==NULL) 
+		return;
+		
+	Dest = Source;
+	
+	while (*Source!=0)
+	{
+		if (*Source=='%')
+		{
+			Source++;
+			val = *Source;
+			
+			if (val>'Z') val-=0x20;
+			val = val - '0';
+			if (val<0) val=0; 
+			if (val>9) val-=7;
+			if (val>15) val=15;
+			
+			Source++;
+
+			val2 = *Source;
+			
+			if (val2>'Z') val2-=0x20;
+			val2 = val2 - '0';
+			if (val2<0) val2=0; 
+			if (val2>9) val2-=7;
+			if (val2>15) val2=15;
+
+			*Dest=val*16+val2;
+		} else *Dest = *Source;
+		Dest++;
+		Source++;
+	}
+	*Dest=0;	
+	
+	LeaveFunction("DecodeHexChars");
+}
+
+
+void AddDynamicString(const char *String)
+{
+	struct DynamicString *Temp;
+	
+	EnterFunction("AddDynamicString");
+	
+	Temp = (struct DynamicString*)kmalloc(sizeof(struct DynamicString),(int)GFP_KERNEL);
+	
+	if (Temp==NULL) 
+		return;
+		
+	memset(Temp->value,0,sizeof(Temp->value));
+	strncpy(Temp->value,String,sizeof(Temp->value)-1);
+	
+	Temp->Next = DynamicList;
+	DynamicList = Temp;
+	
+	LeaveFunction("AddDynamicString");
+}
+
+void GetSecureString(char *String)
+{
+	struct DynamicString *Temp;
+	int max;
+	
+	EnterFunction("GetSecureString");
+	
+	*String = 0;
+	
+	memset(String,0,255);
+	
+	strcat(String,"Dynamic strings are : -");
+	Temp = DynamicList;
+	while (Temp!=NULL)
+	{
+		max=253 - strlen(String) - strlen(Temp->value);
+		strncat(String,Temp->value,max);
+		strcat(String,"- -");
+		Temp = Temp->Next;
+	}	
+	
+	LeaveFunction("GetSecureString");
+}
diff -u --recursive --new-file v2.3.13/linux/net/khttpd/security.h linux/net/khttpd/security.h
--- v2.3.13/linux/net/khttpd/security.h	Wed Dec 31 16:00:00 1969
+++ linux/net/khttpd/security.h	Wed Aug 18 09:45:10 1999
@@ -0,0 +1,12 @@
+#ifndef _INCLUDE_GUARD_SECURITY_H
+#define _INCLUDE_GUARD_SECURITY_H
+
+struct DynamicString;
+
+struct DynamicString
+{
+	struct DynamicString* Next;
+	char value[32-sizeof(void*)];  /* fill 1 cache-line */
+};
+
+#endif
\ No newline at end of file
diff -u --recursive --new-file v2.3.13/linux/net/khttpd/sockets.c linux/net/khttpd/sockets.c
--- v2.3.13/linux/net/khttpd/sockets.c	Wed Dec 31 16:00:00 1969
+++ linux/net/khttpd/sockets.c	Wed Aug 18 09:45:10 1999
@@ -0,0 +1,103 @@
+/*
+
+kHTTPd -- the next generation
+
+Basic socket functions
+
+*/
+/****************************************************************
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2, or (at your option)
+ *	any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program; if not, write to the Free Software
+ *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ****************************************************************/
+
+#include "prototypes.h"
+#include <linux/kernel.h>
+#include <linux/net.h>
+#include <linux/version.h>
+#include <linux/smp_lock.h>
+#include <net/sock.h>
+
+
+/*
+
+MainSocket is shared by all threads, therefore it has to be
+a global variable.
+
+*/
+struct socket *MainSocket=NULL;
+
+
+int StartListening(const int Port)
+{
+	struct socket *sock;
+	struct sockaddr_in sin;
+	int error;
+	
+	EnterFunction("StartListening");
+	
+	/* First create a socket */
+	
+	error = sock_create(PF_INET,SOCK_STREAM,IPPROTO_TCP,&sock);
+	if (error<0) 
+	     (void)printk(KERN_ERR "Error during creation of socket; terminating\n");
+
+
+
+	/* Now bind the socket */
+	
+	sin.sin_family	     = AF_INET;
+	sin.sin_addr.s_addr  = INADDR_ANY;
+	sin.sin_port         = htons((unsigned short)Port);
+	
+	error = sock->ops->bind(sock,(struct sockaddr*)&sin,sizeof(sin));
+	if (error<0)
+	{
+		(void)printk(KERN_ERR "kHTTPd: Error binding socket. This means that some other \n");
+		(void)printk(KERN_ERR "        daemon is (or was a short time ago) using port %i.\n",Port);
+		return 0;	
+	}
+	
+	sock->sk->reuse   = 1;
+	sock->sk->nonagle = 0;
+	sock->sk->linger  = 1;
+
+	/* Now, start listening on the socket */
+	
+	/* I have no idea what a sane backlog-value is. 48 works so far. */
+	
+	error=sock->ops->listen(sock,48);	
+	if (error!=0)
+		(void)printk(KERN_ERR "kHTTPd: Error listening on socket \n");
+	sock->flags |= SO_ACCEPTCON;	
+	
+	MainSocket = sock;
+	
+	EnterFunction("StartListening");
+	return 1; 
+}	
+
+void StopListening(void)
+{
+	struct socket *sock;
+	
+	EnterFunction("StopListening");
+	if (MainSocket==NULL) return;
+	
+	sock=MainSocket;
+	MainSocket = NULL;
+	sock_release(sock);
+
+	LeaveFunction("StopListening");
+}
diff -u --recursive --new-file v2.3.13/linux/net/khttpd/structure.h linux/net/khttpd/structure.h
--- v2.3.13/linux/net/khttpd/structure.h	Wed Dec 31 16:00:00 1969
+++ linux/net/khttpd/structure.h	Wed Aug 18 09:45:10 1999
@@ -0,0 +1,84 @@
+#ifndef _INCLUDE_GUARD_STRUCTURE_H_
+#define _INCLUDE_GUARD_STRUCTURE_H_
+
+#include <linux/time.h>
+#include <linux/wait.h>
+
+
+struct http_request;
+
+struct http_request
+{
+	/* Linked list */
+	struct http_request *Next;
+	
+	/* Network and File data */
+	struct socket	*sock;		
+	struct file	*filp;		
+
+	/* Raw data about the file */
+	
+	int		FileLength;	/* File length in bytes */
+	int		Time;		/* mtime of the file, unix format */
+	int		BytesSent;	/* The number of bytes already sent */
+	int		IsForUserspace;	/* 1 means let Userspace handle this one */
+	
+	/* Wait queue */
+	
+	wait_queue_t sleep;		/* For putting in the socket's waitqueue */
+	
+	/* HTTP request information */
+	char		FileName[256];	/* The requested filename */
+	int		FileNameLength; /* The length of the string representing the filename */
+	char		Agent[128];	/* The agent-string of the remote browser */
+	char		IMS[128];	/* If-modified-since time, rfc string format */
+	char		Host[128];	/* Value given by the Host: header */
+	int		HTTPVER;        /* HTTP-version; 9 for 0.9,   10 for 1.0 and above */
+
+
+	/* Derived date from the above fields */	
+	int		IMS_Time;	/* if-modified-since time, unix format */
+	char		TimeS[64];	/* File mtime, rfc string representation */
+	char		LengthS[14];	/* File length, string representation */
+	char		*MimeType;	/* Pointer to a string with the mime-type 
+					   based on the filename */
+	int		MimeLength;	/* The length of this string */
+	
+};
+
+
+
+/*
+
+struct khttpd_threadinfo represents the four queues that 1 thread has to deal with.
+It is padded to occupy 1 (Intel) cache-line, to avoid "cacheline-pingpong".
+
+*/
+struct khttpd_threadinfo
+{
+	struct http_request* WaitForHeaderQueue;
+	struct http_request* DataSendingQueue;
+	struct http_request* LoggingQueue;
+	struct http_request* UserspaceQueue;
+	char  dummy[16];  /* Padding for cache-lines */
+};
+
+
+/*
+
+struct khttpd_delayed_release is used to build a list of all struct sockets
+that were passed to userspace. It seems to be required that they are not destroyed
+immediatly, so they have a timeout-counter.
+
+*/
+struct khttpd_delayed_release;
+
+struct khttpd_delayed_release
+{
+	struct socket *sock;
+	unsigned long timeout;
+	
+	struct khttpd_delayed_release *Next;
+};
+
+#endif
diff -u --recursive --new-file v2.3.13/linux/net/khttpd/sysctl.c linux/net/khttpd/sysctl.c
--- v2.3.13/linux/net/khttpd/sysctl.c	Wed Dec 31 16:00:00 1969
+++ linux/net/khttpd/sysctl.c	Wed Aug 18 09:45:10 1999
@@ -0,0 +1,321 @@
+/*
+
+kHTTPd -- the next generation
+
+Sysctl interface
+
+*/
+/****************************************************************
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2, or (at your option)
+ *	any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program; if not, write to the Free Software
+ *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ****************************************************************/
+
+
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/malloc.h>
+#include <linux/net.h>
+#include <linux/sched.h>
+#include <linux/skbuff.h>
+#include <linux/smp_lock.h>
+#include <linux/sysctl.h>
+#include <linux/un.h>
+#include <linux/unistd.h>
+
+#include <net/ip.h>
+#include <net/sock.h>
+#include <net/tcp.h>
+
+#include <asm/atomic.h>
+#include <asm/semaphore.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+
+#include <linux/file.h>
+#include "prototypes.h"
+
+
+
+char 	sysctl_khttpd_docroot[200] = "/var/www";
+int 	sysctl_khttpd_stop 	= 0;
+int 	sysctl_khttpd_start 	= 0;
+int 	sysctl_khttpd_unload 	= 0;
+int 	sysctl_khttpd_clientport = 80;
+int 	sysctl_khttpd_permreq    = S_IROTH; /* "other" read-access is required by default*/
+int 	sysctl_khttpd_permforbid = S_IFDIR | S_ISVTX | S_IXOTH | S_IXGRP | S_IXUSR;
+ 				/* forbidden is execute, directory and sticky*/
+int 	sysctl_khttpd_logging 	= 0;
+int 	sysctl_khttpd_serverport= 8080;
+
+char	sysctl_khttpd_dynamicstring[200];
+int 	sysctl_khttpd_sloppymime= 0;
+int	sysctl_khttpd_threads	= 2;
+int	sysctl_khttpd_maxconnect = 1000;
+
+
+static struct ctl_table_header *khttpd_table_header;
+
+static int sysctl_SecureString(ctl_table *table, int *name, int nlen,
+		  void *oldval, size_t *oldlenp,
+		  void *newval, size_t newlen, void **context);
+static int proc_dosecurestring(ctl_table *table, int write, struct file *filp,
+		  void *buffer, size_t *lenp);
+
+
+static ctl_table khttpd_table[] = {
+	{	NET_KHTTPD_DOCROOT,
+		"documentroot",
+		&sysctl_khttpd_docroot,
+		sizeof(sysctl_khttpd_docroot),
+		0644,
+		NULL,
+		proc_dostring,
+		&sysctl_string,
+		NULL,
+		NULL,
+		NULL
+	},
+	{	NET_KHTTPD_STOP,
+		"stop",
+		&sysctl_khttpd_stop,
+		sizeof(int),
+		0644,
+		NULL,
+		proc_dointvec,
+		&sysctl_intvec,
+		NULL,
+		NULL,
+		NULL
+	},
+	{	NET_KHTTPD_START,
+		"start",
+		&sysctl_khttpd_start,
+		sizeof(int),
+		0644,
+		NULL,
+		proc_dointvec,
+		&sysctl_intvec,
+		NULL,
+		NULL,
+		NULL
+	},
+	{	NET_KHTTPD_UNLOAD,
+		"unload",
+		&sysctl_khttpd_unload,
+		sizeof(int),
+		0644,
+		NULL,
+		proc_dointvec,
+		&sysctl_intvec,
+		NULL,
+		NULL,
+		NULL
+	},
+	{	NET_KHTTPD_THREADS,
+		"threads",
+		&sysctl_khttpd_threads,
+		sizeof(int),
+		0644,
+		NULL,
+		proc_dointvec,
+		&sysctl_intvec,
+		NULL,
+		NULL,
+		NULL
+	},
+	{	NET_KHTTPD_MAXCONNECT,
+		"maxconnect",
+		&sysctl_khttpd_maxconnect,
+		sizeof(int),
+		0644,
+		NULL,
+		proc_dointvec,
+		&sysctl_intvec,
+		NULL,
+		NULL,
+		NULL
+	},
+	{	NET_KHTTPD_SLOPPYMIME,
+		"sloppymime",
+		&sysctl_khttpd_sloppymime,
+		sizeof(int),
+		0644,
+		NULL,
+		proc_dointvec,
+		&sysctl_intvec,
+		NULL,
+		NULL,
+		NULL
+	},
+	{	NET_KHTTPD_CLIENTPORT,
+		"clientport",
+		&sysctl_khttpd_clientport,
+		sizeof(int),
+		0644,
+		NULL,
+		proc_dointvec,
+		&sysctl_intvec,
+		NULL,
+		NULL,
+		NULL
+	},
+	{	NET_KHTTPD_PERMREQ,
+		"perm_required",
+		&sysctl_khttpd_permreq,
+		sizeof(int),
+		0644,
+		NULL,
+		proc_dointvec,
+		&sysctl_intvec,
+		NULL,
+		NULL,
+		NULL
+	},
+	{	NET_KHTTPD_PERMFORBID,
+		"perm_forbid",
+		&sysctl_khttpd_permforbid,
+		sizeof(int),
+		0644,
+		NULL,
+		proc_dointvec,
+		&sysctl_intvec,
+		NULL,
+		NULL,
+		NULL
+	},
+	{	NET_KHTTPD_LOGGING,
+		"logging",
+		&sysctl_khttpd_logging,
+		sizeof(int),
+		0644,
+		NULL,
+		proc_dointvec,
+		&sysctl_intvec,
+		NULL,
+		NULL,
+		NULL
+	},
+	{	NET_KHTTPD_SERVERPORT,
+		"serverport",
+		&sysctl_khttpd_serverport,
+		sizeof(int),
+		0644,
+		NULL,
+		proc_dointvec,
+		&sysctl_intvec,
+		NULL,
+		NULL,
+		NULL
+	},
+	{	NET_KHTTPD_DYNAMICSTRING,
+		"dynamic",
+		&sysctl_khttpd_dynamicstring,
+		sizeof(sysctl_khttpd_dynamicstring),
+		0644,
+		NULL,
+		proc_dosecurestring,
+		&sysctl_SecureString,
+		NULL,
+		NULL,
+		NULL
+	},
+	{0,0,0,0,0,0,0,0,0,0,0}	};
+	
+	
+static ctl_table khttpd_dir_table[] = {
+	{NET_KHTTPD, "khttpd", NULL, 0, 0555, khttpd_table,0,0,0,0,0},
+	{0,0,0,0,0,0,0,0,0,0,0}
+};
+
+static ctl_table khttpd_root_table[] = {
+	{CTL_NET, "net", NULL, 0, 0555, khttpd_dir_table,0,0,0,0,0},
+	{0,0,0,0,0,0,0,0,0,0,0}
+};
+	
+
+void StartSysctl(void)
+{
+	khttpd_table_header = register_sysctl_table(khttpd_root_table,1);
+}
+
+
+void EndSysctl(void)
+{
+	unregister_sysctl_table(khttpd_table_header);
+}
+
+static int proc_dosecurestring(ctl_table *table, int write, struct file *filp,
+		  void *buffer, size_t *lenp)
+{
+	int len;
+	char *p, c=0;
+	char String[256];
+	
+	if ((table->data==0) || (table->maxlen==0) || (*lenp==0) ||
+	    ((filp->f_pos!=0) && (write==0))) {
+		*lenp = 0;
+		return 0;
+	}
+	
+	if (write!=0) {
+		len = 0;
+		p = buffer;
+		while (len < *lenp) {
+			if(get_user(c, p++))
+				return -EFAULT;
+			if (c == 0 || c == '\n')
+				break;
+			len++;
+		}
+		if (len >= table->maxlen)
+			len = table->maxlen-1;
+		if(copy_from_user(String, buffer,(unsigned long)len))
+			return -EFAULT;
+		((char *) String)[len] = 0;
+		filp->f_pos += *lenp;
+		AddDynamicString(String);
+	} else {
+		GetSecureString(String);
+		len = strlen(String);
+		if (len > table->maxlen)
+			len = table->maxlen;
+		if (len > *lenp)
+			len = *lenp;
+		if (len!=0)
+			if(copy_to_user(buffer, String,(unsigned long)len))
+				return -EFAULT;
+		if (len < *lenp) {
+			if(put_user('\n', ((char *) buffer) + len))
+				return -EFAULT;
+			len++;
+		}
+		*lenp = len;
+		filp->f_pos += len;
+	}
+	return 0;
+}
+
+static int sysctl_SecureString (/*@unused@*/ctl_table *table, 
+				/*@unused@*/int *name, 
+				/*@unused@*/int nlen,
+		  		/*@unused@*/void *oldval, 
+		  		/*@unused@*/size_t *oldlenp,
+		  		/*@unused@*/void *newval, 
+		  		/*@unused@*/size_t newlen, 
+		  		/*@unused@*/void **context)
+{
+	return -ENOSYS;
+}
diff -u --recursive --new-file v2.3.13/linux/net/khttpd/sysctl.h linux/net/khttpd/sysctl.h
--- v2.3.13/linux/net/khttpd/sysctl.h	Wed Dec 31 16:00:00 1969
+++ linux/net/khttpd/sysctl.h	Wed Aug 18 09:45:10 1999
@@ -0,0 +1,17 @@
+#ifndef _KHTTPD_INCLUDE_GUARD_SYSCTL_H
+#define _KHTTPD_INCLUDE_GUARD_SYSCTL_H
+
+extern char 	sysctl_khttpd_docroot[200];
+extern int 	sysctl_khttpd_stop;
+extern int 	sysctl_khttpd_start;
+extern int 	sysctl_khttpd_unload;
+extern int 	sysctl_khttpd_clientport;
+extern int 	sysctl_khttpd_permreq;
+extern int 	sysctl_khttpd_permforbid;
+extern int 	sysctl_khttpd_logging;
+extern int 	sysctl_khttpd_serverport;
+extern int 	sysctl_khttpd_sloppymime;
+extern int 	sysctl_khttpd_threads;
+extern int	sysctl_khttpd_maxconnect;
+
+#endif
diff -u --recursive --new-file v2.3.13/linux/net/khttpd/userspace.c linux/net/khttpd/userspace.c
--- v2.3.13/linux/net/khttpd/userspace.c	Wed Dec 31 16:00:00 1969
+++ linux/net/khttpd/userspace.c	Wed Aug 18 09:50:44 1999
@@ -0,0 +1,308 @@
+/*
+
+kHTTPd -- the next generation
+
+Pass connections to userspace-daemons
+
+*/
+/****************************************************************
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2, or (at your option)
+ *	any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program; if not, write to the Free Software
+ *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ****************************************************************/
+
+/*
+
+Purpose:
+
+Userspace() hands all requests in the queue to the userspace-daemon, if
+such beast exists.
+
+Return value:
+	The number of requests that changed status
+*/
+#include <linux/kernel.h>
+
+#include <linux/errno.h>
+#include <linux/malloc.h>
+#include <linux/net.h>
+#include <linux/sched.h>
+#include <linux/skbuff.h>
+#include <linux/smp_lock.h>
+#include <linux/un.h>
+#include <linux/unistd.h>
+#include <linux/wait.h>
+
+#include <net/ip.h>
+#include <net/sock.h>
+#include <net/tcp.h>
+
+#include <asm/atomic.h>
+#include <asm/semaphore.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+
+#include <linux/file.h>
+
+
+#include "structure.h"
+#include "prototypes.h"
+#include "sysctl.h"
+
+/* prototypes of local, static functions */
+static int AddSocketToAcceptQueue(struct socket *sock,const int Port);
+static void purge_delayed_release(int CPUNR, int All);
+
+static struct khttpd_delayed_release *delayed_release[CONFIG_KHTTPD_NUMCPU];
+
+
+int Userspace(const int CPUNR)
+{
+	struct http_request *CurrentRequest,**Prev,*Next;
+	
+	EnterFunction("Userspace");
+
+	
+	purge_delayed_release(CPUNR,0);
+
+	
+	CurrentRequest = threadinfo[CPUNR].UserspaceQueue;
+	Prev = &(threadinfo[CPUNR].UserspaceQueue);
+	
+	while (CurrentRequest!=NULL)
+	{
+
+		/* Clean-up the waitqueue of the socket.. Bad things happen if
+		   this is forgotten. */
+		if (CurrentRequest->sock!=NULL)
+		{
+			lock_kernel();  /* Just to be sure (2.3.11) -- Check this for 2.3.13 */
+			if ((CurrentRequest->sock!=NULL)&&(CurrentRequest->sock->sk!=NULL))
+			{
+				/* Some TCP/IP functions call waitqueue-operations without
+				   holding the sock-lock. I am not that brave.
+				*/
+				lock_sock(CurrentRequest->sock->sk);
+				remove_wait_queue(CurrentRequest->sock->sk->sleep,&(CurrentRequest->sleep));
+				release_sock(CurrentRequest->sock->sk);
+			}
+			unlock_kernel(); 
+		} 
+		
+
+		if  (AddSocketToAcceptQueue(CurrentRequest->sock,sysctl_khttpd_clientport)>=0)
+		{
+			struct khttpd_delayed_release *delayed;
+			
+			(*Prev) = CurrentRequest->Next;
+			Next = CurrentRequest->Next;
+			
+			
+			delayed = kmalloc(sizeof(struct khttpd_delayed_release),GFP_KERNEL);
+			if (delayed==NULL)
+			{
+				sock_release(CurrentRequest->sock);
+			} else
+			{
+				/* Schedule socket-deletion 120 seconds from now */
+				delayed->Next = delayed_release[CPUNR];
+				delayed->timeout = jiffies+120*HZ;
+				delayed->sock = CurrentRequest->sock;
+				delayed_release[CPUNR]=delayed;
+			}
+				
+		
+			CurrentRequest->sock = NULL;	 /* We no longer own it */
+			
+			CleanUpRequest(CurrentRequest); 
+				
+			CurrentRequest = Next;
+			continue;
+		
+		}
+		else /* No userspace-daemon present, or other problems with it */
+		{
+			(*Prev) = CurrentRequest->Next;
+			Next = CurrentRequest->Next;
+			
+			Send403(CurrentRequest->sock); /* Sorry, no go... */
+			
+			CleanUpRequest(CurrentRequest); 
+				
+			CurrentRequest = Next;
+			continue;
+		
+		}
+
+		
+		Prev = &(CurrentRequest->Next);	
+		CurrentRequest = CurrentRequest->Next;
+	}
+	
+	LeaveFunction("Userspace");
+	return 0;
+}
+
+void StopUserspace(const int CPUNR)
+{
+	struct http_request *CurrentRequest,*Next;
+	
+	EnterFunction("StopUserspace");
+	CurrentRequest = threadinfo[CPUNR].UserspaceQueue;
+
+	while (CurrentRequest!=NULL)
+	{
+		Next= CurrentRequest->Next;
+		CleanUpRequest(CurrentRequest);
+		CurrentRequest=Next;		
+	}
+	threadinfo[CPUNR].UserspaceQueue = NULL;
+	purge_delayed_release(CPUNR,1);
+	
+	LeaveFunction("StopUserspace");
+}
+
+extern struct sock *tcp_v4_lookup_listener(u32 daddr, unsigned short hnum, int dif);
+
+
+/* 
+   "FindUserspace" returns the struct sock of the userspace-daemon, so that we can
+   "drop" our request in the accept-queue 
+*/
+static struct sock *FindUserspace(const unsigned short Port)
+{
+	EnterFunction("FindUserspace");
+	
+	return tcp_v4_lookup_listener(INADDR_ANY,Port,0);
+	
+	return NULL;
+}
+
+static void dummy_destructor(struct open_request *req)
+{
+}
+
+static struct or_calltable Dummy = 
+{
+ 	NULL,
+ 	&dummy_destructor,
+ 	NULL
+};
+
+#define BACKLOG(sk) ((sk)->tp_pinfo.af_tcp.syn_backlog) /* lvalue! */
+
+static int AddSocketToAcceptQueue(struct socket *sock,const int Port)
+{
+	struct open_request *req;
+	struct sock *sk;
+	struct tcp_opt *tp;
+	
+	EnterFunction("AddSocketToAcceptQueue");
+
+	
+	sk = FindUserspace((unsigned short)Port);	
+	
+	if (sk==NULL)   /* No userspace-daemon found */
+	{
+		return -1;
+	}
+	
+	lock_sock(sk);
+	
+	if (BACKLOG(sk)>128) /* To many pending requests */
+	{
+		return -1;
+	}
+	req = tcp_openreq_alloc();
+	
+	if (req==NULL)
+	{	
+		release_sock(sk);
+		return -1;	
+	}
+	
+	req->sk		= sock->sk;
+	sock->sk = NULL;
+	sock->state = SS_UNCONNECTED;
+	
+	
+	if (req->sk==NULL)
+		(void)printk(KERN_CRIT "kHTTPd: Woops, the socket-buffer is NULL \n"); 
+	  
+	req->class	= &Dummy;
+	req->sk->socket = NULL;
+	req->expires    = jiffies + TCP_TIMEOUT_INIT;
+	
+	tp =&(sk->tp_pinfo.af_tcp);
+	sk->ack_backlog++;
+
+	tcp_inc_slow_timer(TCP_SLT_SYNACK);
+	tcp_synq_queue(tp,req);	
+
+	if (!sk->dead)
+		wake_up_interruptible(sk->sleep);
+		
+	release_sock(sk);
+	
+	LeaveFunction("AddSocketToAcceptQueue");
+		
+	return +1;	
+	
+	
+	
+}
+
+void InitUserspace(const int CPUNR)
+{
+	int I;
+	
+	I=0;
+	while (I<CPUNR)
+		delayed_release[I++]=NULL;
+}
+
+
+/*
+
+This function checks in the delayed_release queue for candidate-sockets
+to be released. If All != 0, all sockets are released. This is required for
+unloading.
+
+*/
+static void purge_delayed_release(const int CPUNR,int All)
+{
+	struct khttpd_delayed_release *Current,*Next,**Prev;
+	
+	Prev = &(delayed_release[CPUNR]);
+	
+	Current = delayed_release[CPUNR];
+	while (Current!=NULL)
+	{
+		if ((Current->timeout<=jiffies)||(All))
+		{
+			Next = Current->Next;
+			
+			*Prev = Next;
+			
+			sock_release(Current->sock);
+			kfree(Current);
+			
+			Current = Next;
+			continue;
+		}
+		
+		Prev = &Current->Next;
+		Current=Current->Next;
+	}
+}
diff -u --recursive --new-file v2.3.13/linux/net/khttpd/waitheaders.c linux/net/khttpd/waitheaders.c
--- v2.3.13/linux/net/khttpd/waitheaders.c	Wed Dec 31 16:00:00 1969
+++ linux/net/khttpd/waitheaders.c	Wed Aug 18 09:51:00 1999
@@ -0,0 +1,300 @@
+/*
+
+kHTTPd -- the next generation
+
+Wait for headers on the accepted connections
+
+*/
+/****************************************************************
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2, or (at your option)
+ *	any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program; if not, write to the Free Software
+ *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ****************************************************************/
+
+/*
+
+Purpose:
+
+WaitForHeaders polls all connections in "WaitForHeaderQueue" to see if
+headers have arived. If so, the headers are decoded and the request is
+moved to either the "SendingDataQueue" or the "UserspaceQueue".
+
+Return value:
+	The number of requests that changed status
+*/
+
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/smp_lock.h>
+#include <linux/file.h>
+
+#include <asm/uaccess.h>
+
+#include "structure.h"
+#include "prototypes.h"
+
+static	char			*Buffer[CONFIG_KHTTPD_NUMCPU];
+
+
+static int DecodeHeader(const int CPUNR, struct http_request *Request);
+
+
+int WaitForHeaders(const int CPUNR)
+{
+	struct http_request *CurrentRequest,**Prev;
+	struct sock *sk;
+	int count = 0;
+	
+	EnterFunction("WaitForHeaders");
+	
+	CurrentRequest = threadinfo[CPUNR].WaitForHeaderQueue;
+	
+	Prev = &(threadinfo[CPUNR].WaitForHeaderQueue);
+	
+	while (CurrentRequest!=NULL)
+	{
+		
+		/* If the connection is lost, remove from queue */
+		
+		lock_sock(CurrentRequest->sock->sk);
+		if (CurrentRequest->sock->sk->state!=TCP_ESTABLISHED)
+		{
+			struct http_request *Next;
+			
+			Next = CurrentRequest->Next;
+			
+			*Prev = CurrentRequest->Next;
+			CurrentRequest->Next = NULL;
+			release_sock(CurrentRequest->sock->sk);
+			
+		
+			CleanUpRequest(CurrentRequest);
+			CurrentRequest = Next;
+			continue;
+		}
+		
+		
+		
+		/* If data pending, take action */	
+		
+		sk = CurrentRequest->sock->sk;
+		
+		if (atomic_read(&(sk->rmem_alloc))>0) /* Do we have data ? */
+		{
+			struct http_request *Next;
+			
+			
+			release_sock(CurrentRequest->sock->sk);
+			
+			/* Decode header */
+			
+			if (DecodeHeader(CPUNR,CurrentRequest)<0)
+			{
+				CurrentRequest = CurrentRequest->Next;
+				continue;
+			} 
+			
+			
+			/* Remove from WaitForHeaderQueue */		
+			
+			Next= CurrentRequest->Next;
+		
+			*Prev = Next;
+			count++;
+			
+			/* Add to either the UserspaceQueue or the DataSendingQueue */
+			
+			if (CurrentRequest->IsForUserspace!=0)
+			{
+				CurrentRequest->Next = threadinfo[CPUNR].UserspaceQueue;
+				threadinfo[CPUNR].UserspaceQueue = CurrentRequest;	
+			} else
+			{
+				CurrentRequest->Next = threadinfo[CPUNR].DataSendingQueue;
+				threadinfo[CPUNR].DataSendingQueue = CurrentRequest;	
+			} 	
+			
+			CurrentRequest = Next;
+			continue;
+		
+		}	
+		else
+			release_sock(CurrentRequest->sock->sk);
+
+		
+		Prev = &(CurrentRequest->Next);
+		CurrentRequest = CurrentRequest->Next;
+	}
+
+	LeaveFunction("WaitHeaders");
+	return count;
+}
+
+void StopWaitingForHeaders(const int CPUNR)
+{
+	struct http_request *CurrentRequest,*Next;
+	
+	EnterFunction("StopWaitingForHeaders");
+	CurrentRequest = threadinfo[CPUNR].WaitForHeaderQueue;
+
+	while (CurrentRequest!=NULL)
+	{
+		Next = CurrentRequest->Next;
+		CleanUpRequest(CurrentRequest);
+		CurrentRequest=Next;		
+	}
+	
+	threadinfo[CPUNR].WaitForHeaderQueue = NULL; /* The queue is empty now */
+	
+	free_page((unsigned long)Buffer[CPUNR]);
+	Buffer[CPUNR]=NULL;
+	
+	EnterFunction("StopWaitingForHeaders");
+}
+
+
+/* 
+
+DecodeHeader peeks at the TCP/IP data, determines what the request is, 
+fills the request-structure and sends the HTTP-header when apropriate.
+
+*/
+
+static int DecodeHeader(const int CPUNR, struct http_request *Request)
+{
+	struct msghdr		msg;
+	struct iovec		iov;
+	int			len;
+
+	mm_segment_t		oldfs;
+	
+	EnterFunction("DecodeHeader");
+	
+	/* First, read the data */
+
+	msg.msg_name     = 0;
+	msg.msg_namelen  = 0;
+	msg.msg_iov	 = &iov;
+	msg.msg_iovlen   = 1;
+	msg.msg_control  = NULL;
+	msg.msg_controllen = 0;
+	msg.msg_flags    = 0;
+	
+	msg.msg_iov->iov_base = &Buffer[CPUNR][0];
+	msg.msg_iov->iov_len  = (size_t)4095;
+	
+	len = 0;
+	oldfs = get_fs(); set_fs(KERNEL_DS);
+	/* 4095 leaves a "0" to terminate the string */
+	
+	len = sock_recvmsg(Request->sock,&msg,4095,MSG_PEEK);
+	set_fs(oldfs);
+
+	if (len>=4094) /* BIG header, we cannot decode it so leave it to userspace */	
+	{
+		Request->IsForUserspace = 1;
+		return 0;
+	}
+	
+	/* Then, decode the header */
+	
+	
+	ParseHeader(Buffer[CPUNR],len,Request);
+	
+	Request->filp = OpenFileForSecurity(Request->FileName);
+	
+	
+	Request->MimeType = ResolveMimeType(Request->FileName,&Request->MimeLength);
+	
+	
+	if (Request->MimeType==NULL) /* Unknown mime-type */
+	{
+		if (Request->filp!=NULL)
+		{
+			fput(Request->filp);
+			Request->filp = NULL;
+		}
+		Request->IsForUserspace = 1;
+		
+		return 0;
+	}
+
+	if (Request->filp==NULL)
+	{
+		Request->IsForUserspace = 1;
+		return 0;
+	}
+	else
+	if ((Request->filp->f_dentry!=NULL)&&(Request->filp->f_dentry->d_inode!=NULL))
+	{
+		Request->FileLength = (int)Request->filp->f_dentry->d_inode->i_size;
+		Request->Time       = Request->filp->f_dentry->d_inode->i_mtime;
+		Request->IMS_Time   = mimeTime_to_UnixTime(Request->IMS);
+		sprintf(Request->LengthS,"%i",Request->FileLength);
+		time_Unix2RFC(min(Request->Time,CurrentTime_i),Request->TimeS);
+   	        /* The min() is required by rfc1945, section 10.10:
+   	           It is not allowed to send a filetime in the future */
+
+		if (Request->IMS_Time>Request->Time)
+		{	/* Not modified since last time */
+			Send304(Request->sock);
+			Request->FileLength=0;
+		}
+		else   /* Normal Case */
+		{
+			Request->sock->sk->nonagle = 2; /* this is TCP_CORK */
+			if (Request->HTTPVER!=9)  /* HTTP/0.9 doesn't allow a header */
+				SendHTTPHeader(Request);
+		}
+		
+	
+	} else 
+	{
+		/* Ehhh... */
+		
+		printk(KERN_CRIT "kHTTPd: Unexpected filesystem response\n");
+		return -1;	
+	}
+	
+	LeaveFunction("DecodeHeader");
+	return 0;
+}
+
+
+int InitWaitHeaders(int ThreadCount)
+{
+	int I,I2;
+
+	EnterFunction("InitWaitHeaders");
+	I=0;	
+	while (I<ThreadCount)
+	{
+		Buffer[I] = (char*)get_free_page((int)GFP_KERNEL);
+		if (Buffer[I] == NULL) 
+		{
+			printk(KERN_CRIT "kHTTPd: Not enough memory for basic needs\n");
+			I2=0;
+			while (I2<I-1)
+			{
+				free_page( (unsigned long)Buffer[I2++]);
+			}
+			return -1;
+		}
+		I++;
+	}
+	
+	LeaveFunction("InitWaitHeaders");	
+	return 0;
+
+}
diff -u --recursive --new-file v2.3.13/linux/net/netrom/af_netrom.c linux/net/netrom/af_netrom.c
--- v2.3.13/linux/net/netrom/af_netrom.c	Thu Jul  8 15:42:21 1999
+++ linux/net/netrom/af_netrom.c	Wed Aug 18 11:38:49 1999
@@ -147,7 +147,7 @@
 /*
  *	Kill all bound sockets on a dropped device.
  */
-static void nr_kill_by_device(struct device *dev)
+static void nr_kill_by_device(struct net_device *dev)
 {
 	struct sock *s;
 
@@ -162,7 +162,7 @@
  */
 static int nr_device_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
-	struct device *dev = (struct device *)ptr;
+	struct net_device *dev = (struct net_device *)ptr;
 
 	if (event != NETDEV_DOWN)
 		return NOTIFY_DONE;
@@ -591,7 +591,7 @@
 {
 	struct sock *sk = sock->sk;
 	struct full_sockaddr_ax25 *addr = (struct full_sockaddr_ax25 *)uaddr;
-	struct device *dev;
+	struct net_device *dev;
 	ax25_address *user, *source;
 
 	if (sk->zapped == 0)
@@ -647,7 +647,7 @@
 	struct sock *sk = sock->sk;
 	struct sockaddr_ax25 *addr = (struct sockaddr_ax25 *)uaddr;
 	ax25_address *user, *source = NULL;
-	struct device *dev;
+	struct net_device *dev;
 
 	if (sk->state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
 		sock->state = SS_CONNECTED;
@@ -818,7 +818,7 @@
 	return 0;
 }
 
-int nr_rx_frame(struct sk_buff *skb, struct device *dev)
+int nr_rx_frame(struct sk_buff *skb, struct net_device *dev)
 {
 	struct sock *sk;
 	struct sock *make;	
@@ -1175,7 +1175,7 @@
 static int nr_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
 {
 	struct sock *s;
-	struct device *dev;
+	struct net_device *dev;
 	const char *devname;
 	int len = 0;
 	off_t pos = 0;
@@ -1295,18 +1295,18 @@
 };
 #endif	
 
-static struct device *dev_nr;
+static struct net_device *dev_nr;
 
 __initfunc(void nr_proto_init(struct net_proto *pro))
 {
 	int i;
 
-	if ((dev_nr = kmalloc(nr_ndevs * sizeof(struct device), GFP_KERNEL)) == NULL) {
+	if ((dev_nr = kmalloc(nr_ndevs * sizeof(struct net_device), GFP_KERNEL)) == NULL) {
 		printk(KERN_ERR "NET/ROM: nr_proto_init - unable to allocate device structure\n");
 		return;
 	}
 
-	memset(dev_nr, 0x00, nr_ndevs * sizeof(struct device));
+	memset(dev_nr, 0x00, nr_ndevs * sizeof(struct net_device));
 
 	for (i = 0; i < nr_ndevs; i++) {
 		dev_nr[i].name = kmalloc(20, GFP_KERNEL);
diff -u --recursive --new-file v2.3.13/linux/net/netrom/nr_dev.c linux/net/netrom/nr_dev.c
--- v2.3.13/linux/net/netrom/nr_dev.c	Mon Dec 28 11:06:44 1998
+++ linux/net/netrom/nr_dev.c	Wed Aug 18 11:38:49 1999
@@ -58,7 +58,7 @@
  *	Only allow IP over NET/ROM frames through if the netrom device is up.
  */
 
-int nr_rx_ip(struct sk_buff *skb, struct device *dev)
+int nr_rx_ip(struct sk_buff *skb, struct net_device *dev)
 {
 	struct net_device_stats *stats = (struct net_device_stats *)dev->priv;
 
@@ -86,7 +86,7 @@
 
 static int nr_rebuild_header(struct sk_buff *skb)
 {
-	struct device *dev = skb->dev;
+	struct net_device *dev = skb->dev;
 	struct net_device_stats *stats = (struct net_device_stats *)dev->priv;
 	struct sk_buff *skbn;
 	unsigned char *bp = skb->data;
@@ -134,7 +134,7 @@
 
 #endif
 
-static int nr_header(struct sk_buff *skb, struct device *dev, unsigned short type,
+static int nr_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
 	void *daddr, void *saddr, unsigned len)
 {
 	unsigned char *buff = skb_push(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN);
@@ -166,7 +166,7 @@
 	return -37;
 }
 
-static int nr_set_mac_address(struct device *dev, void *addr)
+static int nr_set_mac_address(struct net_device *dev, void *addr)
 {
 	struct sockaddr *sa = addr;
 
@@ -179,7 +179,7 @@
 	return 0;
 }
 
-static int nr_open(struct device *dev)
+static int nr_open(struct net_device *dev)
 {
 	dev->tbusy = 0;
 	dev->start = 1;
@@ -191,7 +191,7 @@
 	return 0;
 }
 
-static int nr_close(struct device *dev)
+static int nr_close(struct net_device *dev)
 {
 	dev->tbusy = 1;
 	dev->start = 0;
@@ -203,7 +203,7 @@
 	return 0;
 }
 
-static int nr_xmit(struct sk_buff *skb, struct device *dev)
+static int nr_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct net_device_stats *stats = (struct net_device_stats *)dev->priv;
 
@@ -238,12 +238,12 @@
 	return 0;
 }
 
-static struct net_device_stats *nr_get_stats(struct device *dev)
+static struct net_device_stats *nr_get_stats(struct net_device *dev)
 {
 	return (struct net_device_stats *)dev->priv;
 }
 
-int nr_init(struct device *dev)
+int nr_init(struct net_device *dev)
 {
 	dev->mtu		= NR_MAX_PACKET_SIZE;
 	dev->tbusy		= 0;
diff -u --recursive --new-file v2.3.13/linux/net/netrom/nr_loopback.c linux/net/netrom/nr_loopback.c
--- v2.3.13/linux/net/netrom/nr_loopback.c	Fri Oct  9 11:56:59 1998
+++ linux/net/netrom/nr_loopback.c	Wed Aug 18 11:38:49 1999
@@ -75,7 +75,7 @@
 {
 	struct sk_buff *skb;
 	ax25_address *nr_dest;
-	struct device *dev;
+	struct net_device *dev;
 
 	if ((skb = skb_dequeue(&loopback_queue)) != NULL) {
 		nr_dest = (ax25_address *)(skb->data + 7);
diff -u --recursive --new-file v2.3.13/linux/net/netrom/nr_route.c linux/net/netrom/nr_route.c
--- v2.3.13/linux/net/netrom/nr_route.c	Wed Jun  9 14:45:37 1999
+++ linux/net/netrom/nr_route.c	Wed Aug 18 11:38:49 1999
@@ -62,7 +62,7 @@
  *	neighbour if it is new.
  */
 static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax25,
-	ax25_digi *ax25_digi, struct device *dev, int quality, int obs_count)
+	ax25_digi *ax25_digi, struct net_device *dev, int quality, int obs_count)
 {
 	struct nr_node  *nr_node;
 	struct nr_neigh *nr_neigh;
@@ -321,7 +321,7 @@
  *	"Delete" a node. Strictly speaking remove a route to a node. The node
  *	is only deleted if no routes are left to it.
  */
-static int nr_del_node(ax25_address *callsign, ax25_address *neighbour, struct device *dev)
+static int nr_del_node(ax25_address *callsign, ax25_address *neighbour, struct net_device *dev)
 {
 	struct nr_node  *nr_node;
 	struct nr_neigh *nr_neigh;
@@ -371,7 +371,7 @@
 /*
  *	Lock a neighbour with a quality.
  */
-static int nr_add_neigh(ax25_address *callsign, ax25_digi *ax25_digi, struct device *dev, unsigned int quality)
+static int nr_add_neigh(ax25_address *callsign, ax25_digi *ax25_digi, struct net_device *dev, unsigned int quality)
 {
 	struct nr_neigh *nr_neigh;
 	unsigned long flags;
@@ -420,7 +420,7 @@
  *	"Delete" a neighbour. The neighbour is only removed if the number
  *	of nodes that may use it is zero.
  */
-static int nr_del_neigh(ax25_address *callsign, struct device *dev, unsigned int quality)
+static int nr_del_neigh(ax25_address *callsign, struct net_device *dev, unsigned int quality)
 {
 	struct nr_neigh *nr_neigh;
 
@@ -499,7 +499,7 @@
 /*
  *	A device has been removed. Remove its routes and neighbours.
  */
-void nr_rt_device_down(struct device *dev)
+void nr_rt_device_down(struct net_device *dev)
 {
 	struct nr_neigh *s, *nr_neigh = nr_neigh_list;
 	struct nr_node  *t, *nr_node;
@@ -544,9 +544,9 @@
  *	Check that the device given is a valid AX.25 interface that is "up".
  *	Or a valid ethernet interface with an AX.25 callsign binding.
  */
-static struct device *nr_ax25_dev_get(char *devname)
+static struct net_device *nr_ax25_dev_get(char *devname)
 {
-	struct device *dev;
+	struct net_device *dev;
 
 	if ((dev = dev_get(devname)) == NULL)
 		return NULL;
@@ -560,9 +560,9 @@
 /*
  *	Find the first active NET/ROM device, usually "nr0".
  */
-struct device *nr_dev_first(void)
+struct net_device *nr_dev_first(void)
 {
-	struct device *dev, *first = NULL;
+	struct net_device *dev, *first = NULL;
 
 	read_lock(&dev_base_lock);
 	for (dev = dev_base; dev != NULL; dev = dev->next) {
@@ -578,9 +578,9 @@
 /*
  *	Find the NET/ROM device for the given callsign.
  */
-struct device *nr_dev_get(ax25_address *addr)
+struct net_device *nr_dev_get(ax25_address *addr)
 {
-	struct device *dev;
+	struct net_device *dev;
 
 	read_lock(&dev_base_lock);
 	for (dev = dev_base; dev != NULL; dev = dev->next) {
@@ -617,7 +617,7 @@
 int nr_rt_ioctl(unsigned int cmd, void *arg)
 {
 	struct nr_route_struct nr_route;
-	struct device *dev;
+	struct net_device *dev;
 
 	switch (cmd) {
 
@@ -703,7 +703,7 @@
 	ax25_address *nr_src, *nr_dest;
 	struct nr_neigh *nr_neigh;
 	struct nr_node  *nr_node;
-	struct device *dev;
+	struct net_device *dev;
 	unsigned char *dptr;
 
 	if (ax25 != NULL && call_in_firewall(PF_NETROM, skb->dev, skb->data, NULL, &skb) != FW_ACCEPT)
diff -u --recursive --new-file v2.3.13/linux/net/netsyms.c linux/net/netsyms.c
--- v2.3.13/linux/net/netsyms.c	Thu Jul  8 15:42:21 1999
+++ linux/net/netsyms.c	Wed Aug 18 09:45:10 1999
@@ -49,7 +49,7 @@
 extern __u32 sysctl_wmem_max;
 extern __u32 sysctl_rmem_max;
 
-#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) || defined (CONFIG_KHTTPD) || defined (CONFIG_KHTTPD_MODULE)
 #include <linux/in6.h>
 #include <linux/icmpv6.h>
 #include <net/ipv6.h>
@@ -178,7 +178,9 @@
 #endif
 EXPORT_SYMBOL(pneigh_lookup);
 EXPORT_SYMBOL(pneigh_enqueue);
+EXPORT_SYMBOL(neigh_create);
 EXPORT_SYMBOL(neigh_destroy);
+EXPORT_SYMBOL(neigh_lookup);
 EXPORT_SYMBOL(neigh_parms_alloc);
 EXPORT_SYMBOL(neigh_parms_release);
 EXPORT_SYMBOL(neigh_rand_reach_time);
@@ -259,7 +261,7 @@
 EXPORT_SYMBOL(ipv6_addr_type);
 EXPORT_SYMBOL(icmpv6_send);
 #endif
-#ifdef CONFIG_IPV6_MODULE
+#if defined (CONFIG_IPV6_MODULE) || defined (CONFIG_KHTTPD) || defined (CONFIG_KHTTPD_MODULE)
 /* inet functions common to v4 and v6 */
 EXPORT_SYMBOL(inet_stream_ops);
 EXPORT_SYMBOL(inet_release);
@@ -287,6 +289,7 @@
 EXPORT_SYMBOL(memcpy_fromiovecend);
 EXPORT_SYMBOL(csum_partial_copy_fromiovecend);
 EXPORT_SYMBOL(net_timer);
+EXPORT_SYMBOL(tcp_v4_lookup_listener);
 /* UDP/TCP exported functions for TCPv6 */
 EXPORT_SYMBOL(udp_ioctl);
 EXPORT_SYMBOL(udp_connect);
diff -u --recursive --new-file v2.3.13/linux/net/packet/af_packet.c linux/net/packet/af_packet.c
--- v2.3.13/linux/net/packet/af_packet.c	Wed Jun  9 14:45:37 1999
+++ linux/net/packet/af_packet.c	Wed Aug 18 11:38:49 1999
@@ -194,7 +194,7 @@
 #ifdef CONFIG_SOCK_PACKET
 extern struct proto_ops packet_ops_spkt;
 
-static int packet_rcv_spkt(struct sk_buff *skb, struct device *dev,  struct packet_type *pt)
+static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev,  struct packet_type *pt)
 {
 	struct sock *sk;
 	struct sockaddr_pkt *spkt = (struct sockaddr_pkt*)skb->cb;
@@ -261,7 +261,7 @@
 	struct sock *sk = sock->sk;
 	struct sockaddr_pkt *saddr=(struct sockaddr_pkt *)msg->msg_name;
 	struct sk_buff *skb;
-	struct device *dev;
+	struct net_device *dev;
 	unsigned short proto=0;
 	int err;
 	
@@ -364,7 +364,7 @@
 }
 #endif
 
-static int packet_rcv(struct sk_buff *skb, struct device *dev,  struct packet_type *pt)
+static int packet_rcv(struct sk_buff *skb, struct net_device *dev,  struct packet_type *pt)
 {
 	struct sock *sk;
 	struct sockaddr_ll *sll = (struct sockaddr_ll*)skb->cb;
@@ -428,7 +428,7 @@
 	struct sock *sk = sock->sk;
 	struct sockaddr_ll *saddr=(struct sockaddr_ll *)msg->msg_name;
 	struct sk_buff *skb;
-	struct device *dev;
+	struct net_device *dev;
 	unsigned short proto;
 	unsigned char *addr;
 	int ifindex, err, reserve = 0;
@@ -595,7 +595,7 @@
  *	Attach a packet hook.
  */
 
-static int packet_do_bind(struct sock *sk, struct device *dev, int protocol)
+static int packet_do_bind(struct sock *sk, struct net_device *dev, int protocol)
 {
 	/*
 	 *	Detach an existing hook if present.
@@ -640,7 +640,7 @@
 {
 	struct sock *sk=sock->sk;
 	char name[15];
-	struct device *dev;
+	struct net_device *dev;
 	
 	/*
 	 *	Check legality
@@ -662,7 +662,7 @@
 {
 	struct sockaddr_ll *sll = (struct sockaddr_ll*)uaddr;
 	struct sock *sk=sock->sk;
-	struct device *dev = NULL;
+	struct net_device *dev = NULL;
 	
 	/*
 	 *	Check legality
@@ -846,7 +846,7 @@
 static int packet_getname_spkt(struct socket *sock, struct sockaddr *uaddr,
 			       int *uaddr_len, int peer)
 {
-	struct device *dev;
+	struct net_device *dev;
 	struct sock *sk	= sock->sk;
 
 	if (peer)
@@ -867,7 +867,7 @@
 static int packet_getname(struct socket *sock, struct sockaddr *uaddr,
 			  int *uaddr_len, int peer)
 {
-	struct device *dev;
+	struct net_device *dev;
 	struct sock *sk = sock->sk;
 	struct sockaddr_ll *sll = (struct sockaddr_ll*)uaddr;
 
@@ -892,7 +892,7 @@
 }
 
 #ifdef CONFIG_PACKET_MULTICAST
-static void packet_dev_mc(struct device *dev, struct packet_mclist *i, int what)
+static void packet_dev_mc(struct net_device *dev, struct packet_mclist *i, int what)
 {
 	switch (i->type) {
 	case PACKET_MR_MULTICAST:
@@ -911,7 +911,7 @@
 	}
 }
 
-static void packet_dev_mclist(struct device *dev, struct packet_mclist *i, int what)
+static void packet_dev_mclist(struct net_device *dev, struct packet_mclist *i, int what)
 {
 	for ( ; i; i=i->next) {
 		if (i->ifindex == dev->ifindex)
@@ -922,7 +922,7 @@
 static int packet_mc_add(struct sock *sk, struct packet_mreq *mreq)
 {
 	struct packet_mclist *ml, *i;
-	struct device *dev;
+	struct net_device *dev;
 	int err;
 
 	rtnl_shlock();
@@ -978,7 +978,7 @@
 		    ml->alen == mreq->mr_alen &&
 		    memcmp(ml->addr, mreq->mr_address, ml->alen) == 0) {
 			if (--ml->count == 0) {
-				struct device *dev;
+				struct net_device *dev;
 				*mlp = ml->next;
 				dev = dev_get_by_index(ml->ifindex);
 				if (dev)
@@ -996,7 +996,7 @@
 	struct packet_mclist *ml;
 
 	while ((ml=sk->protinfo.af_packet->mclist) != NULL) {
-		struct device *dev;
+		struct net_device *dev;
 		sk->protinfo.af_packet->mclist = ml->next;
 		if ((dev = dev_get_by_index(ml->ifindex)) != NULL)
 			packet_dev_mc(dev, ml, -1);
@@ -1035,7 +1035,7 @@
 {
 	struct sock *sk;
 	struct packet_opt *po;
-	struct device *dev = (struct device*)data;
+	struct net_device *dev = (struct net_device*)data;
 
 	for (sk = packet_sklist; sk; sk = sk->next) {
 		po = sk->protinfo.af_packet;
diff -u --recursive --new-file v2.3.13/linux/net/rose/af_rose.c linux/net/rose/af_rose.c
--- v2.3.13/linux/net/rose/af_rose.c	Thu Jul  8 15:42:21 1999
+++ linux/net/rose/af_rose.c	Wed Aug 18 11:38:49 1999
@@ -215,7 +215,7 @@
 /*
  *	Kill all bound sockets on a dropped device.
  */
-static void rose_kill_by_device(struct device *dev)
+static void rose_kill_by_device(struct net_device *dev)
 {
 	struct sock *s;
 	
@@ -233,7 +233,7 @@
  */
 static int rose_device_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
-	struct device *dev = (struct device *)ptr;
+	struct net_device *dev = (struct net_device *)ptr;
 
 	if (event != NETDEV_DOWN)
 		return NOTIFY_DONE;
@@ -667,7 +667,7 @@
 {
 	struct sock *sk = sock->sk;
 	struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr;
-	struct device *dev;
+	struct net_device *dev;
 	ax25_address *user, *source;
 	int n;
 
@@ -727,7 +727,7 @@
 	struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr;
 	unsigned char cause, diagnostic;
 	ax25_address *user;
-	struct device *dev;
+	struct net_device *dev;
 	int n;
 
 	if (sk->state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
@@ -945,7 +945,7 @@
 	return 0;
 }
 
-int rose_rx_call_request(struct sk_buff *skb, struct device *dev, struct rose_neigh *neigh, unsigned int lci)
+int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct rose_neigh *neigh, unsigned int lci)
 {
 	struct sock *sk;
 	struct sock *make;
@@ -1366,7 +1366,7 @@
 static int rose_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
 {
 	struct sock *s;
-	struct device *dev;
+	struct net_device *dev;
 	const char *devname, *callsign;
 	int len = 0;
 	off_t pos = 0;
@@ -1491,7 +1491,7 @@
 };
 #endif	
 
-static struct device *dev_rose;
+static struct net_device *dev_rose;
 
 __initfunc(void rose_proto_init(struct net_proto *pro))
 {
@@ -1499,12 +1499,12 @@
 
 	rose_callsign = null_ax25_address;
 
-	if ((dev_rose = kmalloc(rose_ndevs * sizeof(struct device), GFP_KERNEL)) == NULL) {
+	if ((dev_rose = kmalloc(rose_ndevs * sizeof(struct net_device), GFP_KERNEL)) == NULL) {
 		printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate device structure\n");
 		return;
 	}
 
-	memset(dev_rose, 0x00, rose_ndevs * sizeof(struct device));
+	memset(dev_rose, 0x00, rose_ndevs * sizeof(struct net_device));
 
 	for (i = 0; i < rose_ndevs; i++) {
 		dev_rose[i].name = kmalloc(20, GFP_KERNEL);
diff -u --recursive --new-file v2.3.13/linux/net/rose/rose_dev.c linux/net/rose/rose_dev.c
--- v2.3.13/linux/net/rose/rose_dev.c	Thu Dec 17 09:07:45 1998
+++ linux/net/rose/rose_dev.c	Wed Aug 18 11:38:49 1999
@@ -52,7 +52,7 @@
  *	Only allow IP over ROSE frames through if the netrom device is up.
  */
 
-int rose_rx_ip(struct sk_buff *skb, struct device *dev)
+int rose_rx_ip(struct sk_buff *skb, struct net_device *dev)
 {
 	struct net_device_stats *stats = (struct net_device_stats *)dev->priv;
 
@@ -80,7 +80,7 @@
 	return 1;
 }
 
-static int rose_header(struct sk_buff *skb, struct device *dev, unsigned short type,
+static int rose_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
 	void *daddr, void *saddr, unsigned len)
 {
 	unsigned char *buff = skb_push(skb, ROSE_MIN_LEN + 2);
@@ -99,7 +99,7 @@
 
 static int rose_rebuild_header(struct sk_buff *skb)
 {
-	struct device *dev = skb->dev;
+	struct net_device *dev = skb->dev;
 	struct net_device_stats *stats = (struct net_device_stats *)dev->priv;
 	unsigned char *bp = (unsigned char *)skb->data;
 	struct sk_buff *skbn;
@@ -130,7 +130,7 @@
 	return 1;
 }
 
-static int rose_set_mac_address(struct device *dev, void *addr)
+static int rose_set_mac_address(struct net_device *dev, void *addr)
 {
 	struct sockaddr *sa = addr;
 
@@ -143,7 +143,7 @@
 	return 0;
 }
 
-static int rose_open(struct device *dev)
+static int rose_open(struct net_device *dev)
 {
 	dev->tbusy = 0;
 	dev->start = 1;
@@ -155,7 +155,7 @@
 	return 0;
 }
 
-static int rose_close(struct device *dev)
+static int rose_close(struct net_device *dev)
 {
 	dev->tbusy = 1;
 	dev->start = 0;
@@ -167,7 +167,7 @@
 	return 0;
 }
 
-static int rose_xmit(struct sk_buff *skb, struct device *dev)
+static int rose_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct net_device_stats *stats = (struct net_device_stats *)dev->priv;
 
@@ -202,12 +202,12 @@
 	return 0;
 }
 
-static struct net_device_stats *rose_get_stats(struct device *dev)
+static struct net_device_stats *rose_get_stats(struct net_device *dev)
 {
 	return (struct net_device_stats *)dev->priv;
 }
 
-int rose_init(struct device *dev)
+int rose_init(struct net_device *dev)
 {
 	dev->mtu		= ROSE_MAX_PACKET_SIZE - 2;
 	dev->tbusy		= 0;
diff -u --recursive --new-file v2.3.13/linux/net/rose/rose_loopback.c linux/net/rose/rose_loopback.c
--- v2.3.13/linux/net/rose/rose_loopback.c	Wed Oct  7 15:52:55 1998
+++ linux/net/rose/rose_loopback.c	Wed Aug 18 11:38:49 1999
@@ -74,7 +74,7 @@
 static void rose_loopback_timer(unsigned long param)
 {
 	struct sk_buff *skb;
-	struct device *dev;
+	struct net_device *dev;
 	rose_address *dest;
 	struct sock *sk;
 	unsigned short frametype;
diff -u --recursive --new-file v2.3.13/linux/net/rose/rose_route.c linux/net/rose/rose_route.c
--- v2.3.13/linux/net/rose/rose_route.c	Wed Jun  9 14:45:37 1999
+++ linux/net/rose/rose_route.c	Wed Aug 18 11:38:49 1999
@@ -63,7 +63,7 @@
  *	Add a new route to a node, and in the process add the node and the
  *	neighbour if it is new.
  */
-static int rose_add_node(struct rose_route_struct *rose_route, struct device *dev)
+static int rose_add_node(struct rose_route_struct *rose_route, struct net_device *dev)
 {
 	struct rose_node  *rose_node, *rose_tmpn, *rose_tmpp;
 	struct rose_neigh *rose_neigh;
@@ -295,7 +295,7 @@
  *	"Delete" a node. Strictly speaking remove a route to a node. The node
  *	is only deleted if no routes are left to it.
  */
-static int rose_del_node(struct rose_route_struct *rose_route, struct device *dev)
+static int rose_del_node(struct rose_route_struct *rose_route, struct net_device *dev)
 {
 	struct rose_node  *rose_node;
 	struct rose_neigh *rose_neigh;
@@ -433,7 +433,7 @@
 /*
  *	A device has been removed. Remove its routes and neighbours.
  */
-void rose_rt_device_down(struct device *dev)
+void rose_rt_device_down(struct net_device *dev)
 {
 	struct rose_neigh *s, *rose_neigh = rose_neigh_list;
 	struct rose_node  *t, *rose_node;
@@ -477,7 +477,7 @@
 /*
  *	A device has been removed. Remove its links.
  */
-void rose_route_device_down(struct device *dev)
+void rose_route_device_down(struct net_device *dev)
 {
 	struct rose_route *s, *rose_route = rose_route_list;
 
@@ -523,9 +523,9 @@
 /*
  *	Check that the device given is a valid AX.25 interface that is "up".
  */
-struct device *rose_ax25_dev_get(char *devname)
+struct net_device *rose_ax25_dev_get(char *devname)
 {
-	struct device *dev;
+	struct net_device *dev;
 
 	if ((dev = dev_get(devname)) == NULL)
 		return NULL;
@@ -539,9 +539,9 @@
 /*
  *	Find the first active ROSE device, usually "rose0".
  */
-struct device *rose_dev_first(void)
+struct net_device *rose_dev_first(void)
 {
-	struct device *dev, *first = NULL;
+	struct net_device *dev, *first = NULL;
 
 	read_lock(&dev_base_lock);
 	for (dev = dev_base; dev != NULL; dev = dev->next) {
@@ -557,9 +557,9 @@
 /*
  *	Find the ROSE device for the given address.
  */
-struct device *rose_dev_get(rose_address *addr)
+struct net_device *rose_dev_get(rose_address *addr)
 {
-	struct device *dev;
+	struct net_device *dev;
 
 	read_lock(&dev_base_lock);
 	for (dev = dev_base; dev != NULL; dev = dev->next) {
@@ -621,7 +621,7 @@
 int rose_rt_ioctl(unsigned int cmd, void *arg)
 {
 	struct rose_route_struct rose_route;
-	struct device *dev;
+	struct net_device *dev;
 
 	switch (cmd) {
 
@@ -720,7 +720,7 @@
  * 	A device has been "downed" remove its link status. Blow away all
  *	through routes and connections that use this device.
  */
-void rose_link_device_down(struct device *dev)
+void rose_link_device_down(struct net_device *dev)
 {
 	struct rose_neigh *rose_neigh;
 
@@ -745,7 +745,7 @@
 	unsigned short frametype;
 	unsigned int lci, new_lci;
 	unsigned char cause, diagnostic;
-	struct device *dev;
+	struct net_device *dev;
 	unsigned long flags;
 	int len;
 
diff -u --recursive --new-file v2.3.13/linux/net/sched/cls_api.c linux/net/sched/cls_api.c
--- v2.3.13/linux/net/sched/cls_api.c	Wed Jun  9 14:45:37 1999
+++ linux/net/sched/cls_api.c	Wed Aug 18 11:38:49 1999
@@ -125,7 +125,7 @@
 	u32 prio = TC_H_MAJ(t->tcm_info);
 	u32 nprio = prio;
 	u32 parent = t->tcm_parent;
-	struct device *dev;
+	struct net_device *dev;
 	struct Qdisc  *q;
 	struct tcf_proto **back, **chain;
 	struct tcf_proto *tp = NULL;
@@ -352,7 +352,7 @@
 {
 	int t;
 	int s_t;
-	struct device *dev;
+	struct net_device *dev;
 	struct Qdisc *q;
 	struct tcf_proto *tp, **chain;
 	struct tcmsg *tcm = (struct tcmsg*)NLMSG_DATA(cb->nlh);
diff -u --recursive --new-file v2.3.13/linux/net/sched/cls_route.c linux/net/sched/cls_route.c
--- v2.3.13/linux/net/sched/cls_route.c	Wed Jun  9 14:45:37 1999
+++ linux/net/sched/cls_route.c	Wed Aug 18 11:38:49 1999
@@ -83,7 +83,7 @@
 	return id&0xF;
 }
 
-static void route4_reset_fastmap(struct device *dev, struct route4_head *head, u32 id)
+static void route4_reset_fastmap(struct net_device *dev, struct route4_head *head, u32 id)
 {
 	spin_lock_bh(&dev->queue_lock);
 	memset(head->fastmap, 0, sizeof(head->fastmap));
diff -u --recursive --new-file v2.3.13/linux/net/sched/sch_api.c linux/net/sched/sch_api.c
--- v2.3.13/linux/net/sched/sch_api.c	Wed Jun  9 14:45:37 1999
+++ linux/net/sched/sch_api.c	Wed Aug 18 11:38:49 1999
@@ -186,7 +186,7 @@
    (root qdisc, all its children, children of children etc.)
  */
 
-struct Qdisc *qdisc_lookup(struct device *dev, u32 handle)
+struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle)
 {
 	struct Qdisc *q;
 
@@ -276,7 +276,7 @@
 
 /* Allocate an unique handle from space managed by kernel */
 
-u32 qdisc_alloc_handle(struct device *dev)
+u32 qdisc_alloc_handle(struct net_device *dev)
 {
 	int i = 0x10000;
 	static u32 autohandle = TC_H_MAKE(0x80000000U, 0);
@@ -293,7 +293,7 @@
 /* Attach toplevel qdisc to device dev */
 
 static struct Qdisc *
-dev_graft_qdisc(struct device *dev, struct Qdisc *qdisc)
+dev_graft_qdisc(struct net_device *dev, struct Qdisc *qdisc)
 {
 	struct Qdisc *oqdisc;
 
@@ -329,7 +329,7 @@
    Old qdisc is not destroyed but returned in *old.
  */
 
-int qdisc_graft(struct device *dev, struct Qdisc *parent, u32 classid,
+int qdisc_graft(struct net_device *dev, struct Qdisc *parent, u32 classid,
 		struct Qdisc *new, struct Qdisc **old)
 {
 	int err = 0;
@@ -361,7 +361,7 @@
  */
 
 static struct Qdisc *
-qdisc_create(struct device *dev, u32 handle, struct rtattr **tca, int *errp)
+qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp)
 {
 	int err;
 	struct rtattr *kind = tca[TCA_KIND-1];
@@ -503,7 +503,7 @@
 {
 	struct tcmsg *tcm = NLMSG_DATA(n);
 	struct rtattr **tca = arg;
-	struct device *dev;
+	struct net_device *dev;
 	u32 clid = tcm->tcm_parent;
 	struct Qdisc *q = NULL;
 	struct Qdisc *p = NULL;
@@ -560,7 +560,7 @@
 {
 	struct tcmsg *tcm = NLMSG_DATA(n);
 	struct rtattr **tca = arg;
-	struct device *dev;
+	struct net_device *dev;
 	u32 clid = tcm->tcm_parent;
 	struct Qdisc *q = NULL;
 	struct Qdisc *p = NULL;
@@ -751,7 +751,7 @@
 {
 	int idx, q_idx;
 	int s_idx, s_q_idx;
-	struct device *dev;
+	struct net_device *dev;
 	struct Qdisc *q;
 
 	s_idx = cb->args[0];
@@ -797,7 +797,7 @@
 {
 	struct tcmsg *tcm = NLMSG_DATA(n);
 	struct rtattr **tca = arg;
-	struct device *dev;
+	struct net_device *dev;
 	struct Qdisc *q = NULL;
 	struct Qdisc_class_ops *cops;
 	unsigned long cl = 0;
@@ -971,7 +971,7 @@
 {
 	int t;
 	int s_t;
-	struct device *dev;
+	struct net_device *dev;
 	struct Qdisc *q;
 	struct tcmsg *tcm = (struct tcmsg*)NLMSG_DATA(cb->nlh);
 	struct qdisc_dump_args arg;
diff -u --recursive --new-file v2.3.13/linux/net/sched/sch_generic.c linux/net/sched/sch_generic.c
--- v2.3.13/linux/net/sched/sch_generic.c	Wed Jun  9 14:45:37 1999
+++ linux/net/sched/sch_generic.c	Wed Aug 18 11:38:49 1999
@@ -85,7 +85,7 @@
    NOTE: Called under dev->queue_lock with locally disabled BH.
 */
 
-int qdisc_restart(struct device *dev)
+int qdisc_restart(struct net_device *dev)
 {
 	struct Qdisc *q = dev->qdisc;
 	struct sk_buff *skb;
@@ -206,7 +206,7 @@
 
 	while ((h = lh.forw) != &lh) {
 		int res;
-		struct device *dev;
+		struct net_device *dev;
 		struct Qdisc *q = (struct Qdisc*)h;
 
 		qdisc_stop_run(q);
@@ -253,7 +253,7 @@
 		goto out;
 
 	while ((h = lh.forw) != &lh) {
-		struct device *dev;
+		struct net_device *dev;
 		struct Qdisc *q = (struct Qdisc*)h;
 
 		qdisc_stop_run(q);
@@ -447,7 +447,7 @@
 	pfifo_fast_reset,
 };
 
-struct Qdisc * qdisc_create_dflt(struct device *dev, struct Qdisc_ops *ops)
+struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops)
 {
 	struct Qdisc *sch;
 	int size = sizeof(*sch) + ops->priv_size;
@@ -485,7 +485,7 @@
 void qdisc_destroy(struct Qdisc *qdisc)
 {
 	struct Qdisc_ops *ops = qdisc->ops;
-	struct device *dev;
+	struct net_device *dev;
 
 	if (!atomic_dec_and_test(&qdisc->refcnt))
 		return;
@@ -515,7 +515,7 @@
 }
 
 
-void dev_activate(struct device *dev)
+void dev_activate(struct net_device *dev)
 {
 	/* No queueing discipline is attached to device;
 	   create default one i.e. pfifo_fast for devices,
@@ -552,7 +552,7 @@
 	spin_unlock_bh(&dev->queue_lock);
 }
 
-void dev_deactivate(struct device *dev)
+void dev_deactivate(struct net_device *dev)
 {
 	struct Qdisc *qdisc;
 
@@ -569,7 +569,7 @@
 	spin_unlock_bh(&dev->queue_lock);
 }
 
-void dev_init_scheduler(struct device *dev)
+void dev_init_scheduler(struct net_device *dev)
 {
 	write_lock(&qdisc_tree_lock);
 	spin_lock_bh(&dev->queue_lock);
@@ -580,7 +580,7 @@
 	write_unlock(&qdisc_tree_lock);
 }
 
-void dev_shutdown(struct device *dev)
+void dev_shutdown(struct net_device *dev)
 {
 	struct Qdisc *qdisc;
 
diff -u --recursive --new-file v2.3.13/linux/net/sched/sch_teql.c linux/net/sched/sch_teql.c
--- v2.3.13/linux/net/sched/sch_teql.c	Wed Jun  9 14:45:37 1999
+++ linux/net/sched/sch_teql.c	Wed Aug 18 11:38:49 1999
@@ -67,7 +67,7 @@
 struct teql_master
 {
 	struct Qdisc_ops qops;
-	struct device dev;
+	struct net_device dev;
 	struct Qdisc *slaves;
 	struct net_device_stats stats;
 	char name[IFNAMSIZ];
@@ -90,7 +90,7 @@
 static int
 teql_enqueue(struct sk_buff *skb, struct Qdisc* sch)
 {
-	struct device *dev = sch->dev;
+	struct net_device *dev = sch->dev;
 	struct teql_sched_data *q = (struct teql_sched_data *)sch->data;
 
 	__skb_queue_tail(&q->q, skb);
@@ -123,7 +123,7 @@
 
 	skb = __skb_dequeue(&dat->q);
 	if (skb == NULL) {
-		struct device *m = dat->m->dev.qdisc->dev;
+		struct net_device *m = dat->m->dev.qdisc->dev;
 		if (m) {
 			dat->m->slaves = sch;
 			spin_lock(&m->queue_lock);
@@ -187,7 +187,7 @@
 
 static int teql_qdisc_init(struct Qdisc *sch, struct rtattr *opt)
 {
-	struct device *dev = sch->dev;
+	struct net_device *dev = sch->dev;
 	struct teql_master *m = (struct teql_master*)sch->ops;
 	struct teql_sched_data *q = (struct teql_sched_data *)sch->data;
 
@@ -234,7 +234,7 @@
 /* "teql*" netdevice routines */
 
 static int
-__teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct device *dev)
+__teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device *dev)
 {
 	struct teql_sched_data *q = (void*)dev->qdisc->data;
 	struct neighbour *mn = skb->dst->neighbour;
@@ -267,7 +267,7 @@
 }
 
 static __inline__ int
-teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct device *dev)
+teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device *dev)
 {
 	if (dev->hard_header == NULL ||
 	    skb->dst == NULL ||
@@ -276,7 +276,7 @@
 	return __teql_resolve(skb, skb_res, dev);
 }
 
-static int teql_master_xmit(struct sk_buff *skb, struct device *dev)
+static int teql_master_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct teql_master *master = (void*)dev->priv;
 	struct Qdisc *start, *q;
@@ -297,7 +297,7 @@
 		goto drop;
 
 	do {
-		struct device *slave = q->dev;
+		struct net_device *slave = q->dev;
 		
 		if (slave->qdisc_sleeping != q)
 			continue;
@@ -355,7 +355,7 @@
 	return 0;
 }
 
-static int teql_master_open(struct device *dev)
+static int teql_master_open(struct net_device *dev)
 {
 	struct Qdisc * q;
 	struct teql_master *m = (void*)dev->priv;
@@ -369,7 +369,7 @@
 
 	q = m->slaves;
 	do {
-		struct device *slave = q->dev;
+		struct net_device *slave = q->dev;
 
 		if (slave == NULL)
 			return -EUNATCH;
@@ -398,19 +398,19 @@
 	return 0;
 }
 
-static int teql_master_close(struct device *dev)
+static int teql_master_close(struct net_device *dev)
 {
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
-static struct net_device_stats *teql_master_stats(struct device *dev)
+static struct net_device_stats *teql_master_stats(struct net_device *dev)
 {
 	struct teql_master *m = (void*)dev->priv;
 	return &m->stats;
 }
 
-static int teql_master_mtu(struct device *dev, int new_mtu)
+static int teql_master_mtu(struct net_device *dev, int new_mtu)
 {
 	struct teql_master *m = (void*)dev->priv;
 	struct Qdisc *q;
@@ -430,7 +430,7 @@
 	return 0;
 }
 
-static int teql_master_init(struct device *dev)
+static int teql_master_init(struct net_device *dev)
 {
 	dev->open		= teql_master_open;
 	dev->hard_start_xmit	= teql_master_xmit;
diff -u --recursive --new-file v2.3.13/linux/net/wanrouter/wanmain.c linux/net/wanrouter/wanmain.c
--- v2.3.13/linux/net/wanrouter/wanmain.c	Wed Jun  2 14:40:22 1999
+++ linux/net/wanrouter/wanmain.c	Wed Aug 18 11:38:49 1999
@@ -297,7 +297,7 @@
  */
 
 
-int wanrouter_encapsulate (struct sk_buff* skb, struct device* dev)
+int wanrouter_encapsulate (struct sk_buff* skb, struct net_device* dev)
 {
 	int hdr_len = 0;
 
@@ -339,7 +339,7 @@
  */
 
 
-unsigned short wanrouter_type_trans (struct sk_buff* skb, struct device* dev)
+unsigned short wanrouter_type_trans (struct sk_buff* skb, struct net_device* dev)
 {
 	int cnt = skb->data[0] ? 0 : 1;	/* there may be a pad present */
 	unsigned short ethertype;
@@ -515,7 +515,7 @@
  
 static int device_shutdown (wan_device_t* wandev)
 {
-	struct device* dev;
+	struct net_device* dev;
 
 	if (wandev->state == WAN_UNCONFIGURED)
 		return 0;
@@ -569,7 +569,7 @@
 static int device_new_if (wan_device_t* wandev, wanif_conf_t* u_conf)
 {
 	wanif_conf_t conf;
-	struct device* dev;
+	struct net_device* dev;
 	int err;
 
 	if ((wandev->state == WAN_UNCONFIGURED) || (wandev->new_if == NULL))
@@ -581,11 +581,11 @@
 	if (conf.magic != ROUTER_MAGIC)
 		return -EINVAL;
 		
-	dev = kmalloc(sizeof(struct device), GFP_KERNEL);
+	dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
 	if (dev == NULL)
 		return -ENOBUFS;
 		
-	memset(dev, 0, sizeof(struct device));
+	memset(dev, 0, sizeof(struct net_device));
 	err = wandev->new_if(wandev, dev, &conf);
 	if (!err)
 	{
@@ -678,7 +678,7 @@
 
 static int delete_interface (wan_device_t* wandev, char* name, int force)
 {
-	struct device *dev, *prev;
+	struct net_device *dev, *prev;
 
 	for (dev = wandev->dev, prev = NULL;
 		dev && strcmp(name, dev->name);
diff -u --recursive --new-file v2.3.13/linux/net/x25/af_x25.c linux/net/x25/af_x25.c
--- v2.3.13/linux/net/x25/af_x25.c	Thu Jul  8 15:42:21 1999
+++ linux/net/x25/af_x25.c	Wed Aug 18 11:38:49 1999
@@ -168,7 +168,7 @@
 /*
  *	Kill all bound sockets on a dropped device.
  */
-static void x25_kill_by_device(struct device *dev)
+static void x25_kill_by_device(struct net_device *dev)
 {
 	struct sock *s;
 
@@ -183,7 +183,7 @@
  */
 static int x25_device_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
-	struct device *dev = (struct device *)ptr;
+	struct net_device *dev = (struct net_device *)ptr;
 
 	if (dev->type == ARPHRD_X25
 #if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE)
@@ -589,7 +589,7 @@
 {
 	struct sock *sk = sock->sk;
 	struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr;
-	struct device *dev;
+	struct net_device *dev;
 
 	if (sk->state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
 		sock->state = SS_CONNECTED;
@@ -1179,7 +1179,7 @@
 static int x25_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
 {
 	struct sock *s;
-	struct device *dev;
+	struct net_device *dev;
 	const char *devname;
 	int len = 0;
 	off_t pos = 0;
@@ -1328,7 +1328,7 @@
 
 int init_module(void)
 {
-	struct device *dev;
+	struct net_device *dev;
 
 	x25_proto_init(NULL);
 
diff -u --recursive --new-file v2.3.13/linux/net/x25/x25_dev.c linux/net/x25/x25_dev.c
--- v2.3.13/linux/net/x25/x25_dev.c	Thu Jul  8 15:42:21 1999
+++ linux/net/x25/x25_dev.c	Wed Aug 18 11:38:49 1999
@@ -94,7 +94,7 @@
 	return 0;
 }
 
-int x25_lapb_receive_frame(struct sk_buff *skb, struct device *dev, struct packet_type *ptype)
+int x25_lapb_receive_frame(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype)
 {
 	struct x25_neigh *neigh;
 	int queued;
@@ -141,7 +141,7 @@
 	}
 }
 
-int x25_llc_receive_frame(struct sk_buff *skb, struct device *dev, struct packet_type *ptype)
+int x25_llc_receive_frame(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype)
 {
 	struct x25_neigh *neigh;
 
diff -u --recursive --new-file v2.3.13/linux/net/x25/x25_link.c linux/net/x25/x25_link.c
--- v2.3.13/linux/net/x25/x25_link.c	Sun Jul 26 23:35:58 1998
+++ linux/net/x25/x25_link.c	Wed Aug 18 11:38:49 1999
@@ -277,7 +277,7 @@
 /*
  *	Add a new device.
  */
-void x25_link_device_up(struct device *dev)
+void x25_link_device_up(struct net_device *dev)
 {
 	struct x25_neigh *x25_neigh;
 	unsigned long flags;
@@ -337,7 +337,7 @@
 /*
  *	A device has been removed, remove its links.
  */
-void x25_link_device_down(struct device *dev)
+void x25_link_device_down(struct net_device *dev)
 {
 	struct x25_neigh *neigh, *x25_neigh = x25_neigh_list;
 
@@ -353,7 +353,7 @@
 /*
  *	Given a device, return the neighbour address.
  */
-struct x25_neigh *x25_get_neigh(struct device *dev)
+struct x25_neigh *x25_get_neigh(struct net_device *dev)
 {
 	struct x25_neigh *x25_neigh;
 
@@ -371,7 +371,7 @@
 {
 	struct x25_subscrip_struct x25_subscr;
 	struct x25_neigh *x25_neigh;
-	struct device *dev;
+	struct net_device *dev;
 
 	switch (cmd) {
 
diff -u --recursive --new-file v2.3.13/linux/net/x25/x25_route.c linux/net/x25/x25_route.c
--- v2.3.13/linux/net/x25/x25_route.c	Mon Jul  7 08:20:00 1997
+++ linux/net/x25/x25_route.c	Wed Aug 18 11:38:49 1999
@@ -50,7 +50,7 @@
 /*
  *	Add a new route.
  */
-static int x25_add_route(x25_address *address, unsigned int sigdigits, struct device *dev)
+static int x25_add_route(x25_address *address, unsigned int sigdigits, struct net_device *dev)
 {
 	struct x25_route *x25_route;
 	unsigned long flags;
@@ -105,7 +105,7 @@
 	restore_flags(flags);
 }
 
-static int x25_del_route(x25_address *address, unsigned int sigdigits, struct device *dev)
+static int x25_del_route(x25_address *address, unsigned int sigdigits, struct net_device *dev)
 {
 	struct x25_route *x25_route;
 
@@ -122,7 +122,7 @@
 /*
  *	A device has been removed, remove its routes.
  */
-void x25_route_device_down(struct device *dev)
+void x25_route_device_down(struct net_device *dev)
 {
 	struct x25_route *route, *x25_route = x25_route_list;
 
@@ -138,9 +138,9 @@
 /*
  *	Check that the device given is a valid X.25 interface that is "up".
  */
-struct device *x25_dev_get(char *devname)
+struct net_device *x25_dev_get(char *devname)
 {
-	struct device *dev;
+	struct net_device *dev;
 
 	if ((dev = dev_get(devname)) == NULL)
 		return NULL;
@@ -158,7 +158,7 @@
 /*
  *	Find a device given an X.25 address.
  */
-struct device *x25_get_route(x25_address *addr)
+struct net_device *x25_get_route(x25_address *addr)
 {
 	struct x25_route *route, *use = NULL;
 
@@ -182,7 +182,7 @@
 int x25_route_ioctl(unsigned int cmd, void *arg)
 {
 	struct x25_route_struct x25_route;
-	struct device *dev;
+	struct net_device *dev;
 
 	switch (cmd) {
 
